File template-glib-3.38.0.obscpio of Package template-glib
07070100000000000081A400000000000000000000000168C4C09600000006000000000000000000000000000000000000002000000000template-glib-3.38.0/.gitignorebuild
07070100000001000081A400000000000000000000000168C4C09600000171000000000000000000000000000000000000002400000000template-glib-3.38.0/.gitlab-ci.ymlinclude:
- project: "GNOME/citemplates"
file: "templates/default-rules.yml"
- component: gitlab.gnome.org/GNOME/citemplates/gnomeos-basic-ci@master
- component: gitlab.gnome.org/GNOME/citemplates/release-service@master
inputs:
dist-job-name: "build-gnomeos"
tarball-artifact-path: "_builddir/meson-dist/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.xz"
07070100000002000081A400000000000000000000000168C4C09600000138000000000000000000000000000000000000002500000000template-glib-3.38.0/CONTRIBUTING.md# Contributing to Template-GLib
This project is very new.
Take a look around and see if there is anything you'd like to work on.
Report bugs to me any way you know how.
Email, github, bugzilla (in gnome-builder project), etc.
## Coding Style
We follow the GLib and GTK coding style, which is roughly GNU C11.
07070100000003000081A400000000000000000000000168C4C096000067A2000000000000000000000000000000000000001D00000000template-glib-3.38.0/COPYING GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
07070100000004000081A400000000000000000000000168C4C096000011A5000000000000000000000000000000000000001A00000000template-glib-3.38.0/NEWS==============
Version 3.38.0
==============
This is a stable release for GNOME 49.0
* Allow GObject Introspection to automatically cast various numerics into
the arguments of a call-site when the will fit in the destination type
and size.
* Use gi-doc for documentation.
==============
Version 3.37.1
==============
Release for GNOME 49 Beta
* Add `.mangle()` for strings to make it simpler to convert
ClassName to class_name.
* Fix calls to a function in a GIRepository like GLib.strsplit
* Add support for GStrv in GI parameter types
* Allow comparing GStrv for == and != comparison
* Fix handling for null branches
==============
Version 3.37.0
==============
Release for GNOME 49 Alpha
• Port to libgirepository-2.0
• Improve testsuite for ASAN/LSAN findings
==============
Version 3.36.3
==============
Changes in this release:
• Translation updates
==============
Version 3.36.2
==============
This release contains bug fixes only
• Fix trace level define
• Fix unused dlfcn.h include
==============
Version 3.36.1
==============
This release contains important fixes suggested for distribution to end users.
• Fix leak of GObject Introspection interface info
• Document usage of package_subdir
• Translation updates
==============
Version 3.36.0
==============
This release corresponds with GNOME 43.0
No changes since 3.35.0
==============
Version 3.35.0
==============
This is a development release, not intended for end users.
Changes in this release:
• Build system improvements and test suites
• Many fixes to TmplExpr lexing, parsing, and evaluation
• A number of new AST nodes and symbo API
• Various new builtin functions
• Improved support for swallowing newlines from templates
==============
Version 3.34.1
==============
Changes in this release:
• Translation updates
==============
Version 3.34.0
==============
No changes since 3.33.92.
===============
Version 3.33.92
===============
Changes in this release:
• Updated meson build requirement
• Build fixes for macOS
• Translation updates
==============
Version 3.32.0
==============
Changes in this release:
• Translation updates
===============
Version 3.31.91
===============
Changes in this release:
• Improve cross-compilation support.
==============
Version 3.30.0
==============
Changes in this release:
• Documentation fixes
• Check {{include}} for valid path
• Various G-I fixes
==============
Version 3.28.0
==============
No changes since 3.27.90.
===============
Version 3.27.90
===============
Changes in this release:
• Allow iteration of string arrays (GStrv)
==============
Version 3.27.2
==============
Changes in this release:
• A number of imporovements to the template locator.
• Support for more gobject introspection API calls.
• You can know use typeof(expr) to get the GType of the result
of the expression.
• The token stream tries harder to supress newlines.
• require/version expression priority is now lower
• Some memory leaks were plugged
• Versioning of symbols is now down with export macros to be
more portable for alternative platforms.
• We now explicity require a modern C standard.
Updated Translations:
German, Slovenian
==============
Version 3.26.0
==============
Changes in this release:
• Don't store build dir in generated files to help with
build reproducibility.
===============
Version 3.25.92
===============
Changes in this release:
• Use LGPLv2.1+ consistently
• Fix unused variable in eval
• Check for version-script support by the linker
• Bump to more recent meson dependency
Updated Translations:
Hungarian, Spanish, Indonesian, Czech, Slovenian, Brazilian, Serbian
==============
Version 3.25.3
==============
Changes
• Add support for gtk-doc based documentation.
• Add support for using template-glib as a Meson subproject.
Updated Translations:
• Swedish
==============
Version 3.25.2
==============
This is the first release of template-glib.
Template-GLib is a small templating library for GLib based applications. It
supports a fairly simple scripting style for templates as well as integration
with GObject Introspection. This allows templates to be created that need to
iterate through data found in real GObjects.
Currently, Template-GLib is used by the GNOME Builder project for project
templates, but we think it could be useful to other projects as well.
Thanks!
07070100000005000081A400000000000000000000000168C4C09600000D4B000000000000000000000000000000000000001F00000000template-glib-3.38.0/README.md# Template-GLib
Template-GLib is a library to help you generate text based on a template and
user defined state. Template-GLib does not use a language runtime, so it is
safe to use from any GObject-Introspectable language.
Template-GLib allows you to access properties on GObjects as well as call
simple methods via GObject-Introspection. See our examples for how to call
methods.
## Authors
* Christian Hergert <chergert@redhat.com>
## Examples
See `examples/` for more detailed examples.
The following is contrived to show you the versatility of the syntax.
Template expressions and blocks are defined inside of {{ and }}.
```tmpl
{{if (foo.bar)*10/30.0+1 != foo.baz()}}
{{for item in foo.list}}
{{item.foo}}
{{end}}
{{else if x > 10}}
bar
{{else}}
foo
{{end}}
```
### Includes
* `{{include "path-to-template.tmpl"}}`
### Conditionals
* `{{if <expression>}}`
* `{{else if <expression>}}`
* `{{else <expression>}}`
* `{{for <identifier> in <expression>}}`
`if` and `for` should have a closing `{{end}}`
### Expressions
Expressions are parsed using a formal grammer, which you can find in the
flex and bison files at `src/tmpl-expr-scanner.l` and `tmpl-expr-parser.y`
respectively.
All numbers are currently represented as double-precision floating point.
This may change in the near future.
These can be used inside of {{ and }} to be evaluated. They can also be used
as expressions using the above conditional blocks.
```
true => true
false => false
" " => " "
" " * 3 => " "
1 + 3 => 4
1 - 3 => -2
1 * 3 => 3
1 / 3 => .333333
a = (1*3) => (a assigned 3)
a * a => 9
!true => false
!!true => true
func min(a,b) = if a < b then a; else b;;
min(1,2) => 1
obj.foo => (Gets GObject property "foo")
obj.foo=1 => (Sets GObject property "foo")
obj.foo() => (Calls foo() on obj, via GObject Introspection)
# Note that we do not yet have support for accessing
# children of the Typelib. That is coming.
require Gtk => (GITypelib of Gtk)
require Gtk version "3.0" => (GITypelib of Gtk, requiring 3.0)
```
### Template Loading
See `TmplTemplateLoader` to control the lookup of included templates.
You probably want to do this if you are using this in something like a
webserver. By default, the search path is empty, and will not allow
including external resources.
Search paths will not allow loading templates above the search path entry.
### Scope
You can assign state into the template using `TmplScope`.
```c
/* scope can be inherited, by passing a parent instead of NULL */
TmplScope *scope = tmpl_scope_new (NULL);
TmplSymbol *symbol = tmpl_scope_get (scope, "foo");
tmpl_symbol_assign_boolean (symbol, TRUE);
tmpl_symbol_assign_double (symbol, 123.4);
tmpl_symbol_assign_string (symbol, "foo");
tmpl_symbol_assign_object (symbol, g_object_new (MY_TYPE_FOO, NULL));
/* or if you can assign via a GValue */
GValue value = G_VALUE_INIT;
g_value_set_boxed (&value, my_boxed);
tmpl_symbol_assign_value (symbol, &value);
g_value_unset (&value);
```
## Contributing
See CONTRIBUTING.md for information on how you can contribute.
07070100000006000041ED00000000000000000000000268C4C09600000000000000000000000000000000000000000000001900000000template-glib-3.38.0/doc07070100000007000081A400000000000000000000000168C4C09600000404000000000000000000000000000000000000002500000000template-glib-3.38.0/doc/meson.buildif not get_option('introspection').allowed()
error('API reference requires introspection.')
endif
toml_conf = configuration_data()
toml_conf.set('version', meson.project_version())
gidocgen = find_program('gi-docgen')
gidocgen_common_args = [
'--quiet',
'--no-namespace-dir',
]
if get_option('werror')
gidocgen_common_args += ['--fatal-warnings']
endif
docs_dir = get_option('datadir') / 'doc'
source_toml = configure_file(
input: 'template-glib.toml.in',
output: 'template-glib.toml',
configuration: toml_conf,
install: true,
install_dir: docs_dir / 'template-glib-@0@'.format(apiversion),
)
custom_target('template-glib-doc',
input: [ source_toml, libtemplate_glib_gir[0] ],
output: 'template-glib-@0@'.format(apiversion),
command: [
gidocgen,
'generate',
gidocgen_common_args,
'--config=@INPUT0@',
'--output-dir=@OUTPUT@',
'--content-dir=@0@'.format(meson.current_source_dir()),
'@INPUT1@',
],
build_by_default: true,
install: true,
install_dir: docs_dir,
)
07070100000008000081A400000000000000000000000168C4C096000000C3000000000000000000000000000000000000002500000000template-glib-3.38.0/doc/overview.mdTitle: Overview
Template-GLib is a library that provides simple templating for GLib-based
applications. It supports GObject Introspection to allow templates to call
back into application code.
07070100000009000081A400000000000000000000000168C4C096000003A4000000000000000000000000000000000000002F00000000template-glib-3.38.0/doc/template-glib.toml.in[library]
version = "@version@"
browse_url = ""
repository_url = ""
website_url = ""
docs_url = ""
authors = "Christian Hergert"
license = "LGPL-2.1-or-later"
description = "A templating library for GLib applications"
dependencies = ["Gio-2.0"]
devhelp = true
search_index = true
[dependencies."GObject-2.0"]
name = "GObject"
description = "The base type system library"
docs_url = "https://docs.gtk.org/gobject/"
[dependencies."GLib-2.0"]
name = "GLib"
description = "The base type system library"
docs_url = "https://docs.gtk.org/glib/"
[dependencies."Gio-2.0"]
name = "GIO"
description = "GObject Interfaces and Objects, Networking, IPC, and I/O"
docs_url = "https://docs.gtk.org/gio/"
[theme]
name = "basic"
show_index_summary = true
show_class_hierarchy = true
[source-location]
base_url = ""
[extra]
# The same order will be used when generating the index
content_files = [
"overview.md",
]
urlmap_file = "urlmap.js"
0707010000000A000081A400000000000000000000000168C4C096000000E6000000000000000000000000000000000000002300000000template-glib-3.38.0/doc/urlmap.js// A map between namespaces and base URLs for their online documentation
baseURLs = [
[ 'GLib', 'https://docs.gtk.org/glib/' ],
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
[ 'Gio', 'https://docs.gtk.org/gio/' ],
]
0707010000000B000041ED00000000000000000000000268C4C09600000000000000000000000000000000000000000000001E00000000template-glib-3.38.0/examples0707010000000C000081A400000000000000000000000168C4C09600000191000000000000000000000000000000000000002B00000000template-glib-3.38.0/examples/article.tmpl<!--
this assumes you have an article GObject in scope
with the properties title, author, sections and data.
content is a GListModel of paragraphs.
-->
<html>
<head>
<title>{{article.title}}</title>
</head>
<body>
<h1>{{article.title}}</h1>
<div>By {{article.author}} on {{article.date}}</div>
{{for section in article.sections}}
<div>{{section}}</div>
{{end}}
</body>
</html>
0707010000000D000081A400000000000000000000000168C4C09600000359000000000000000000000000000000000000002B00000000template-glib-3.38.0/examples/article.valausing GLib;
using Template;
class Article : Object {
public string title {
get { return "Sample Article"; }
}
public string author {
get { return Environment.get_user_name(); }
}
private string _date = (new DateTime.now_local()).to_string();
public string date {
get { return _date; }
}
private string[] _sections = {"Iterate", "over", "strv"};
public string[] sections {
get { return _sections; }
}
}
static int main (string[] args) {
var file = GLib.File.new_for_path("article.tmpl");
var tmpl = new Template.Template (null);
try {
tmpl.parse_file (file, null);
var scope = new Template.Scope ();
scope["article"].assign_object(new Article());
var expanded = tmpl.expand_string (scope);
stdout.printf ("%s\n", expanded);
} catch (GLib.Error ex) {
stderr.printf ("%s\n", ex.message);
return 1;
}
return 0;
}
0707010000000E000081A400000000000000000000000168C4C096000001E7000000000000000000000000000000000000002F00000000template-glib-3.38.0/examples/simple-vala.valausing GLib;
using Template;
static int main (string[] argv)
{
var file = GLib.File.new_for_path("simple.tmpl");
var tmpl = new Template.Template (null);
try {
tmpl.parse_file (file, null);
var scope = new Template.Scope ();
var title = scope.get ("title");
title.assign_string ("Example Title");
var expanded = tmpl.expand_string (scope);
stdout.printf ("%s\n", expanded);
} catch (GLib.Error ex) {
stderr.printf ("%s\n", ex.message);
return 1;
}
return 0;
}
0707010000000F000081A400000000000000000000000168C4C09600000526000000000000000000000000000000000000002700000000template-glib-3.38.0/examples/simple.c#include <tmpl-glib.h>
#include <stdlib.h>
gint
main (gint argc,
gchar *argv[])
{
g_autoptr(GFile) file = NULL;
g_autoptr(TmplScope) scope = NULL;
g_autoptr(TmplTemplate) tmpl = NULL;
g_autoptr(GError) error = NULL;
TmplSymbol *symbol = NULL;
gchar *str;
/*
* First we need to create and parse our template.
* The template can be expanded multiple times, so you can
* keep them around and re-use them.
*/
file = g_file_new_for_path ("simple.tmpl");
tmpl = tmpl_template_new (NULL);
if (!tmpl_template_parse_file (tmpl, file, NULL, &error))
{
g_printerr ("%s\n", error->message);
return EXIT_FAILURE;
}
/*
* Now create our scope used to expand the template,
* and assign the "title" variable in the scope.
*/
scope = tmpl_scope_new ();
symbol = tmpl_scope_get (scope, "title");
tmpl_symbol_assign_string (symbol, "My Title");
/*
* Expand the template based on our scope. You can also expand into a
* GOutputStream, instead of a string.
*/
if (!(str = tmpl_template_expand_string (tmpl, scope, &error)))
{
g_printerr ("%s\n", error->message);
return EXIT_FAILURE;
}
g_print ("%s\n", str);
g_free (str);
/*
* All our state gets cleaned up thanks to g_autoptr()!
*/
return EXIT_SUCCESS;
}
07070100000010000081A400000000000000000000000168C4C0960000025E000000000000000000000000000000000000002800000000template-glib-3.38.0/examples/simple.jsconst Template = imports.gi.Template;
const Gio = imports.gi.Gio;
// Get our file to process
let file = Gio.File.new_for_path("simple.tmpl");
// Create a new template and parse our input file
let tmpl = new Template.Template();
tmpl.parse_file(file, null);
// Create scope for expansion
let scope = Template.Scope.new ();
// Create and assign "title" variable in scope
let title = scope.get("title");
title.assign_string("Example Title");
// Write to stdout
let stream = Gio.UnixOutputStream.new (0, false);
// Expand the template into stream
let expanded = tmpl.expand_string(scope);
log(expanded);
07070100000011000081ED00000000000000000000000168C4C0960000023D000000000000000000000000000000000000002800000000template-glib-3.38.0/examples/simple.py#!/usr/bin/env python3
import gi
gi.require_version('Template', '1.0')
from gi.repository import Gio
from gi.repository import Template
# Get our file to process
file = Gio.File.new_for_path('simple.tmpl')
# Create a new template and parse our input file
tmpl = Template.Template()
tmpl.parse_file(file, None)
# Create scope for expansion
scope = Template.Scope.new()
# Create and assign "title" variable in scope
title = scope.get('title')
title.assign_string('Example Title')
# Expand the template into stream
expanded = tmpl.expand_string(scope)
print(expanded)
07070100000012000081A400000000000000000000000168C4C096000000A2000000000000000000000000000000000000002A00000000template-glib-3.38.0/examples/simple.tmpl<html>
<head>
<title>{{title="Example Page"}}</title>
</head>
<body>
{{if title}}
<h1>{{title}}</h1>
{{else}}
<h1>Untitled</h1>
{{end}}
</body>
</html>
07070100000013000081A400000000000000000000000168C4C09600001017000000000000000000000000000000000000002100000000template-glib-3.38.0/meson.buildproject('template-glib', 'c',
version: '3.38.0',
license: 'LGPLv2.1+',
meson_version: '>= 0.51.0',
default_options: [ 'warning_level=2', 'buildtype=debugoptimized', 'c_std=gnu11' ],
)
package_subdir = get_option('package_subdir')
if meson.is_subproject() and package_subdir == ''
error('-Dpackage_subdir must be set when using @0@ as a subproject'.format(meson.project_name()))
endif
version_arr = meson.project_version().split('.')
template_glib_version_major = version_arr[0].to_int()
template_glib_version_minor = version_arr[1].to_int()
template_glib_version_micro = version_arr[2].to_int()
apiversion = '1.0'
soversion = 0
if template_glib_version_minor.is_odd()
template_glib_interface_age = 0
else
template_glib_interface_age = template_glib_version_micro
endif
# maintaining compatibility with the previous libtool versioning
# current = minor * 100 + micro - interface
# revision = interface
current = template_glib_version_minor * 100 + template_glib_version_micro - template_glib_interface_age
revision = template_glib_interface_age
libversion = '@0@.@1@.@2@'.format(soversion, current, revision)
darwin_versions = [current + 1, '@0@.@1@'.format(current + 1, revision)]
config_h = configuration_data()
config_h.set_quoted('GETTEXT_PACKAGE', 'libtemplate_glib')
config_h.set_quoted('LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir')))
cc = meson.get_compiler('c')
release_args = []
global_link_args = []
test_link_args = [
'-Wl,-z,relro',
'-Wl,-z,now',
]
if not get_option('buildtype').startswith('debug')
add_project_arguments(['-DG_DISABLE_CAST_CHECKS'], language: 'c')
release_args += [ '-DG_DISABLE_ASSERT' ]
test_link_args += [
'-Wl,-Bsymbolic',
'-fno-plt',
]
endif
foreach link_arg: test_link_args
if cc.links('int main () { return 0; }', name: link_arg, args: link_arg)
global_link_args += link_arg
endif
endforeach
add_project_link_arguments(global_link_args, language: 'c')
configure_file(
output: 'config.h',
configuration: config_h,
)
cc = meson.get_compiler('c')
global_c_args = []
test_c_args = [
'-Wcast-align',
'-Wdeclaration-after-statement',
'-Wformat-nonliteral',
'-Wformat-security',
'-Wmissing-include-dirs',
'-Wnested-externs',
'-Wno-missing-field-initializers',
'-Wno-sign-compare',
'-Wno-unused-parameter',
'-Wpointer-arith',
'-Wredundant-decls',
'-Wswitch-default',
'-Wswitch-enum',
'-Wuninitialized',
['-Werror=format-security', '-Werror=format=2' ],
'-Werror=empty-body',
'-Werror=implicit-function-declaration',
'-Werror=incompatible-pointer-types',
'-Werror=pointer-arith',
'-Werror=init-self',
'-Werror=int-conversion',
'-Werror=misleading-indentation',
'-Werror=missing-include-dirs',
'-Werror=overflow',
'-Werror=parenthesis',
'-Werror=return-type',
'-Werror=shadow',
'-Werror=strict-prototypes',
'-Werror=undef',
]
if get_option('buildtype') != 'plain'
test_c_args += '-fstack-protector-strong'
endif
if get_option('profiling')
test_c_args += '-pg'
endif
foreach arg: test_c_args
if cc.has_multi_arguments(arg)
global_c_args += arg
endif
endforeach
add_project_arguments(
global_c_args,
language: 'c'
)
# Setup various paths that subdirectory meson.build files need
libdir = join_paths(get_option('libdir'), package_subdir)
includedir = join_paths(get_option('includedir'), package_subdir)
girdir = join_paths(get_option('datadir'), package_subdir, 'gir-1.0')
typelibdir = join_paths(get_option('libdir'), package_subdir, 'girepository-1.0')
if package_subdir == ''
vapidir = join_paths(get_option('datadir'), 'vala', 'vapi')
else
vapidir = join_paths(get_option('datadir'), package_subdir, 'vapi')
endif
gnome = import('gnome')
i18n = import('i18n')
gir = find_program('g-ir-scanner', required: get_option('introspection'))
generate_gir = gir.found() and (not meson.is_cross_build() or get_option('introspection').enabled())
generate_vapi = generate_gir and get_option('vapi')
subdir('src')
subdir('po')
if get_option('tests')
subdir('tests')
endif
if get_option('docs')
subdir('doc')
endif
07070100000014000081A400000000000000000000000168C4C09600000373000000000000000000000000000000000000002700000000template-glib-3.38.0/meson_options.txt# Performance and debugging related options
option('tracing', type: 'boolean', value: false)
option('profiling', type: 'boolean', value: false)
# Support for multiple languages
option('introspection', type: 'feature', value: 'auto')
option('vapi', type: 'boolean', value: true)
# For subproject usage.
#
# If this is a subproject and you want the installed files to be private
# that means you can set package_subdir=gnome-builder and install them in
# someplace like:
#
# /usr/lib/gnome-builder/libtemplate_glib-1.0.so
# /usr/lib/girepository-1.0/gnome-builder/TemplateGLib-1.0.typelib
option('package_subdir', type: 'string',
description: 'Private sub-directory used when built as a subproject'
)
option('docs',
type: 'boolean', value: false,
description: 'Whether to generate the API reference for Template-GLib')
option('tests', type: 'boolean', value: true)
07070100000015000041ED00000000000000000000000268C4C09600000000000000000000000000000000000000000000001800000000template-glib-3.38.0/po07070100000016000081A400000000000000000000000168C4C09600000098000000000000000000000000000000000000002000000000template-glib-3.38.0/po/LINGUAS# please keep this list sorted alphabetically
#
ar
ca
cs
da
de
el
en_GB
es
eu
fr
fur
hi
hr
hu
id
it
ka
kab
lt
nl
pl
pt
pt_BR
ro
ru
sl
sr
sv
tr
uk
zh_CN
07070100000017000081A400000000000000000000000168C4C096000000A9000000000000000000000000000000000000002400000000template-glib-3.38.0/po/POTFILES.in# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
src/tmpl-parser.c
src/tmpl-template.c
src/tmpl-template-locator.c
07070100000018000081A400000000000000000000000168C4C0960000050C000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/ar.po# Arabic translation for template-glib.
# Copyright (C) 2025 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Ahmed Najmawi <iramosu@protonmail.com>, 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib main\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2025-05-29 18:42+0000\n"
"PO-Revision-Date: 2025-06-08 16:11+0300\n"
"Last-Translator: Ahmed Najmawi <iramosu@protonmail.com>\n"
"Language-Team: Arabic <Arabic>\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.5\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "لا يمكن استدعاء %s() إلا مرة واحدة"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "لا يحتوي المحلِّل على تدفق دَخْل"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "يجب تحليل القالب قبل توسيعه"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "تعذَّر العثور على القالب «%s»"
07070100000019000081A400000000000000000000000168C4C096000004EF000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/ca.po# Catalan translation for template-glib.
# Copyright (C) 2021 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# maite <maite.guix@gmail.com>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib template-glib-3-32\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2021-09-17 14:30+0000\n"
"PO-Revision-Date: 2021-11-01 17:45+0100\n"
"Language-Team: Catalan <gnome@llistes.softcatala.org>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: maite guix <maite.guix@me.com>\n"
"X-Generator: Poedit 3.0\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() només es pot trucar una vegada"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "L'analitzador no conté cap flux d'entrada"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "S'ha d'analitzar la plantilla abans d'expandir-la"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "No s'ha pogut localitzar la plantilla «%s»"
0707010000001A000081A400000000000000000000000168C4C09600000552000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/cs.po# Czech translation for template-glib.
# Copyright (C) 2016 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
#
# Marek Černocký <marek@manet.cz>, 2016, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-05 10:48+0000\n"
"PO-Revision-Date: 2017-06-25 12:10+0200\n"
"Last-Translator: Marek Černocký <marek@manet.cz>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Gtranslator 2.91.7\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "Funkce %s() může být zavolána jen jednou"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "Ve zpracování není žádný datový proud"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Před rozbalením je šablonu nutné zpracovat"
#: src/tmpl-template-locator.c:105
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Selhalo vyhledání šablony „%s“"
0707010000001B000081A400000000000000000000000168C4C09600000496000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/da.po# Danish translation for template-glib.
# Copyright (C) 2019 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# scootergrisen, 2019.
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2019-02-07 02:09+0000\n"
"PO-Revision-Date: 2019-02-20 00:00+0200\n"
"Last-Translator: scootergrisen\n"
"Language-Team: Danish\n"
"Language: da\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() må kun kaldes én gang"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Fortolker indeholder ikke en inputstrøm"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Skal fortolke skabelon inden udvidelse"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Kunne ikke finde skabelonen “%s”"
0707010000001C000081A400000000000000000000000168C4C09600000552000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/de.po# German translation for template-glib.
# Copyright (C) 2016 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Mario Blättermann <mario.blaettermann@gmail.com>, 2016-2017.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-27 22:39+0000\n"
"PO-Revision-Date: 2017-10-02 11:28+0200\n"
"Last-Translator: Mario Blättermann <mario.blaettermann@gmail.com>\n"
"Language-Team: German <gnome-de@gnome.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.0.3\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() darf nur einmal aufgerufen werden"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "Parser enthält keinen Eingabe-Datenstrom"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Vorlage muss vor dem Erweitern verarbeitet werden"
#: src/tmpl-template-locator.c:105
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Vorlage »%s« konnte nicht gefunden werden"
0707010000001D000081A400000000000000000000000168C4C096000005DA000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/el.po# Greek translation for template-glib.
# Copyright (C) 2016 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Γιάννης Κουτσούκος <giankoyt@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=template-glib&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2016-03-22 03:03+0000\n"
"PO-Revision-Date: 2016-03-22 12:02+0200\n"
"Last-Translator: Yannis Koutsoukos <giankoyt@gmail.com>\n"
"Language-Team: Greek <gnome-el-list@gnome.org>\n"
"Language: el\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.5.4\n"
#: ../src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() μπορεί να κληθεί μόνο μία φορά"
#: ../src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "O αναλυτής δεν περιέχει ροή εισόδου"
#: ../src/tmpl-template.c:451
#, c-format
msgid "Must parse template before expanding"
msgstr "Πρέπει να αναλύσει το πρότυπο πριν από την επέκταση"
#: ../src/tmpl-template-locator.c:105
#, c-format
msgid "Failed to locate template \"%s\""
msgstr "Αποτυχία εντοπισμού προτύπου \"%s\" "
0707010000001E000081A400000000000000000000000168C4C09600000508000000000000000000000000000000000000002100000000template-glib-3.38.0/po/en_GB.po# British English translation for template-glib.
# Copyright (C) 2019 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Zander Brown <zbrown@gnome.org>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2019-03-13 18:34+0000\n"
"PO-Revision-Date: 2019-08-26 00:34+0100\n"
"Last-Translator: Zander Brown <zbrown@gnome.org>\n"
"Language-Team: English - United Kingdom <en_GB@li.org>\n"
"Language: en_GB\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 3.32.1\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() may only be called once"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Parser does not contain an input stream"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Must parse template before expanding"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Failed to locate template “%s”"
0707010000001F000081A400000000000000000000000168C4C0960000057E000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/es.po# Spanish translation for template-glib.
# Copyright (C) 2016 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Daniel Mustieles <daniel.mustieles@gmail.com>, 2016, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-05 10:48+0000\n"
"PO-Revision-Date: 2017-06-20 13:54+0200\n"
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
"Language-Team: es <gnome-es-list@gnome.org>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 2.91.6\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "Sólo se puede llamar una vez a %s()"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "El analizador no contiene ningún flujo de entrada"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Se debe analizar la plantilla antes de expandirla"
#: src/tmpl-template-locator.c:105
#, c-format
#| msgid "Failed to locate template \"%s\""
msgid "Failed to locate template “%s”"
msgstr "Falló a buscar la plantilla «%s»"
07070100000020000081A400000000000000000000000168C4C096000004E4000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/eu.po# Basque translation for template-glib.
# Copyright (C) 2019 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Asier Sarasua Garmendia <asier.sarasua@gmail.com>, 2019.
#
msgid ""
msgstr "Project-Id-Version: template-glib template-glib-3-32\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2019-09-20 17:16+0000\n"
"PO-Revision-Date: 2019-09-24 10:00+0100\n"
"Last-Translator: Asier Sarasua Garmendia <asier.sarasua@gmail.com>\n"
"Language-Team: Basque <librezale@librezale.eus>\n"
"Language: eu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() behin soilik deitu daiteke"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Analizatzaileak ez dauka sarrerako korronterik"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Txantiloia analizatu behar da hedatu baino lehen"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Ez da aurkitu “%s” txantiloia"
07070100000021000081A400000000000000000000000168C4C09600000559000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/fr.po# French translation for template-glib.
# Copyright (C) 2021 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Thibault Leclair <thibaultleclair@yahoo.com>, 2021-2022.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib template-glib-3-32\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2021-09-17 14:30+0000\n"
"PO-Revision-Date: 2022-02-21 22:22+0100\n"
"Last-Translator: Thibault Leclair <thibaultleclair@yahoo.com>\n"
"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Gtranslator 40.0\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() doit être appelé seulement une fois"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "L’analyseur ne reçoit pas de flux d’entrée"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Il est nécessaire d’analyser le modèle avant expansion"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Impossible de trouver le modèle « %s »"
07070100000022000081A400000000000000000000000168C4C09600000527000000000000000000000000000000000000001F00000000template-glib-3.38.0/po/fur.po# Friulian translation for template-glib.
# Copyright (C) 2017 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Fabio Tomat <f.t.public@gmail.com>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?"
"product=template-glib&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2017-04-08 15:34+0000\n"
"PO-Revision-Date: 2017-04-08 21:41+0200\n"
"Language-Team: Friulian <fur@li.org>\n"
"Language: fur\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
"X-Generator: Poedit 1.8.12\n"
#: ../src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() al pues jessi clamât dome une volte"
#: ../src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "L'analizadôr nol conten nissun flus di jentrade"
#: ../src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Prime di espandi la sagome si scugne analizâle"
#: ../src/tmpl-template-locator.c:105
#, c-format
msgid "Failed to locate template \"%s\""
msgstr "no si è rivâts a cjatâ la sagome “%s”"
07070100000023000081A400000000000000000000000168C4C096000005E4000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/hi.po# Hindi translation for template-glib.
# Copyright (C) 2024 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Scrambled777 <weblate.scrambled777@simplelogin.com>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib main\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2024-03-18 21:22+0000\n"
"PO-Revision-Date: 2024-04-01 23:41+0530\n"
"Last-Translator: Scrambled777 <weblate.scrambled777@simplelogin.com>\n"
"Language-Team: Hindi\n"
"Language: hi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Gtranslator 46.0\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() को केवल एक बार ही बुलाया जा सकता है"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "पार्सर में कोई इनपुट स्ट्रीम नहीं है"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "विस्तार करने से पहले खाका को पार्स करना होगा"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "खाका “%s” ढूँढने में विफल"
07070100000024000081A400000000000000000000000168C4C0960000053B000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/hr.po# Croatian translation for template-glib.
# Copyright (C) 2020 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2020-09-06 14:08+0000\n"
"PO-Revision-Date: 2020-09-13 18:45+0200\n"
"Language-Team: Croatian <hr@li.org>\n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"Last-Translator: gogo <trebelnik2@gmail.com>\n"
"X-Generator: Poedit 2.3\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() se može pozvati samo jednom"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Obrađivač ne sadrži ulazno strujanje"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Predložak se mora obraditi prije proširivanja"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Neuspjelo lociranje predloška “%s”"
07070100000025000081A400000000000000000000000168C4C09600000571000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/hu.po# Hungarian translation for template-glib.
# Copyright (C) 2016 Free Software Foundation, Inc.
# This file is distributed under the same license as the template-glib package.
#
# Balázs Úr <urbalazs@gmail.com>, 2016, 2017.
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-27 22:39+0000\n"
"PO-Revision-Date: 2017-09-05 17:55+0200\n"
"Last-Translator: Balázs Úr <urbalazs@gmail.com>\n"
"Language-Team: Hungarian <gnome-hu-list@gnome.org>\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 1.2\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "A(z) %s() csak egyszer hívható meg"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "A feldolgozó nem tartalmaz bemeneti adatfolyamot"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Fel kell dolgozni a sablont a kibővítés előtt"
#: src/tmpl-template-locator.c:105
#, c-format
#| msgid "Failed to locate template \"%s\""
msgid "Failed to locate template “%s”"
msgstr "Nem sikerült megtalálni a(z) „%s” sablont"
07070100000026000081A400000000000000000000000168C4C09600000509000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/id.po# Indonesian translation for template-glib.
# Copyright (C) 2017 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Andika Triwidada <atriwidada@gnome.org>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-05 10:48+0000\n"
"PO-Revision-Date: 2017-06-18 14:37+0700\n"
"Last-Translator: Kukuh Syafaat <syafaatkukuh@gmail.com>\n"
"Language-Team: Indonesian <gnome-l10n-id@googlegroups.com>\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.11\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() hanya boleh dipanggil sekali"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "Pengurai tidak mengandung suatu stream masukan"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Mesti mengurai templat sebelum memperluas"
#: src/tmpl-template-locator.c:105
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Gagal menemukan templat \"%s\""
07070100000027000081A400000000000000000000000168C4C09600000526000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/it.po# Italian translation for template-glib.
# Copyright (C) 2018 Free Software Foundation, Inc.
# This file is distributed under the same license as the template-glib package.
# Milo Casagrande <milo@milo.name>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib template-glib-3-28\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2018-03-14 17:03+0000\n"
"PO-Revision-Date: 2018-11-21 14:20+0100\n"
"Language-Team: Italian <gnome-it-list@gnome.org>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Last-Translator: Milo Casagrande <milo@milo.name>\n"
"X-Generator: Poedit 2.1.1\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() può essere chiamata solo una volta"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "L'analizzatore non contiene uno stream di input"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Necessario analizzare il modello prima dell'espansione"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Impossibile trovare il modello «%s»"
07070100000028000081A400000000000000000000000168C4C096000005D0000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/ka.po# Georgian translation for template-glib.
# Copyright (C) 2022 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# NorwayFun <temuri.doghonadze@gmail.com>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib main\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2022-11-02 06:11+0000\n"
"PO-Revision-Date: 2022-11-20 19:04+0100\n"
"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
"Language-Team: Georgian <ka@li.org>\n"
"Language: ka\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.2\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() მხოლოდ ერთხელ შეგიძლიათ გამოიძახოთ"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "დამმუშავებელი შეყვანის ნაკადს არ შეიცავს"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "გაფართოებამდე შაბლონის დამუშავება აუცილებელია"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "შაბლონი \"%s\" ვერ ვიპოვე"
07070100000029000081A400000000000000000000000168C4C09600000509000000000000000000000000000000000000001F00000000template-glib-3.38.0/po/kab.po# Kabyle translation for template-glib
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
# This file is distributed under the same license as the template-glib package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2022-08-03 23:44+0000\n"
"PO-Revision-Date: 2020-03-10 16:21+0000\n"
"Last-Translator: tasutlelli17 <Unknown>\n"
"Language-Team: Kabyle <kab@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2022-08-25 22:52+0000\n"
"X-Generator: Launchpad (build 813bec7783fe35df624c0e68cd38fcaa442fb8d1)\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() ala yiwet n tikkelt i yezmer ad d-yettusawel"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Amaslaḍ ur yesɛi ara asuddem n unekcum"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Ilaq ad tettusleḍ tneɣrfut uqbel asennerni"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "D awezɣi ad d-tettussideg tneɣruft \"%s\""
0707010000002A000081A400000000000000000000000168C4C09600000557000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/lt.po# Lithuanian translation for template-glib.
# Copyright (C) 2021 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Aurimas Černius <aurisc4@gmail.com>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2021-08-28 14:07+0000\n"
"PO-Revision-Date: 2021-09-06 14:25+0300\n"
"Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
"Language: lt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
"%100<10 || n%100>=20) ? 1 : 2)\n"
"X-Generator: Gtranslator 40.0\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() galima kviesti tik vieną kartą"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Analizatorius neturi įvesties srauto"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Būtina išanalizuoti šabloną prieš išplečiant"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Nepavyko rasti šablono „%s“"
0707010000002B000081A400000000000000000000000168C4C09600000033000000000000000000000000000000000000002400000000template-glib-3.38.0/po/meson.buildi18n.gettext(meson.project_name(), preset: 'glib')
0707010000002C000081A400000000000000000000000168C4C09600000502000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/nl.po# Dutch translation for template-glib.
# Copyright (C) 2019 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Nathan Follens <nthn@unseen.is>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2018-11-21 13:22+0000\n"
"PO-Revision-Date: 2019-01-17 00:32+0100\n"
"Language-Team: Dutch <gnome-nl-list@gnome.org>\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Last-Translator: Nathan Follens <nthn@unseen.is>\n"
"X-Generator: Poedit 2.2\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() kan maar één keer opgeroepen worden"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Parseerder bevat geen invoerstream"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Moet sjabloon verwerken vóór uitbreiding"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Sjabloon ‘%s’ kan niet gevonden worden"
0707010000002D000081A400000000000000000000000168C4C09600000591000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/pl.po# Polish translation for template-glib.
# Copyright © 2016-2017 the template-glib authors.
# This file is distributed under the same license as the template-glib package.
# Piotr Drąg <piotrdrag@gmail.com>, 2016-2017.
# Aviary.pl <community-poland@mozilla.org>, 2016-2017.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-05 10:48+0000\n"
"PO-Revision-Date: 2017-06-05 12:49+0200\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <community-poland@mozilla.org>\n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() może być wywołane tylko raz"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "Parser nie zawiera potoku wejściowego"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Należy przetworzyć szablon przed rozszerzeniem"
#: src/tmpl-template-locator.c:105
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Ustalenie położenia szablonu „%s” się nie powiodło"
0707010000002E000081A400000000000000000000000168C4C0960000055A000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/pt.po# Portuguese translation for template-glib.
# Copyright (C) 2016 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Tiago Santos <tiagofsantos81@sapo.pt>, 2014 - 2016.
# Hugo Carvalho <hugokarvalho@hotmail.com>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2020-09-06 14:08+0000\n"
"PO-Revision-Date: 2021-08-28 15:06+0100\n"
"Last-Translator: Hugo Carvalho <hugokarvalho@hotmail.com>\n"
"Language-Team: Portuguese <gnome_pt@yahoogroups.com>\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.0\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() apenas pode ser chamada uma vez"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "O interpretador não contém um fluxo de entrada"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Tem de interpretar o modelo antes de o expandir"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Falha ao localizar o modelo \"%s\""
0707010000002F000081A400000000000000000000000168C4C096000005A4000000000000000000000000000000000000002100000000template-glib-3.38.0/po/pt_BR.po# Brazilian Portuguese translation for template-glib.
# Copyright (C) 2017 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Rafael Fontenelle <rafaelff@gnome.org>, 2016, 2017.
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-05 10:48+0000\n"
"PO-Revision-Date: 2017-06-25 16:29-0200\n"
"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Virtaal 1.0.0-beta1\n"
"X-Project-Style: gnome\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() pode ser chamado apenas uma vez"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "O analisador não contém um fluxo de entrada"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Deve-se analisar o modelo antes de expandir"
#: src/tmpl-template-locator.c:105
#, c-format
#| msgid "Failed to locate template \"%s\""
msgid "Failed to locate template “%s”"
msgstr "Falha ao localizar o modelo “%s”"
07070100000030000081A400000000000000000000000168C4C0960000054E000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/ro.po# Romanian translation for template-glib.
# Copyright (C) 2018 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Floren <>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2018-03-14 00:15+0000\n"
"PO-Revision-Date: 2018-04-05 17:54+0300\n"
"Language-Team: Romanian <gnomero-list@lists.sourceforge.net>\n"
"Language: ro\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2);;\n"
"Last-Translator: Florentina Mușat <florentina.musat.28@gmail.com>\n"
"X-Generator: Poedit 2.0.6\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() poate fi apelată doar o dată"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Programul de parsare nu conține un flux de intrare"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Trebuie parsat șablonul înainte de extindere"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Nu s-a putut localiza șablonul „%s”"
07070100000031000081A400000000000000000000000168C4C096000005CA000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/ru.po# Russian translation for template-glib.
# Copyright (C) 2023 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Aleksandr Melman <Alexmelman88@gmail.com>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib main\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2023-03-08 00:19+0000\n"
"PO-Revision-Date: 2023-04-21 12:58+0300\n"
"Last-Translator: Aleksandr Melman <Alexmelman88@gmail.com>\n"
"Language-Team: Russian <ru@li.org>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 3.2.2\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() может быть вызван только один раз"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Парсер не содержит входного потока"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Перед расширением необходимо разобрать шаблон"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Не удалось обнаружить шаблон \"%s\""
07070100000032000081A400000000000000000000000168C4C096000005BF000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/sl.po# Slovenian translation for template-glib.
# Copyright (C) 2016 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
#
# Matej Urbančič <mateju@svn.gnome.org>, 2016–2017.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-09-18 21:16+0200\n"
"PO-Revision-Date: 2017-09-18 21:16+0200\n"
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: sl_SI\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
"%100==4 ? 3 : 0);\n"
"X-Poedit-SourceCharset: utf-8\n"
"X-Generator: Poedit 2.0.1\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() je dovoljeno klicati le enkrat"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "Razčlenjevalnik ne vključuje vhodnega pretoka"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Pred razširjanjem je treba predlogo razčleniti"
#: src/tmpl-template-locator.c:105
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Iskanje predloge »%s« je spodletelo."
07070100000033000081A400000000000000000000000168C4C09600000655000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/sr.po# Serbian translation for template-glib.
# Copyright © 2016 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Мирослав Николић <miroslavnikolic@rocketmail.com>, 2016, 2017.
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-27 22:39+0000\n"
"PO-Revision-Date: 2017-08-12 21:45+0200\n"
"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
"Language-Team: српски <gnome-sr@googlegroups.org>\n"
"Language: sr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : "
"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Project-Style: gnome\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "Функција „%s()“ може бити позвана само једном"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "Обрађивач не садржи улазни ток"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Мора да обради шаблон пре ширења"
#: src/tmpl-template-locator.c:105
#, c-format
#| msgid "Failed to locate template \"%s\""
msgid "Failed to locate template “%s”"
msgstr "Нисам успео да пронађем шаблон „%s“"
07070100000034000081A400000000000000000000000168C4C09600000572000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/sv.po# Swedish translation for template-glib.
# Copyright © 2016, 2017 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Josef Andersson <josef.andersson@fripost.org>, 2016.
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"builder&keywords=I18N+L10N&component=templates\n"
"POT-Creation-Date: 2017-06-05 10:48+0000\n"
"PO-Revision-Date: 2017-06-12 18:50+0200\n"
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.8.11\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() kan bara anropas en gång"
#: src/tmpl-parser.c:211
msgid "Parser does not contain an input stream"
msgstr "Tolk innehåller inte en inmatningsström"
#: src/tmpl-template.c:454
msgid "Must parse template before expanding"
msgstr "Måste tolka mall innan expansion"
#: src/tmpl-template-locator.c:105
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Misslyckades med att finna mallen ”%s”"
07070100000035000081A400000000000000000000000168C4C09600000514000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/tr.po# Turkish translation for template-glib.
# Copyright (C) 2019 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
#
# Serdar Sağlam <teknomobil@msn.com>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2022-09-18 14:32+0000\n"
"PO-Revision-Date: 2019-01-29 03:05+0300\n"
"Last-Translator: Serdar Sağlam <teknomobil@yandex.com>\n"
"Language-Team: Turkish <gnome-turk@gnome.org>\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 2.2.1\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() sadece bir kez çağrılabilir"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Ayrıştırıcı bir giriş akışı içermiyor"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Genişletmeden önce şablonu ayrıştırmak gerekir"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Şablon konumu bulunamadı “%s”"
07070100000036000081A400000000000000000000000168C4C096000005EB000000000000000000000000000000000000001E00000000template-glib-3.38.0/po/uk.po# Ukrainian translation for template-glib.
# Copyright (C) 2020 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
#
# Yuri Chornoivan <yurchor@ukr.net>, 2020.
msgid ""
msgstr ""
"Project-Id-Version: template-glib template-glib-3-32\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2019-09-24 08:20+0000\n"
"PO-Revision-Date: 2020-03-31 12:38+0300\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Lokalize 20.07.70\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() можна викликати лише один раз"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "Обробник не містить жодного потоку вхідних даних"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "Слід обробити шаблон до розгортання"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "Не вдалося знайти шаблон «%s»"
07070100000037000081A400000000000000000000000168C4C09600000495000000000000000000000000000000000000002100000000template-glib-3.38.0/po/zh_CN.po# Chinese (China) translation for template-glib.
# Copyright (C) 2020 template-glib's COPYRIGHT HOLDER
# This file is distributed under the same license as the template-glib package.
# Boyuan Yang <073plan@gmail.com>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: template-glib master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/template-glib/issues\n"
"POT-Creation-Date: 2020-03-31 09:39+0000\n"
"PO-Revision-Date: 2020-09-06 10:07-0400\n"
"Language-Team: Chinese (China) <i18n-zh@googlegroups.com>\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: \n"
"X-Generator: Poedit 2.4.1\n"
#: src/tmpl-parser.c:199
#, c-format
msgid "%s() may only be called once"
msgstr "%s() 只能调用一次"
#: src/tmpl-parser.c:211
#, c-format
msgid "Parser does not contain an input stream"
msgstr "解析器未包含输入流"
#: src/tmpl-template.c:454
#, c-format
msgid "Must parse template before expanding"
msgstr "展开前必须解析模板"
#: src/tmpl-template-locator.c:117
#, c-format
msgid "Failed to locate template “%s”"
msgstr "无法定位模板“%s”"
07070100000038000041ED00000000000000000000000268C4C09600000000000000000000000000000000000000000000001900000000template-glib-3.38.0/src07070100000039000081A400000000000000000000000168C4C0960000003A000000000000000000000000000000000000002F00000000template-glib-3.38.0/src/Template-1.0.metadataTemplate name="Template"
* cheader_filename="tmpl-glib.h"
0707010000003A000081A400000000000000000000000168C4C09600000A6D000000000000000000000000000000000000002000000000template-glib-3.38.0/src/main.c/* main.c
*
* Copyright (C) 2015-2017 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gio/gio.h>
#include <stdio.h>
#include <stdlib.h>
#include <tmpl-glib.h>
static gboolean
method_missing (TmplScope *scope,
const gchar *name,
TmplSymbol **symbol,
gpointer user_data)
{
g_autofree gchar *str = g_strdup_printf ("missing symbol: %s", name);
g_assert (scope != NULL);
g_assert (name != NULL);
g_assert (symbol != NULL);
*symbol = tmpl_symbol_new ();
tmpl_symbol_assign_string (*symbol, str);
return TRUE;
}
gint
main (gint argc,
gchar *argv[])
{
TmplTemplateLocator *locator = NULL;
GOutputStream *stream = NULL;
TmplTemplate *tmpl = NULL;
TmplScope *scope = NULL;
GFile *file = NULL;
gchar *output;
GError *error = NULL;
gint ret = EXIT_FAILURE;
gchar zero = 0;
if (argc != 2)
{
g_printerr ("usage: %s TEMPLATE\n", argv [0]);
return EXIT_FAILURE;
}
locator = tmpl_template_locator_new ();
tmpl_template_locator_prepend_search_path (locator, ".");
tmpl = tmpl_template_new (locator);
file = g_file_new_for_commandline_arg (argv [1]);
scope = tmpl_scope_new ();
tmpl_scope_set_resolver (scope, method_missing, NULL, NULL);
if (!tmpl_template_parse_file (tmpl, file, NULL, &error))
{
g_printerr ("ERROR: %s\n", error->message);
g_clear_error (&error);
goto cleanup;
}
stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
if (!tmpl_template_expand (tmpl, stream, scope, NULL, &error))
{
g_printerr ("ERROR: %s\n", error->message);
g_clear_error (&error);
goto cleanup;
}
g_output_stream_write (stream, &zero, 1, NULL, NULL);
output = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (stream));
g_print ("%s\n", output);
ret = EXIT_SUCCESS;
cleanup:
g_clear_object (&stream);
g_clear_object (&locator);
g_clear_object (&tmpl);
g_clear_object (&file);
return ret;
}
0707010000003B000081A400000000000000000000000168C4C0960000191F000000000000000000000000000000000000002500000000template-glib-3.38.0/src/meson.buildlibtemplate_glib_header_subdir = 'template-glib-' + apiversion
libtemplate_glib_header_dir = join_paths(includedir, libtemplate_glib_header_subdir)
version_data = configuration_data()
version_data.set('TMPL_MAJOR_VERSION', template_glib_version_major)
version_data.set('TMPL_MINOR_VERSION', template_glib_version_minor)
version_data.set('TMPL_MICRO_VERSION', template_glib_version_micro)
version_data.set('TMPL_VERSION', meson.project_version())
version_data.set10('ENABLE_TRACING', get_option('tracing'))
core_lib_include_directories = [
include_directories('.'),
include_directories('..'),
]
tmpl_version_h = configure_file(
input: 'tmpl-version.h.in',
output: 'tmpl-version.h',
install_dir: libtemplate_glib_header_dir,
configuration: version_data)
tmpl_debug_h = configure_file(
input: 'tmpl-debug.h.in',
output: 'tmpl-debug.h',
install_dir: libtemplate_glib_header_dir,
configuration: version_data)
libtemplate_glib_enum_headers = [
'tmpl-error.h',
'tmpl-expr-types.h',
]
libtemplate_glib_enums = gnome.mkenums('tmpl-enums',
h_template: 'tmpl-enums.h.in',
c_template: 'tmpl-enums.c.in',
sources: libtemplate_glib_enum_headers,
install_header: true,
install_dir: libtemplate_glib_header_dir,
)
libtemplate_glib_generated_headers = [
tmpl_debug_h,
tmpl_version_h,
libtemplate_glib_enums[1],
]
libtemplate_glib_public_headers = [
'tmpl-error.h',
'tmpl-expr-types.h',
'tmpl-expr.h',
'tmpl-glib.h',
'tmpl-scope.h',
'tmpl-symbol.h',
'tmpl-template-locator.h',
'tmpl-template.h',
'tmpl-version-macros.h',
]
libtemplate_glib_public_sources = [
'tmpl-error.c',
'tmpl-expr.c',
'tmpl-scope.c',
'tmpl-symbol.c',
'tmpl-template.c',
'tmpl-template-locator.c',
libtemplate_glib_enums[0],
]
libtemplate_glib_deps = [
dependency('gio-2.0'),
dependency('girepository-2.0'),
cc.find_library('m', required: false),
]
flex = find_program('flex')
bison = find_program('bison')
sed = find_program('sed')
tmpl_expr_parser = custom_target('tmpl-expr-parser',
input: 'tmpl-expr-parser.y',
output: ['tmpl-expr-parser.c', 'tmpl-expr-parser.h'],
command: [bison, '@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@']
)
# This is an awful workaround, flex files embed options to control the output
# this fails with meson which wants to output to specific directories
# and just to avoid any regressions we don't want to modify the autotools files
tmpl_expr_scanner_flex = custom_target('tmpl-expr-scanner-flex',
input: 'tmpl-expr-scanner.l',
output: 'tmpl-expr-meson-scanner.l',
capture: true,
command: [sed, '-e', 's/^%option header-file.*$//',
'-e', 's/^%option outfile.*$//', '@INPUT@']
)
tmpl_expr_scanner = custom_target('tmpl-expr-scanner',
input: tmpl_expr_scanner_flex,
output: 'tmpl-expr-scanner.c',
command: [flex, '-o', '@OUTPUT@', '@INPUT@']
)
libtemplate_glib_sources = [
libtemplate_glib_generated_headers,
libtemplate_glib_public_headers,
libtemplate_glib_public_sources,
tmpl_expr_parser,
tmpl_expr_scanner,
'tmpl-branch-node.c',
'tmpl-branch-node.h',
'tmpl-condition-node.c',
'tmpl-condition-node.h',
'tmpl-expr-eval.c',
'tmpl-expr-node.c',
'tmpl-expr-node.h',
'tmpl-expr-parser-private.h',
'tmpl-expr-private.h',
'tmpl-gi-private.h',
'tmpl-gi.c',
'tmpl-iter-node.c',
'tmpl-iter-node.h',
'tmpl-iterator.c',
'tmpl-iterator.h',
'tmpl-lexer.c',
'tmpl-lexer.h',
'tmpl-node.c',
'tmpl-node.h',
'tmpl-parser.c',
'tmpl-parser.h',
'tmpl-text-node.c',
'tmpl-text-node.h',
'tmpl-token-input-stream.c',
'tmpl-token-input-stream.h',
'tmpl-token.c',
'tmpl-token.h',
'tmpl-util-private.h',
'tmpl-util.c',
]
core_lib_c_args = [
'-DTMPL_GLIB_COMPILATION',
]
core_lib = static_library('template_glib', libtemplate_glib_sources,
dependencies: libtemplate_glib_deps,
c_args: release_args + core_lib_c_args,
include_directories: core_lib_include_directories,
)
core_lib_dep = declare_dependency(
sources: libtemplate_glib_generated_headers,
dependencies: libtemplate_glib_deps,
link_whole: core_lib,
include_directories: core_lib_include_directories,
)
libtemplate_glib = library(
'template_glib-' + apiversion,
link_whole: core_lib,
dependencies: libtemplate_glib_deps,
soversion: soversion,
version: libversion,
darwin_versions: darwin_versions,
install: true,
)
libtemplate_glib_dep = declare_dependency(
sources: libtemplate_glib_generated_headers,
dependencies: libtemplate_glib_deps,
link_with: libtemplate_glib,
include_directories: core_lib_include_directories,
)
if generate_gir
libtemplate_glib_gir = gnome.generate_gir(libtemplate_glib,
sources: libtemplate_glib_generated_headers + libtemplate_glib_public_headers + libtemplate_glib_public_sources,
nsversion: apiversion,
namespace: 'Template',
export_packages: 'template-glib-@0@'.format(apiversion),
symbol_prefix: 'tmpl',
identifier_prefix: 'Tmpl',
link_with: libtemplate_glib,
includes: [ 'Gio-2.0' ],
install: true,
install_dir_gir: girdir,
include_directories: core_lib_include_directories,
install_dir_typelib: typelibdir,
extra_args: [
'--c-include=tmpl-glib.h',
'-DTMPL_GLIB_COMPILATION',
],
)
if get_option('vapi')
libtemplate_glib_vapi = gnome.generate_vapi('template-glib-' + apiversion,
sources: libtemplate_glib_gir[0],
packages: [ 'gio-2.0' ],
install: true,
install_dir: vapidir,
)
endif
endif
install_headers(libtemplate_glib_public_headers,
install_dir: libtemplate_glib_header_dir
)
if meson.version().version_compare('>=0.57')
meson.override_dependency('template-glib-@0@'.format(apiversion), libtemplate_glib_dep)
endif
pkgg = import('pkgconfig')
pkgg.generate(
libraries: [libtemplate_glib],
subdirs: join_paths(package_subdir, libtemplate_glib_header_subdir),
version: meson.project_version(),
name: 'Template-GLib',
filebase: 'template-glib-@0@'.format(apiversion),
description: 'A templating library for GLib',
requires: 'gio-2.0',
install_dir: join_paths(libdir, 'pkgconfig'),
)
0707010000003C000081A400000000000000000000000168C4C09600001AFD000000000000000000000000000000000000002C00000000template-glib-3.38.0/src/tmpl-branch-node.c/* tmpl-branch-node.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "tmpl-branch-node"
#include "tmpl-branch-node.h"
#include "tmpl-condition-node.h"
#include "tmpl-debug.h"
#include "tmpl-error.h"
#include "tmpl-util-private.h"
struct _TmplBranchNode
{
TmplNode parent_instance;
TmplNode *if_branch;
GPtrArray *children;
};
G_DEFINE_TYPE (TmplBranchNode, tmpl_branch_node, TMPL_TYPE_NODE)
static gboolean
tmpl_branch_node_accept (TmplNode *node,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error)
{
TmplBranchNode *self = (TmplBranchNode *)node;
TMPL_ENTRY;
g_assert (TMPL_IS_BRANCH_NODE (self));
g_assert (self->if_branch != NULL);
g_assert (lexer != NULL);
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
if (!tmpl_node_accept (self->if_branch, lexer, cancellable, error))
TMPL_RETURN (FALSE);
/*
* At this point, the if branch should have everything, so we are
* looking for ELSE_IF, ELSE, or END. Everything else is a syntax
* error.
*/
while (TRUE)
{
TmplToken *token = NULL;
if (!tmpl_lexer_next (lexer, &token, cancellable, error))
TMPL_RETURN (FALSE);
switch (tmpl_token_type (token))
{
case TMPL_TOKEN_EOF:
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Unexpected end-of-file reached");
TMPL_RETURN (FALSE);
case TMPL_TOKEN_END:
tmpl_token_free (token);
TMPL_RETURN (TRUE);
case TMPL_TOKEN_ELSE:
case TMPL_TOKEN_ELSE_IF:
{
TmplNode *child;
TmplExpr *expr = NULL;
if (tmpl_token_type (token) != TMPL_TOKEN_ELSE)
{
const gchar *exprstr;
exprstr = tmpl_token_get_text (token);
expr = tmpl_expr_from_string (exprstr, error);
}
else
expr = tmpl_expr_new_boolean (TRUE);
tmpl_token_free (token);
if (expr == NULL)
TMPL_RETURN (FALSE);
child = tmpl_condition_node_new (expr);
if (self->children == NULL)
self->children = g_ptr_array_new_with_free_func (g_object_unref);
g_ptr_array_add (self->children, child);
if (!tmpl_node_accept (child, lexer, cancellable, error))
TMPL_RETURN (FALSE);
}
break;
case TMPL_TOKEN_TEXT:
case TMPL_TOKEN_IF:
case TMPL_TOKEN_EXPRESSION:
case TMPL_TOKEN_FOR:
case TMPL_TOKEN_INCLUDE:
default:
tmpl_token_free (token);
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Invalid token, expected else if, else, or end.");
TMPL_RETURN (FALSE);
}
}
}
static void
tmpl_branch_node_visit_children (TmplNode *node,
TmplNodeVisitor visitor,
gpointer user_data)
{
TmplBranchNode *self = (TmplBranchNode *)node;
g_assert (TMPL_IS_NODE (node));
g_assert (visitor != NULL);
if (self->if_branch)
visitor (self->if_branch, user_data);
if (self->children != NULL)
{
for (guint i = 0; i < self->children->len; i++)
{
TmplNode *child = g_ptr_array_index (self->children, i);
visitor (child, user_data);
}
}
}
static void
tmpl_branch_node_finalize (GObject *object)
{
TmplBranchNode *self = (TmplBranchNode *)object;
g_clear_pointer (&self->children, g_ptr_array_unref);
g_clear_object (&self->if_branch);
G_OBJECT_CLASS (tmpl_branch_node_parent_class)->finalize (object);
}
static void
tmpl_branch_node_class_init (TmplBranchNodeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
TmplNodeClass *node_class = TMPL_NODE_CLASS (klass);
object_class->finalize = tmpl_branch_node_finalize;
node_class->accept = tmpl_branch_node_accept;
node_class->visit_children = tmpl_branch_node_visit_children;
}
static void
tmpl_branch_node_init (TmplBranchNode *self)
{
}
/**
* tmpl_branch_node_new:
* @expr: (transfer full): A TmplExpr
*
* Creates a new branch (if, else if, else) using @expr for the (if)
* branch.
*
* Returns: (transfer full): A #TmplBranchNode.
*/
TmplNode *
tmpl_branch_node_new (TmplExpr *condition)
{
TmplBranchNode *self;
self = g_object_new (TMPL_TYPE_BRANCH_NODE, NULL);
self->if_branch = tmpl_condition_node_new (condition);
return TMPL_NODE (self);
}
static gboolean
condition_matches (TmplNode *condition,
TmplScope *scope,
GError **error)
{
TmplExpr *expr;
GValue value = G_VALUE_INIT;
gboolean ret;
g_assert (TMPL_IS_CONDITION_NODE (condition));
if (!(expr = tmpl_condition_node_get_condition (TMPL_CONDITION_NODE (condition))))
return FALSE;
if (!tmpl_expr_eval (expr, scope, &value, error))
return FALSE;
ret = tmpl_value_as_boolean (&value);
TMPL_CLEAR_VALUE (&value);
return ret;
}
TmplNode *
tmpl_branch_node_branch (TmplBranchNode *self,
TmplScope *scope,
GError **error)
{
GError *local_error = NULL;
TMPL_ENTRY;
g_return_val_if_fail (TMPL_IS_BRANCH_NODE (self), NULL);
g_return_val_if_fail (self->if_branch != NULL, NULL);
if (condition_matches (self->if_branch, scope, &local_error))
return self->if_branch;
if (local_error != NULL)
{
g_propagate_error (error, local_error);
TMPL_RETURN (NULL);
}
if (self->children != NULL)
{
for (guint i = 0; i < self->children->len; i++)
{
TmplNode *child = g_ptr_array_index (self->children, i);
if (condition_matches (child, scope, &local_error))
TMPL_RETURN (child);
if (local_error != NULL)
{
g_propagate_error (error, local_error);
TMPL_RETURN (NULL);
}
}
}
TMPL_RETURN (NULL);
}
0707010000003D000081A400000000000000000000000168C4C096000005AC000000000000000000000000000000000000002C00000000template-glib-3.38.0/src/tmpl-branch-node.h/* tmpl-branch-node.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_BRANCH_NODE_H
#define TMPL_BRANCH_NODE_H
#include "tmpl-expr.h"
#include "tmpl-node.h"
#include "tmpl-scope.h"
G_BEGIN_DECLS
#define TMPL_TYPE_BRANCH_NODE (tmpl_branch_node_get_type())
G_DECLARE_FINAL_TYPE (TmplBranchNode, tmpl_branch_node, TMPL, BRANCH_NODE, TmplNode)
TmplNode *tmpl_branch_node_new (TmplExpr *expr);
TmplNode *tmpl_branch_node_branch (TmplBranchNode *self,
TmplScope *scope,
GError **error);
G_END_DECLS
#endif /* TMPL_BRANCH_NODE_H */
0707010000003E000081A400000000000000000000000168C4C096000012AA000000000000000000000000000000000000002F00000000template-glib-3.38.0/src/tmpl-condition-node.c/* tmpl-condition-node.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "tmpl-condition-node"
#include "tmpl-condition-node.h"
#include "tmpl-debug.h"
#include "tmpl-error.h"
struct _TmplConditionNode
{
TmplNode parent_instance;
GPtrArray *children;
TmplExpr *condition;
};
G_DEFINE_TYPE (TmplConditionNode, tmpl_condition_node, TMPL_TYPE_NODE)
static gboolean
tmpl_condition_node_accept (TmplNode *node,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error)
{
TmplConditionNode *self = (TmplConditionNode *)node;
TmplToken *token = NULL;
TMPL_ENTRY;
g_assert (TMPL_IS_NODE (node));
g_assert (lexer != NULL);
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
/*
* We are an if/else if/else condition, if we come across an
* end/else if/else then we need to unget and allow the parent
* branch to resolve.
*/
while (TRUE)
{
TmplNode *child;
if (!tmpl_lexer_next (lexer, &token, cancellable, error))
TMPL_RETURN (FALSE);
switch (tmpl_token_type (token))
{
case TMPL_TOKEN_EOF:
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Unexpected end-of-file reached.");
TMPL_RETURN (FALSE);
case TMPL_TOKEN_ELSE_IF:
case TMPL_TOKEN_ELSE:
case TMPL_TOKEN_END:
tmpl_lexer_unget (lexer, token);
TMPL_RETURN (TRUE);
case TMPL_TOKEN_TEXT:
case TMPL_TOKEN_IF:
case TMPL_TOKEN_FOR:
case TMPL_TOKEN_EXPRESSION:
child = tmpl_node_new_for_token (token, error);
tmpl_token_free (token);
if (child == NULL)
TMPL_RETURN (FALSE);
if (self->children == NULL)
self->children = g_ptr_array_new_with_free_func (g_object_unref);
g_ptr_array_add (self->children, child);
if (!tmpl_node_accept (child, lexer, cancellable, error))
TMPL_RETURN (FALSE);
break;
case TMPL_TOKEN_INCLUDE:
default:
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Invalid token type");
TMPL_RETURN (FALSE);
}
}
g_assert_not_reached ();
}
static void
tmpl_condition_node_visit_children (TmplNode *node,
TmplNodeVisitor visitor,
gpointer user_data)
{
TmplConditionNode *self = (TmplConditionNode *)node;
g_assert (TMPL_IS_CONDITION_NODE (self));
g_assert (visitor != NULL);
if (self->children != NULL)
{
for (guint i = 0; i < self->children->len; i++)
{
TmplNode *child = g_ptr_array_index (self->children, i);
visitor (child, user_data);
}
}
}
static void
tmpl_condition_node_finalize (GObject *object)
{
TmplConditionNode *self = (TmplConditionNode *)object;
g_clear_pointer (&self->condition, tmpl_expr_unref);
g_clear_pointer (&self->children, g_ptr_array_unref);
G_OBJECT_CLASS (tmpl_condition_node_parent_class)->finalize (object);
}
static void
tmpl_condition_node_class_init (TmplConditionNodeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
TmplNodeClass *node_class = TMPL_NODE_CLASS (klass);
object_class->finalize = tmpl_condition_node_finalize;
node_class->accept = tmpl_condition_node_accept;
node_class->visit_children = tmpl_condition_node_visit_children;
}
static void
tmpl_condition_node_init (TmplConditionNode *self)
{
}
TmplNode *
tmpl_condition_node_new (TmplExpr *condition)
{
TmplConditionNode *self;
self = g_object_new (TMPL_TYPE_CONDITION_NODE, NULL);
self->condition = condition;
return TMPL_NODE (self);
}
TmplExpr *
tmpl_condition_node_get_condition (TmplConditionNode *self)
{
g_return_val_if_fail (TMPL_IS_CONDITION_NODE (self), NULL);
return self->condition;
}
0707010000003F000081A400000000000000000000000168C4C09600000551000000000000000000000000000000000000002F00000000template-glib-3.38.0/src/tmpl-condition-node.h/* tmpl-condition-node.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_CONDITION_NODE_H
#define TMPL_CONDITION_NODE_H
#include "tmpl-expr.h"
#include "tmpl-node.h"
G_BEGIN_DECLS
#define TMPL_TYPE_CONDITION_NODE (tmpl_condition_node_get_type())
G_DECLARE_FINAL_TYPE (TmplConditionNode, tmpl_condition_node, TMPL, CONDITION_NODE, TmplNode)
TmplNode *tmpl_condition_node_new (TmplExpr *expr);
TmplExpr *tmpl_condition_node_get_condition (TmplConditionNode *self);
G_END_DECLS
#endif /* TMPL_CONDITION_NODE_H */
07070100000040000081A400000000000000000000000168C4C09600000CA8000000000000000000000000000000000000002900000000template-glib-3.38.0/src/tmpl-debug.h.in/* tmpl-debug.h.in
*
* Copyright (C) 2015-2017 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_DEBUG_H
#define TMPL_DEBUG_H
#include <glib.h>
G_BEGIN_DECLS
#ifndef TMPL_ENABLE_TRACE
# define TMPL_ENABLE_TRACE @ENABLE_TRACING@
#endif
#if TMPL_ENABLE_TRACE != 1
# undef TMPL_ENABLE_TRACE
#endif
#define TMPL_LOG_LEVEL_TRACE (1 << G_LOG_LEVEL_USER_SHIFT)
#ifdef TMPL_ENABLE_TRACE
# define TMPL_TRACE_MSG(fmt, ...) \
g_log(G_LOG_DOMAIN, TMPL_LOG_LEVEL_TRACE, " MSG: %s():%d: "fmt, \
G_STRFUNC, __LINE__, ##__VA_ARGS__)
# define TMPL_PROBE \
g_log(G_LOG_DOMAIN, TMPL_LOG_LEVEL_TRACE, "PROBE: %s():%d", \
G_STRFUNC, __LINE__)
# define TMPL_TODO(_msg) \
g_log(G_LOG_DOMAIN, TMPL_LOG_LEVEL_TRACE, " TODO: %s():%d: %s", \
G_STRFUNC, __LINE__, _msg)
# define TMPL_ENTRY \
g_log(G_LOG_DOMAIN, TMPL_LOG_LEVEL_TRACE, "ENTRY: %s():%d", \
G_STRFUNC, __LINE__)
# define TMPL_EXIT \
G_STMT_START { \
g_log(G_LOG_DOMAIN, TMPL_LOG_LEVEL_TRACE, " EXIT: %s():%d", \
G_STRFUNC, __LINE__); \
return; \
} G_STMT_END
# define TMPL_GOTO(_l) \
G_STMT_START { \
g_log(G_LOG_DOMAIN, TMPL_LOG_LEVEL_TRACE, " GOTO: %s():%d ("#_l")", \
G_STRFUNC, __LINE__); \
goto _l; \
} G_STMT_END
# define TMPL_RETURN(_r) \
G_STMT_START { \
g_log(G_LOG_DOMAIN, TMPL_LOG_LEVEL_TRACE, " EXIT: %s():%d ", \
G_STRFUNC, __LINE__); \
return _r; \
} G_STMT_END
#else
# define TMPL_TODO(_msg)
# define TMPL_PROBE
# define TMPL_TRACE_MSG(fmt, ...)
# define TMPL_ENTRY
# define TMPL_GOTO(_l) goto _l
# define TMPL_EXIT return
# define TMPL_RETURN(_r) return _r
#endif
G_END_DECLS
#endif /* TMPL_DEBUG_H */
07070100000041000081A400000000000000000000000168C4C0960000034B000000000000000000000000000000000000002900000000template-glib-3.38.0/src/tmpl-enums.c.in/*** BEGIN file-header ***/
#include "config.h"
#include "tmpl-enums.h"
#include "tmpl-error.h"
#include "tmpl-expr-types.h"
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@basename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
static GType etype = 0;
if (G_UNLIKELY(etype == 0)) {
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
}
return etype;
}
/*** END value-tail ***/
/*** BEGIN file-tail ***/
/*** END file-tail ***/
07070100000042000081A400000000000000000000000168C4C096000001ED000000000000000000000000000000000000002900000000template-glib-3.38.0/src/tmpl-enums.h.in/*** BEGIN file-header ***/
#ifndef __IDE_ENUMS_H__
#define __IDE_ENUMS_H__
#include <glib-object.h>
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@basename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType @enum_name@_get_type (void);
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
/*** END value-header ***/
/*** BEGIN file-tail ***/
G_END_DECLS
#endif /* __IDE_ENUMS_H__ */
/*** END file-tail ***/
07070100000043000081A400000000000000000000000168C4C09600000359000000000000000000000000000000000000002600000000template-glib-3.38.0/src/tmpl-error.c/* tmpl-error.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tmpl-error.h"
GQuark
tmpl_error_quark (void)
{
return g_quark_from_static_string ("tmpl-error");
}
07070100000044000081A400000000000000000000000168C4C09600000688000000000000000000000000000000000000002600000000template-glib-3.38.0/src/tmpl-error.h/* gis-error.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_ERROR_H
#define TMPL_ERROR_H
#include <glib.h>
#include "tmpl-version-macros.h"
G_BEGIN_DECLS
#define TMPL_ERROR (tmpl_error_quark())
typedef enum
{
TMPL_ERROR_INVALID_STATE = 1,
TMPL_ERROR_TEMPLATE_NOT_FOUND,
TMPL_ERROR_CIRCULAR_INCLUDE,
TMPL_ERROR_SYNTAX_ERROR,
TMPL_ERROR_LEXER_FAILURE,
TMPL_ERROR_TYPE_MISMATCH,
TMPL_ERROR_INVALID_OP_CODE,
TMPL_ERROR_DIVIDE_BY_ZERO,
TMPL_ERROR_MISSING_SYMBOL,
TMPL_ERROR_SYMBOL_REDEFINED,
TMPL_ERROR_NOT_AN_OBJECT,
TMPL_ERROR_NULL_POINTER,
TMPL_ERROR_NO_SUCH_PROPERTY,
TMPL_ERROR_GI_FAILURE,
TMPL_ERROR_RUNTIME_ERROR,
TMPL_ERROR_NOT_IMPLEMENTED,
TMPL_ERROR_NOT_A_VALUE,
TMPL_ERROR_NOT_A_FUNCTION,
} TmplError;
TMPL_AVAILABLE_IN_ALL
GQuark tmpl_error_quark (void);
G_END_DECLS
#endif /* TMPL_ERROR_H */
07070100000045000081A400000000000000000000000168C4C09600011E0C000000000000000000000000000000000000002A00000000template-glib-3.38.0/src/tmpl-expr-eval.c/* tmpl-expr-eval.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <math.h>
#include <string.h>
#include <girepository/girepository.h>
#include "tmpl-error.h"
#include "tmpl-expr.h"
#include "tmpl-expr-private.h"
#include "tmpl-gi-private.h"
#include "tmpl-scope.h"
#include "tmpl-symbol.h"
#include "tmpl-util-private.h"
#define DECLARE_BUILTIN(name) \
static gboolean builtin_##name (const GValue *, GValue *, GError **);
typedef gboolean (*BuiltinFunc) (const GValue *value,
GValue *return_value,
GError **error);
typedef gboolean (*FastDispatch) (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error);
static gboolean tmpl_expr_eval_internal (TmplExpr *node,
TmplScope *scope,
GValue *return_value,
GError **error);
static gboolean throw_type_mismatch (GError **error,
const GValue *left,
const GValue *right,
const gchar *message);
static gboolean eq_enum_string (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error);
static gboolean ne_enum_string (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error);
static gboolean add_string_string_slow (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error);
DECLARE_BUILTIN (abs)
DECLARE_BUILTIN (assert)
DECLARE_BUILTIN (ceil)
DECLARE_BUILTIN (floor)
DECLARE_BUILTIN (hex)
DECLARE_BUILTIN (log)
DECLARE_BUILTIN (print)
DECLARE_BUILTIN (printerr)
DECLARE_BUILTIN (repr)
DECLARE_BUILTIN (sqrt)
DECLARE_BUILTIN (sin)
DECLARE_BUILTIN (tan)
DECLARE_BUILTIN (cos)
DECLARE_BUILTIN (typeof)
DECLARE_BUILTIN (cast_byte)
DECLARE_BUILTIN (cast_char)
DECLARE_BUILTIN (cast_i32)
DECLARE_BUILTIN (cast_u32)
DECLARE_BUILTIN (cast_i64)
DECLARE_BUILTIN (cast_u64)
DECLARE_BUILTIN (cast_float)
DECLARE_BUILTIN (cast_double)
DECLARE_BUILTIN (cast_bool)
static GHashTable *fast_dispatch;
static BuiltinFunc builtin_funcs [] = {
builtin_abs,
builtin_ceil,
builtin_floor,
builtin_hex,
builtin_log,
builtin_print,
builtin_repr,
builtin_sqrt,
builtin_typeof,
builtin_assert,
builtin_sin,
builtin_tan,
builtin_cos,
builtin_printerr,
builtin_cast_byte,
builtin_cast_char,
builtin_cast_i32,
builtin_cast_u32,
builtin_cast_i64,
builtin_cast_u64,
builtin_cast_float,
builtin_cast_double,
builtin_cast_bool,
};
static inline guint
build_hash (TmplExprType type,
GType left,
GType right)
{
if (left && !G_TYPE_IS_FUNDAMENTAL (left))
return 0;
if (right && !G_TYPE_IS_FUNDAMENTAL (right))
return 0;
return type | (left << 16) | (right << 24);
}
static gboolean
eq_gtype_gtype (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value,
g_value_get_gtype (left) == g_value_get_gtype (right) ||
g_type_is_a (g_value_get_gtype (right), g_value_get_gtype (left)));
return TRUE;
}
static gboolean
ne_gtype_gtype (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
if (eq_gtype_gtype (left, right, return_value, error))
{
g_value_set_boolean (return_value, !g_value_get_boolean (return_value));
return TRUE;
}
return FALSE;
}
static gboolean
eq_null (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
const GValue *val;
g_value_init (return_value, G_TYPE_BOOLEAN);
if (G_VALUE_HOLDS_POINTER (left) && g_value_get_pointer (left) == NULL)
val = right;
else
val = left;
if (val->g_type == G_TYPE_INVALID ||
G_VALUE_HOLDS_POINTER (val) ||
G_VALUE_HOLDS_STRING (val) ||
G_VALUE_HOLDS_OBJECT (val) ||
G_VALUE_HOLDS_BOXED (val) ||
G_VALUE_HOLDS_GTYPE (val) ||
G_VALUE_HOLDS_VARIANT (val))
{
g_value_set_boolean (return_value, val->data[0].v_pointer == NULL);
return TRUE;
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_TYPE_MISMATCH,
"Cannot compare %s for null equality",
G_VALUE_TYPE_NAME (val));
return FALSE;
}
static gboolean
ne_null (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
if (eq_null (left, right, return_value, error))
{
g_value_set_boolean (return_value, !g_value_get_boolean (return_value));
return TRUE;
}
return FALSE;
}
static gboolean
strv_eq (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_BOOLEAN);
if (g_value_get_boxed (left) == g_value_get_boxed (right) ||
(g_value_get_boxed (left) && g_value_get_boxed (right) && g_strv_equal (g_value_get_boxed (left), g_value_get_boxed (right))))
g_value_set_boolean (return_value, TRUE);
else
g_value_set_boolean (return_value, FALSE);
return TRUE;
}
static gboolean
strv_ne (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
if (strv_eq (left, right, return_value, error))
{
g_value_set_boolean (return_value, !g_value_get_boolean (return_value));
return TRUE;
}
return FALSE;
}
static gboolean
throw_type_mismatch (GError **error,
const GValue *left,
const GValue *right,
const gchar *message)
{
if (right != NULL)
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_TYPE_MISMATCH,
"%s: %s and %s",
message,
G_VALUE_TYPE_NAME (left),
G_VALUE_TYPE_NAME (right));
else
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_TYPE_MISMATCH,
"%s: %s", message, G_VALUE_TYPE_NAME (left));
return TRUE;
}
#define SIMPLE_NUMBER_OP(op, left, right, return_value, error) \
G_STMT_START { \
if (G_VALUE_HOLDS (left, G_VALUE_TYPE (right))) \
{ \
if (G_VALUE_HOLDS (left, G_TYPE_DOUBLE)) \
{ \
g_value_init (return_value, G_TYPE_DOUBLE); \
g_value_set_double (return_value, \
g_value_get_double (left) \
op \
g_value_get_double (right)); \
return TRUE; \
} \
} \
return throw_type_mismatch (error, left, right, "invalid op " #op); \
} G_STMT_END
static FastDispatch
find_dispatch_slow (TmplExprSimple *node,
const GValue *left,
const GValue *right)
{
if (node->type == TMPL_EXPR_EQ)
{
if ((G_VALUE_HOLDS_STRING (left) && G_VALUE_HOLDS_ENUM (right)) ||
(G_VALUE_HOLDS_STRING (right) && G_VALUE_HOLDS_ENUM (left)))
return eq_enum_string;
if (G_VALUE_HOLDS_GTYPE (left) && G_VALUE_HOLDS_GTYPE (right))
return eq_gtype_gtype;
if ((G_VALUE_HOLDS_POINTER (left) && g_value_get_pointer (left) == NULL) ||
(G_VALUE_HOLDS_POINTER (right) && g_value_get_pointer (right) == NULL))
return eq_null;
if (G_VALUE_HOLDS (left, G_TYPE_STRV) && G_VALUE_HOLDS (right, G_TYPE_STRV))
return strv_eq;
}
if (node->type == TMPL_EXPR_NE)
{
if ((G_VALUE_HOLDS_STRING (left) && G_VALUE_HOLDS_ENUM (right)) ||
(G_VALUE_HOLDS_STRING (right) && G_VALUE_HOLDS_ENUM (left)))
return ne_enum_string;
if (G_VALUE_HOLDS_GTYPE (left) && G_VALUE_HOLDS_GTYPE (right))
return ne_gtype_gtype;
if ((G_VALUE_HOLDS_POINTER (left) && g_value_get_pointer (left) == NULL) ||
(G_VALUE_HOLDS_POINTER (right) && g_value_get_pointer (right) == NULL))
return ne_null;
if (G_VALUE_HOLDS (left, G_TYPE_STRV) && G_VALUE_HOLDS (right, G_TYPE_STRV))
return strv_ne;
}
if (node->type == TMPL_EXPR_ADD)
{
if (G_VALUE_HOLDS_STRING (left) || G_VALUE_HOLDS_STRING (right))
return add_string_string_slow;
}
return NULL;
}
static gboolean
tmpl_expr_simple_eval (TmplExprSimple *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue left = G_VALUE_INIT;
GValue right = G_VALUE_INIT;
gboolean ret = FALSE;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
if (tmpl_expr_eval_internal (node->left, scope, &left, error) &&
((node->right == NULL) ||
tmpl_expr_eval_internal (node->right, scope, &right, error)))
{
FastDispatch dispatch = NULL;
guint hash;
hash = build_hash (node->type, G_VALUE_TYPE (&left), G_VALUE_TYPE (&right));
if (hash != 0)
dispatch = g_hash_table_lookup (fast_dispatch, GINT_TO_POINTER (hash));
if G_UNLIKELY (dispatch == NULL)
{
dispatch = find_dispatch_slow (node, &left, &right);
if (dispatch == NULL)
{
g_autofree gchar *msg = g_strdup_printf ("type mismatch (%d)", node->type);
throw_type_mismatch (error, &left, &right, msg);
goto cleanup;
}
}
ret = dispatch (&left, &right, return_value, error);
}
cleanup:
TMPL_CLEAR_VALUE (&left);
TMPL_CLEAR_VALUE (&right);
return ret;
}
static gboolean
tmpl_expr_simple_eval_logical (TmplExprSimple *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue left = G_VALUE_INIT;
GValue right = G_VALUE_INIT;
gboolean ret = FALSE;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
g_value_init (return_value, G_TYPE_BOOLEAN);
if (!tmpl_expr_eval_internal (node->left, scope, &left, error))
goto failure;
switch ((int)node->type)
{
case TMPL_EXPR_AND:
if (!tmpl_value_as_boolean (&left))
{
g_value_set_boolean (return_value, FALSE);
ret = TRUE;
break;
}
if (!tmpl_expr_eval_internal (node->right, scope, &right, error))
goto failure;
g_value_set_boolean (return_value, tmpl_value_as_boolean (&right));
ret = TRUE;
break;
case TMPL_EXPR_OR:
if (tmpl_value_as_boolean (&left))
{
g_value_set_boolean (return_value, TRUE);
ret = TRUE;
break;
}
if (!tmpl_expr_eval_internal (node->right, scope, &right, error))
goto failure;
g_value_set_boolean (return_value, tmpl_value_as_boolean (&right));
ret = TRUE;
break;
default:
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_RUNTIME_ERROR,
"Unknown logical operator type: %d", node->type);
break;
}
failure:
TMPL_CLEAR_VALUE (&left);
TMPL_CLEAR_VALUE (&right);
return ret;
}
static gboolean
tmpl_expr_fn_call_eval (TmplExprFnCall *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue left = G_VALUE_INIT;
gboolean ret = FALSE;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
if (tmpl_expr_eval_internal (node->param, scope, &left, error))
ret = builtin_funcs [node->builtin] (&left, return_value, error);
TMPL_CLEAR_VALUE (&left);
return ret;
}
static gboolean
tmpl_expr_flow_eval (TmplExprFlow *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue cond = G_VALUE_INIT;
gboolean ret = FALSE;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
if (!tmpl_expr_eval_internal (node->condition, scope, &cond, error))
goto cleanup;
if (node->type == TMPL_EXPR_IF)
{
if (tmpl_value_as_boolean (&cond))
{
if (node->primary != NULL)
ret = tmpl_expr_eval_internal (node->primary, scope, return_value, error);
else
ret = TRUE;
goto cleanup;
}
else
{
if (node->secondary != NULL)
ret = tmpl_expr_eval_internal (node->secondary, scope, return_value, error);
else
ret = TRUE;
goto cleanup;
}
}
else if (node->type == TMPL_EXPR_WHILE)
{
if (node->primary != NULL)
{
while (tmpl_value_as_boolean (&cond))
{
/* last iteration is result value */
g_value_unset (return_value);
if (!tmpl_expr_eval_internal (node->primary, scope, return_value, error))
goto cleanup;
g_value_unset (&cond);
if (!tmpl_expr_eval_internal (node->condition, scope, &cond, error))
goto cleanup;
}
}
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_INVALID_STATE,
"Invalid AST");
cleanup:
TMPL_CLEAR_VALUE (&cond);
return ret;
}
static gboolean
tmpl_expr_stmt_list_eval (TmplExprStmtList *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue last = G_VALUE_INIT;
if G_UNLIKELY (node->stmts == NULL || node->stmts->len == 0)
{
g_set_error_literal (error,
TMPL_ERROR,
TMPL_ERROR_RUNTIME_ERROR,
"Runtime Error: implausible TmplExprStmtList");
return FALSE;
}
for (guint i = 0; i < node->stmts->len; i++)
{
TmplExpr *stmt = g_ptr_array_index (node->stmts, i);
TMPL_CLEAR_VALUE (&last);
if (!tmpl_expr_eval_internal (stmt, scope, &last, error))
{
TMPL_CLEAR_VALUE (&last);
return FALSE;
}
}
*return_value = last;
return TRUE;
}
static gboolean
tmpl_expr_args_eval (TmplExprSimple *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue left = G_VALUE_INIT;
gboolean ret = FALSE;
if (!tmpl_expr_eval_internal (node->left, scope, &left, error))
goto cleanup;
if (!tmpl_expr_eval_internal (node->left, scope, return_value, error))
goto cleanup;
ret = TRUE;
cleanup:
TMPL_CLEAR_VALUE (&left);
return ret;
}
static gboolean
tmpl_expr_symbol_ref_eval (TmplExprSymbolRef *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
TmplSymbol *symbol;
g_assert (node != NULL);
g_assert (scope != NULL);
symbol = tmpl_scope_peek (scope, node->symbol);
if (symbol == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_MISSING_SYMBOL,
"No such symbol \"%s\" in scope",
node->symbol);
return FALSE;
}
if (tmpl_symbol_get_symbol_type (symbol) == TMPL_SYMBOL_VALUE)
{
tmpl_symbol_get_value (symbol, return_value);
return TRUE;
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_A_VALUE,
"The symbol \"%s\" is not a value",
node->symbol);
return FALSE;
}
static gboolean
tmpl_expr_symbol_assign_eval (TmplExprSymbolAssign *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
TmplSymbol *symbol;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
if (!tmpl_expr_eval_internal (node->right, scope, return_value, error))
return FALSE;
symbol = tmpl_scope_get (scope, node->symbol);
tmpl_symbol_assign_value (symbol, return_value);
return TRUE;
}
static gboolean
tmpl_expr_getattr_eval (TmplExprGetattr *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue left = G_VALUE_INIT;
GParamSpec *pspec;
GObject *object;
gboolean ret = FALSE;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
if (!tmpl_expr_eval_internal (node->left, scope, &left, error))
goto cleanup;
if (G_VALUE_HOLDS (&left, TMPL_TYPE_TYPELIB) &&
g_value_get_pointer (&left) != NULL)
{
GIRepository *repository = tmpl_repository_get_default ();
GITypelib *typelib = g_value_get_pointer (&left);
const gchar *ns = gi_typelib_get_namespace (typelib);
GIBaseInfo *base_info;
/* Maybe we can resolve this dot accessor (.foo) using GObject
* Introspection from the first object.
*/
base_info = gi_repository_find_by_name (repository, ns, node->attr);
if (base_info == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_GI_FAILURE,
"Failed to locate %s within %s",
node->attr, ns);
goto cleanup;
}
g_value_init (return_value, TMPL_TYPE_BASE_INFO);
g_value_take_boxed (return_value, base_info);
ret = TRUE;
goto cleanup;
}
if (!G_VALUE_HOLDS_OBJECT (&left))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_AN_OBJECT,
"Cannot access property \"%s\" of non-object \"%s\"",
node->attr, G_VALUE_TYPE_NAME (&left));
goto cleanup;
}
object = g_value_get_object (&left);
if (object == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NULL_POINTER,
"Cannot access property of null object");
goto cleanup;
}
if (!(pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), node->attr)))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NO_SUCH_PROPERTY,
"No such property \"%s\" on object \"%s\"",
node->attr, G_OBJECT_TYPE_NAME (object));
goto cleanup;
}
g_value_init (return_value, pspec->value_type);
g_object_get_property (object, node->attr, return_value);
ret = TRUE;
cleanup:
TMPL_CLEAR_VALUE (&left);
return ret;
}
static gboolean
tmpl_expr_setattr_eval (TmplExprSetattr *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue left = G_VALUE_INIT;
GValue right = G_VALUE_INIT;
GObject *object;
gboolean ret = FALSE;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
if (!tmpl_expr_eval_internal (node->left, scope, &left, error))
goto cleanup;
if (!G_VALUE_HOLDS_OBJECT (&left))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_AN_OBJECT,
"Cannot access property \"%s\" of non-object \"%s\"",
node->attr, G_VALUE_TYPE_NAME (&left));
goto cleanup;
}
object = g_value_get_object (&left);
if (object == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NULL_POINTER,
"Cannot access property of null object");
goto cleanup;
}
if (!g_object_class_find_property (G_OBJECT_GET_CLASS (object), node->attr))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NO_SUCH_PROPERTY,
"No such property \"%s\" on object \"%s\"",
node->attr, G_OBJECT_TYPE_NAME (object));
goto cleanup;
}
if (!tmpl_expr_eval_internal (node->right, scope, &right, error))
goto cleanup;
g_object_set_property (object, node->attr, &right);
g_value_init (return_value, G_VALUE_TYPE (&right));
g_value_copy (&right, return_value);
ret = TRUE;
cleanup:
TMPL_CLEAR_VALUE (&left);
TMPL_CLEAR_VALUE (&right);
g_assert (ret == TRUE || (error == NULL || *error != NULL));
return ret;
}
/* Based on gtkbuilderscope.c */
static char *
make_mangle (const char *name)
{
gboolean split_first_cap = TRUE;
GString *symbol_name = g_string_new ("");
int i;
for (i = 0; name[i] != '\0'; i++)
{
/* skip if uppercase, first or previous is uppercase */
if ((name[i] == g_ascii_toupper (name[i]) &&
((i > 0 && name[i-1] != g_ascii_toupper (name[i-1])) ||
(i == 1 && name[0] == g_ascii_toupper (name[0]) && split_first_cap))) ||
(i > 2 && name[i] == g_ascii_toupper (name[i]) &&
name[i-1] == g_ascii_toupper (name[i-1]) &&
name[i-2] == g_ascii_toupper (name[i-2])))
g_string_append_c (symbol_name, '_');
g_string_append_c (symbol_name, g_ascii_tolower (name[i]));
}
return g_string_free (symbol_name, FALSE);
}
static gchar *
make_title (const gchar *str)
{
GString *ret;
g_assert (str != NULL);
ret = g_string_new (NULL);
for (; *str; str = g_utf8_next_char (str))
{
gunichar ch = g_utf8_get_char (str);
if (!g_unichar_isalnum (ch))
{
if (ret->len && ret->str[ret->len - 1] != ' ')
g_string_append_c (ret, ' ');
continue;
}
if (ret->len && ret->str[ret->len - 1] != ' ')
g_string_append_unichar (ret, ch);
else
g_string_append_unichar (ret, g_unichar_toupper (ch));
}
return g_string_free (ret, FALSE);
}
static GIBaseInfo *
find_by_gtype (GIRepository *repository,
GType type)
{
while ((type != G_TYPE_INVALID))
{
GIBaseInfo *info = gi_repository_find_by_gtype (repository, type);
if (info != NULL)
return info;
type = g_type_parent (type);
}
return NULL;
}
static gboolean
tmpl_expr_gi_call_eval (TmplExprGiCall *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GValue left = G_VALUE_INIT;
GValue right = G_VALUE_INIT;
GIRepository *repository;
GIBaseInfo *base_info;
GIFunctionInfo *function = NULL;
GIArgument return_value_arg = { 0 };
GITypeInfo return_value_type;
GIArgument *dispatch_args = NULL;
GITransfer xfer = 0;
TmplExpr *args;
GObject *object;
gboolean ret = FALSE;
GArray *in_args = NULL;
GArray *values = NULL;
GType type;
guint dispatch_len = 0;
guint n_args;
guint offset = 0;
guint i;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
if (!tmpl_expr_eval_internal (node->object, scope, &left, error))
goto cleanup;
if (G_VALUE_HOLDS_STRING (&left))
{
const gchar *str = g_value_get_string (&left) ?: "";
/*
* TODO: This should be abstracted somewhere else rather than our G-I call.
* Basically we are adding useful string functions like:
*
* "foo".upper()
* "foo".lower()
* "foo".casefold()
* "foo".reverse()
* "foo".len()
* "foo".title()
*/
if (FALSE) {}
else if (g_str_equal (node->name, "upper"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, g_utf8_strup (str, -1));
ret = TRUE;
}
else if (g_str_equal (node->name, "lower"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, g_utf8_strdown (str, -1));
ret = TRUE;
}
else if (g_str_equal (node->name, "casefold"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, g_utf8_casefold (str, -1));
ret = TRUE;
}
else if (g_str_equal (node->name, "reverse"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, g_utf8_strreverse (str, -1));
ret = TRUE;
}
else if (g_str_equal (node->name, "len"))
{
g_value_init (return_value, G_TYPE_UINT);
g_value_set_uint (return_value, strlen (str));
ret = TRUE;
}
else if (g_str_equal (node->name, "escape"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, g_strescape (str, NULL));
ret = TRUE;
}
else if (g_str_equal (node->name, "escape_markup"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, g_markup_escape_text (str, -1));
ret = TRUE;
}
else if (g_str_equal (node->name, "space"))
{
gchar *space;
guint len = strlen (str);
g_value_init (return_value, G_TYPE_STRING);
space = g_malloc (len + 1);
memset (space, ' ', len);
space[len] = '\0';
g_value_take_string (return_value, space);
ret = TRUE;
}
else if (g_str_equal (node->name, "title"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, make_title (str));
ret = TRUE;
}
else if (g_str_equal (node->name, "mangle"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, make_mangle (str));
ret = TRUE;
}
else
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_GI_FAILURE,
"No such method %s for string",
node->name);
}
goto cleanup;
}
if (G_VALUE_HOLDS_ENUM (&left))
{
if (FALSE) {}
else if (g_str_equal (node->name, "nick"))
{
GEnumClass *enum_class = g_type_class_peek (G_VALUE_TYPE (&left));
GEnumValue *enum_value = g_enum_get_value (enum_class, g_value_get_enum (&left));
g_value_init (return_value, G_TYPE_STRING);
if (enum_value != NULL)
g_value_set_static_string (return_value, enum_value->value_nick);
ret = TRUE;
}
else
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_GI_FAILURE,
"No such method %s for enum",
node->name);
}
goto cleanup;
}
if (G_VALUE_HOLDS_GTYPE (&left))
{
if (FALSE) {}
else if (g_str_equal (node->name, "name"))
{
g_value_init (return_value, G_TYPE_STRING);
g_value_set_static_string (return_value, g_type_name (g_value_get_gtype (&left)));
ret = TRUE;
goto cleanup;
}
else if (g_str_equal (node->name, "is_a"))
{
if (node->params != NULL)
{
GValue param1 = G_VALUE_INIT;
if (!tmpl_expr_eval_internal (node->params, scope, ¶m1, error))
goto cleanup;
if (!G_VALUE_HOLDS_GTYPE (¶m1))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_TYPE_MISMATCH,
"%s is not a GType",
G_VALUE_TYPE_NAME (¶m1));
TMPL_CLEAR_VALUE (¶m1);
goto cleanup;
}
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value,
g_type_is_a (g_value_get_gtype (&left),
g_value_get_gtype (¶m1)));
TMPL_CLEAR_VALUE (¶m1);
ret = TRUE;
goto cleanup;
}
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_GI_FAILURE,
"No such method %s of GType",
node->name);
goto cleanup;
}
repository = tmpl_repository_get_default ();
if (G_VALUE_HOLDS (&left, TMPL_TYPE_TYPELIB) &&
g_value_get_pointer (&left) != NULL)
{
GITypelib *typelib = g_value_get_pointer (&left);
const gchar *ns = gi_typelib_get_namespace (typelib);
base_info = gi_repository_find_by_name (repository, ns, node->name);
if (base_info == NULL || !GI_IS_FUNCTION_INFO (base_info))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_GI_FAILURE,
"%s is not a function in %s",
node->name, ns);
goto cleanup;
}
function = (GIFunctionInfo *)base_info;
n_args = gi_callable_info_get_n_args ((GICallableInfo *)function);
values = g_array_new (FALSE, TRUE, sizeof (GValue));
g_array_set_clear_func (values, (GDestroyNotify)g_value_unset);
g_array_set_size (values, n_args);
in_args = g_array_new (FALSE, TRUE, sizeof (GIArgument));
g_array_set_size (in_args, n_args + 1);
/* Skip past first param, which is used for Object below */
dispatch_args = ((GIArgument *)(gpointer)in_args->data);
dispatch_len = n_args;
goto apply_args;
}
if (G_VALUE_HOLDS (&left, TMPL_TYPE_BASE_INFO) &&
(base_info = g_value_get_boxed (&left)) &&
GI_IS_OBJECT_INFO (base_info))
{
TmplGTypeFunc gtype_func = tmpl_gi_get_gtype_func (base_info);
if (gtype_func != NULL &&
(type = gtype_func ()) &&
g_type_is_a (type, G_TYPE_OBJECT))
{
object = NULL;
goto lookup_for_object;
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_AN_OBJECT,
"Failed to locate GType function for object");
goto cleanup;
}
if (!G_VALUE_HOLDS_OBJECT (&left))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_AN_OBJECT,
"Cannot access function \"%s\" of non-object \"%s\"",
node->name, G_VALUE_TYPE_NAME (&left));
goto cleanup;
}
object = g_value_get_object (&left);
if (object == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NULL_POINTER,
"Cannot access function of null object");
goto cleanup;
}
type = G_OBJECT_TYPE (object);
lookup_for_object:
while (g_type_is_a (type, G_TYPE_OBJECT))
{
guint n_ifaces;
base_info = find_by_gtype (repository, type);
if (base_info == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_GI_FAILURE,
"Failed to locate GObject Introspection data for %s. "
"Consider importing required module.",
g_type_name (type));
goto cleanup;
}
/* First locate the function in the object */
function = gi_object_info_find_method ((GIObjectInfo *)base_info, node->name);
if (function != NULL)
break;
/* Maybe the function is found in an interface */
n_ifaces = gi_object_info_get_n_interfaces ((GIObjectInfo *)base_info);
for (i = 0; function == NULL && i < n_ifaces; i++)
{
GIInterfaceInfo *iface_info = NULL;
iface_info = gi_object_info_get_interface ((GIObjectInfo *)base_info, i);
function = gi_interface_info_find_method (iface_info, node->name);
g_clear_pointer (&iface_info, gi_base_info_unref);
}
if (function != NULL)
break;
type = g_type_parent (type);
}
if (function == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_GI_FAILURE,
"No such method \"%s\" on object \"%s\"",
node->name, G_OBJECT_TYPE_NAME (object));
goto cleanup;
}
n_args = gi_callable_info_get_n_args ((GICallableInfo *)function);
values = g_array_new (FALSE, TRUE, sizeof (GValue));
g_array_set_clear_func (values, (GDestroyNotify)g_value_unset);
g_array_set_size (values, n_args);
in_args = g_array_new (FALSE, TRUE, sizeof (GIArgument));
g_array_set_size (in_args, n_args + 1);
if (object != NULL)
{
g_array_index (in_args, GIArgument, 0).v_pointer = object;
offset = 1;
}
else
{
in_args->len--;
}
dispatch_args = (GIArgument *)(gpointer)in_args->data;
dispatch_len = in_args->len;
apply_args:
args = node->params;
for (i = 0; i < n_args; i++)
{
g_autoptr(GIArgInfo) arg_info = gi_callable_info_get_arg ((GICallableInfo *)function, i);
GIArgument *arg = &g_array_index (in_args, GIArgument, i + offset);
GValue *value = &g_array_index (values, GValue, i);
GITypeInfo type_info = { 0 };
if (gi_arg_info_get_direction (arg_info) != GI_DIRECTION_IN)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_RUNTIME_ERROR,
"Only \"in\" parameters are supported");
goto cleanup;
}
if (args == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Too few arguments to function \"%s\"",
node->name);
goto cleanup;
}
if (args->any.type == TMPL_EXPR_ARGS)
{
if (!tmpl_expr_eval_internal (((TmplExprSimple *)args)->left, scope, value, error))
goto cleanup;
args = ((TmplExprSimple *)args)->right;
}
else
{
if (!tmpl_expr_eval_internal (args, scope, value, error))
goto cleanup;
args = NULL;
}
gi_arg_info_load_type_info (arg_info, &type_info);
if (!tmpl_gi_argument_from_g_value (value, &type_info, arg_info, arg, error))
{
gi_base_info_clear (&type_info);
goto cleanup;
}
gi_base_info_clear (&type_info);
}
if ((args != NULL) && (n_args > 0))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Too many arguments to function \"%s\"",
node->name);
goto cleanup;
}
if (!gi_function_info_invoke (function,
dispatch_args,
dispatch_len,
NULL,
0,
&return_value_arg,
error))
goto cleanup;
gi_callable_info_load_return_type ((GICallableInfo *)function, &return_value_type);
xfer = gi_callable_info_get_caller_owns ((GICallableInfo *)function);
ret = tmpl_gi_argument_to_g_value (return_value, &return_value_type, &return_value_arg, xfer, error);
gi_base_info_clear (&return_value_type);
cleanup:
g_clear_pointer (&in_args, g_array_unref);
if (values != NULL)
{
for (i = 0; i < values->len; i++)
{
GValue *value = &g_array_index (values, GValue, i);
if (G_VALUE_TYPE (value) != G_TYPE_INVALID)
g_value_unset (value);
}
g_clear_pointer (&values, g_array_unref);
}
TMPL_CLEAR_VALUE (&left);
TMPL_CLEAR_VALUE (&right);
g_clear_pointer (&function, gi_base_info_unref);
return ret;
}
static gboolean
tmpl_expr_anon_fn_call_eval (TmplExprAnonFnCall *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
char **args;
TmplExpr *params = NULL;
TmplScope *local_scope = NULL;
gboolean ret = FALSE;
gint n_args = 0;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
if (node->anon->any.type != TMPL_EXPR_FUNC)
{
g_set_error_literal (error,
TMPL_ERROR,
TMPL_ERROR_NOT_A_FUNCTION,
"Not a function to evaluate");
return FALSE;
}
args = node->anon->func.symlist;
n_args = args ? g_strv_length (args) : 0;
local_scope = tmpl_scope_new_with_parent (scope);
params = node->params;
for (guint i = 0; i < n_args; i++)
{
const gchar *arg = args[i];
GValue value = G_VALUE_INIT;
if (params == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Function takes %d arguments, got %d",
n_args, i);
return FALSE;
}
if (params->any.type == TMPL_EXPR_ARGS)
{
TmplExprSimple *simple = (TmplExprSimple *)params;
if (!tmpl_expr_eval_internal (simple->left, local_scope, &value, error))
goto cleanup;
params = simple->right;
}
else
{
if (!tmpl_expr_eval_internal (params, local_scope, &value, error))
goto cleanup;
params = NULL;
}
tmpl_scope_set_value (local_scope, arg, &value);
TMPL_CLEAR_VALUE (&value);
}
if (params != NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Function takes %d params",
n_args);
goto cleanup;
}
if (!tmpl_expr_eval_internal (node->anon, local_scope, return_value, error))
goto cleanup;
ret = TRUE;
cleanup:
g_clear_pointer (&local_scope, tmpl_scope_unref);
return ret;
}
static gboolean
tmpl_expr_user_fn_call_eval (TmplExprUserFnCall *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GPtrArray *args_ar = NULL;
TmplExpr *expr = NULL;
TmplExpr *params = NULL;
TmplScope *local_scope = NULL;
TmplSymbol *symbol;
const char * const *args = NULL;
gboolean ret = FALSE;
gint n_args = 0;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
symbol = tmpl_scope_peek (scope, node->symbol);
if (symbol == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_MISSING_SYMBOL,
"No such function \"%s\"",
node->symbol);
return FALSE;
}
if (tmpl_symbol_get_symbol_type (symbol) != TMPL_SYMBOL_EXPR)
{
/* Check for anonymous function */
if (tmpl_symbol_holds (symbol, TMPL_TYPE_EXPR) &&
(expr = tmpl_symbol_get_boxed (symbol)) &&
expr->any.type == TMPL_EXPR_FUNC)
{
args = (const char * const *)expr->func.symlist;
n_args = args ? g_strv_length ((char **)args) : 0;
expr = expr->func.list;
goto prepare;
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_A_FUNCTION,
"\"%s\" is not a function within scope",
node->symbol);
return FALSE;
}
expr = tmpl_symbol_get_expr (symbol, &args_ar);
if (args_ar == NULL)
n_args = 0, args = NULL;
else
n_args = args_ar->len, args = (const char * const *)(gpointer)args_ar->pdata;
prepare:
g_assert (expr != NULL);
g_assert (n_args == 0 || args != NULL);
local_scope = tmpl_scope_new_with_parent (scope);
params = node->params;
for (guint i = 0; i < n_args; i++)
{
const gchar *arg = args[i];
GValue value = G_VALUE_INIT;
g_assert (arg != NULL);
if (params == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"\"%s\" takes %d arguments, not %d",
node->symbol, n_args, i);
return FALSE;
}
if (params->any.type == TMPL_EXPR_ARGS)
{
TmplExprSimple *simple = (TmplExprSimple *)params;
if (!tmpl_expr_eval_internal (simple->left, local_scope, &value, error))
goto cleanup;
params = simple->right;
}
else
{
if (!tmpl_expr_eval_internal (params, local_scope, &value, error))
goto cleanup;
params = NULL;
}
symbol = tmpl_scope_get (local_scope, arg);
tmpl_symbol_assign_value (symbol, &value);
TMPL_CLEAR_VALUE (&value);
}
if (params != NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"\"%s\" takes %d params",
node->symbol, n_args);
goto cleanup;
}
if (!tmpl_expr_eval_internal (expr, local_scope, return_value, error))
goto cleanup;
ret = TRUE;
cleanup:
g_clear_pointer (&local_scope, tmpl_scope_unref);
return ret;
}
static gboolean
tmpl_expr_require_eval (TmplExprRequire *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GITypelib *typelib;
GError *local_error = NULL;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
typelib = gi_repository_require (tmpl_repository_get_default (),
node->name,
node->version,
0,
&local_error);
g_assert (typelib != NULL || local_error != NULL);
if (typelib == NULL)
{
g_propagate_error (error, local_error);
return FALSE;
}
g_value_init (return_value, TMPL_TYPE_TYPELIB);
g_value_set_pointer (return_value, typelib);
tmpl_scope_set_value (scope, node->name, return_value);
return TRUE;
}
static gboolean
tmpl_expr_func_eval (TmplExprFunc *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
GPtrArray *args = NULL;
TmplSymbol *symbol;
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
/* We just need to insert a symbol into @scope that includes
* the function defined here. If the symbol already exists,
* it will be replaced with this function.
*/
if (node->symlist != NULL)
{
args = g_ptr_array_new_with_free_func (g_free);
for (guint i = 0; node->symlist[i]; i++)
g_ptr_array_add (args, g_strdup (node->symlist[i]));
}
if (node->name != NULL)
{
symbol = tmpl_scope_get (scope, node->name);
tmpl_symbol_assign_expr (symbol, node->list, args);
g_clear_pointer (&args, g_ptr_array_unref);
}
else
{
g_value_init (return_value, TMPL_TYPE_EXPR);
g_value_set_boxed (return_value, node);
}
g_clear_pointer (&args, g_ptr_array_unref);
return TRUE;
}
static gboolean
tmpl_expr_eval_internal (TmplExpr *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
g_assert (node != NULL);
g_assert (scope != NULL);
g_assert (return_value != NULL);
switch (node->any.type)
{
case TMPL_EXPR_ADD:
case TMPL_EXPR_SUB:
case TMPL_EXPR_MUL:
case TMPL_EXPR_DIV:
case TMPL_EXPR_UNARY_MINUS:
case TMPL_EXPR_GT:
case TMPL_EXPR_LT:
case TMPL_EXPR_NE:
case TMPL_EXPR_EQ:
case TMPL_EXPR_GTE:
case TMPL_EXPR_LTE:
return tmpl_expr_simple_eval ((TmplExprSimple *)node, scope, return_value, error);
case TMPL_EXPR_AND:
case TMPL_EXPR_OR:
return tmpl_expr_simple_eval_logical ((TmplExprSimple *)node, scope, return_value, error);
case TMPL_EXPR_NUMBER:
g_value_init (return_value, G_TYPE_DOUBLE);
g_value_set_double (return_value, ((TmplExprNumber *)node)->number);
return TRUE;
case TMPL_EXPR_BOOLEAN:
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value, ((TmplExprBoolean *)node)->value);
return TRUE;
case TMPL_EXPR_STRING:
g_value_init (return_value, G_TYPE_STRING);
g_value_set_string (return_value, ((TmplExprString *)node)->value);
return TRUE;
case TMPL_EXPR_ARGS:
return tmpl_expr_args_eval ((TmplExprSimple *)node, scope, return_value, error);
case TMPL_EXPR_STMT_LIST:
return tmpl_expr_stmt_list_eval ((TmplExprStmtList *)node, scope, return_value, error);
case TMPL_EXPR_IF:
case TMPL_EXPR_WHILE:
return tmpl_expr_flow_eval ((TmplExprFlow *)node, scope, return_value, error);
case TMPL_EXPR_SYMBOL_REF:
return tmpl_expr_symbol_ref_eval ((TmplExprSymbolRef *)node, scope, return_value, error);
case TMPL_EXPR_SYMBOL_ASSIGN:
return tmpl_expr_symbol_assign_eval ((TmplExprSymbolAssign *)node, scope, return_value, error);
case TMPL_EXPR_FN_CALL:
return tmpl_expr_fn_call_eval ((TmplExprFnCall *)node, scope, return_value, error);
case TMPL_EXPR_ANON_FN_CALL:
return tmpl_expr_anon_fn_call_eval ((TmplExprAnonFnCall *)node, scope, return_value, error);
case TMPL_EXPR_USER_FN_CALL:
return tmpl_expr_user_fn_call_eval ((TmplExprUserFnCall *)node, scope, return_value, error);
case TMPL_EXPR_GI_CALL:
return tmpl_expr_gi_call_eval ((TmplExprGiCall *)node, scope, return_value, error);
case TMPL_EXPR_GETATTR:
return tmpl_expr_getattr_eval ((TmplExprGetattr *)node, scope, return_value, error);
case TMPL_EXPR_SETATTR:
return tmpl_expr_setattr_eval ((TmplExprSetattr *)node, scope, return_value, error);
case TMPL_EXPR_REQUIRE:
return tmpl_expr_require_eval ((TmplExprRequire *)node, scope, return_value, error);
case TMPL_EXPR_INVERT_BOOLEAN:
{
GValue tmp = G_VALUE_INIT;
gboolean ret;
ret = tmpl_expr_eval_internal (((TmplExprSimple *)node)->left, scope, &tmp, error);
if (ret)
{
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value, !tmpl_value_as_boolean (&tmp));
}
TMPL_CLEAR_VALUE (&tmp);
g_assert (ret == TRUE || (error == NULL || *error != NULL));
return ret;
}
case TMPL_EXPR_FUNC:
return tmpl_expr_func_eval ((TmplExprFunc *)node, scope, return_value, error);
case TMPL_EXPR_NOP:
return TRUE;
case TMPL_EXPR_NULL:
g_value_init (return_value, G_TYPE_POINTER);
g_value_set_pointer (return_value, NULL);
return TRUE;
default:
break;
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_INVALID_OP_CODE,
"invalid opcode: %04x", node->any.type);
return FALSE;
}
static gboolean
div_double_double (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
gdouble denom = g_value_get_double (right);
if (denom == 0.0)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_DIVIDE_BY_ZERO,
"divide by zero");
return FALSE;
}
g_value_init (return_value, G_TYPE_DOUBLE);
g_value_set_double (return_value, g_value_get_double (left) / denom);
return TRUE;
}
static gboolean
unary_minus_double (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_DOUBLE);
g_value_set_double (return_value, -g_value_get_double (left));
return TRUE;
}
static gboolean
mul_double_string (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
GString *str;
gint v;
gint i;
str = g_string_new (NULL);
v = g_value_get_double (left);
for (i = 0; i < v; i++)
g_string_append (str, g_value_get_string (right));
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, g_string_free (str, FALSE));
return TRUE;
}
static gboolean
mul_string_double (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
return mul_double_string (right, left, return_value, error);
}
static gboolean
add_string_string (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value,
g_strdup_printf ("%s%s",
g_value_get_string (left),
g_value_get_string (right)));
return TRUE;
}
static gboolean
add_string_string_slow (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
GValue trans = G_VALUE_INIT;
g_value_init (&trans, G_TYPE_STRING);
g_value_init (return_value, G_TYPE_STRING);
if (G_VALUE_HOLDS_STRING (left))
{
if (!g_value_transform (right, &trans))
return FALSE;
right = &trans;
}
else
{
if (!g_value_transform (left, &trans))
return FALSE;
left = &trans;
}
g_value_take_string (return_value,
g_strdup_printf ("%s%s",
g_value_get_string (left),
g_value_get_string (right)));
return TRUE;
}
static gboolean
eq_string_string (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
const gchar *left_str = g_value_get_string (left);
const gchar *right_str = g_value_get_string (right);
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value, 0 == g_strcmp0 (left_str, right_str));
return TRUE;
}
static gboolean
ne_string_string (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
const gchar *left_str = g_value_get_string (left);
const gchar *right_str = g_value_get_string (right);
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value, 0 != g_strcmp0 (left_str, right_str));
return TRUE;
}
static gboolean
eq_boolean_boolean (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value,
g_value_get_boolean (left) == g_value_get_boolean (right));
return TRUE;
}
static gboolean
ne_boolean_boolean (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value,
g_value_get_boolean (left) != g_value_get_boolean (right));
return TRUE;
}
static gboolean
eq_pointer_pointer (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value,
g_value_get_pointer (left) == g_value_get_pointer (right));
return TRUE;
}
static gboolean
ne_pointer_pointer (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value,
g_value_get_pointer (left) != g_value_get_pointer (right));
return TRUE;
}
static gboolean
eq_enum_string (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
const gchar *str;
GEnumClass *klass;
const GEnumValue *val;
GType type;
gint eval;
if (G_VALUE_HOLDS_STRING (left))
{
str = g_value_get_string (left);
eval = g_value_get_enum (right);
type = G_VALUE_TYPE (right);
}
else
{
str = g_value_get_string (right);
eval = g_value_get_enum (left);
type = G_VALUE_TYPE (left);
}
klass = g_type_class_peek (type);
val = g_enum_get_value ((GEnumClass *)klass, eval);
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value, 0 == g_strcmp0 (str, val->value_nick));
return TRUE;
}
static gboolean
ne_enum_string (const GValue *left,
const GValue *right,
GValue *return_value,
GError **error)
{
if (eq_enum_string (left, right, return_value, error))
{
g_value_set_boolean (return_value, !g_value_get_boolean (return_value));
return TRUE;
}
return FALSE;
}
#define SIMPLE_OP_FUNC(func_name, ret_type, set_func, get_left, op, get_right) \
static gboolean \
func_name (const GValue *left, \
const GValue *right, \
GValue *return_value, \
GError **error) \
{ \
g_value_init (return_value, ret_type); \
g_value_##set_func (return_value, \
g_value_##get_left (left) \
op \
g_value_##get_right (right)); \
return TRUE; \
}
SIMPLE_OP_FUNC (add_double_double, G_TYPE_DOUBLE, set_double, get_double, +, get_double)
SIMPLE_OP_FUNC (sub_double_double, G_TYPE_DOUBLE, set_double, get_double, -, get_double)
SIMPLE_OP_FUNC (mul_double_double, G_TYPE_DOUBLE, set_double, get_double, *, get_double)
SIMPLE_OP_FUNC (lt_double_double, G_TYPE_BOOLEAN, set_boolean, get_double, <, get_double)
SIMPLE_OP_FUNC (lte_double_double, G_TYPE_BOOLEAN, set_boolean, get_double, <=, get_double)
SIMPLE_OP_FUNC (gt_double_double, G_TYPE_BOOLEAN, set_boolean, get_double, >, get_double)
SIMPLE_OP_FUNC (eq_double_double, G_TYPE_BOOLEAN, set_boolean, get_double, ==, get_double)
SIMPLE_OP_FUNC (ne_double_double, G_TYPE_BOOLEAN, set_boolean, get_double, !=, get_double)
SIMPLE_OP_FUNC (gte_double_double, G_TYPE_BOOLEAN, set_boolean, get_double, >=, get_double)
SIMPLE_OP_FUNC (eq_double_int, G_TYPE_BOOLEAN, set_boolean, get_double, ==, get_int)
SIMPLE_OP_FUNC (eq_double_uint, G_TYPE_BOOLEAN, set_boolean, get_double, ==, get_uint)
SIMPLE_OP_FUNC (eq_int_double, G_TYPE_BOOLEAN, set_boolean, get_int, ==, get_double)
SIMPLE_OP_FUNC (eq_uint_double, G_TYPE_BOOLEAN, set_boolean, get_uint, ==, get_double)
SIMPLE_OP_FUNC (gt_double_int, G_TYPE_BOOLEAN, set_boolean, get_double, >, get_int)
SIMPLE_OP_FUNC (gt_double_uint, G_TYPE_BOOLEAN, set_boolean, get_double, >, get_uint)
SIMPLE_OP_FUNC (gt_int_double, G_TYPE_BOOLEAN, set_boolean, get_int, >, get_double)
SIMPLE_OP_FUNC (gt_uint_double, G_TYPE_BOOLEAN, set_boolean, get_uint, >, get_double)
SIMPLE_OP_FUNC (lt_double_int, G_TYPE_BOOLEAN, set_boolean, get_double, <, get_int)
SIMPLE_OP_FUNC (lt_double_uint, G_TYPE_BOOLEAN, set_boolean, get_double, <, get_uint)
SIMPLE_OP_FUNC (lt_int_double, G_TYPE_BOOLEAN, set_boolean, get_int, <, get_double)
SIMPLE_OP_FUNC (lt_uint_double, G_TYPE_BOOLEAN, set_boolean, get_uint, <, get_double)
SIMPLE_OP_FUNC (ne_double_int, G_TYPE_BOOLEAN, set_boolean, get_double, !=, get_uint)
SIMPLE_OP_FUNC (ne_double_uint, G_TYPE_BOOLEAN, set_boolean, get_double, !=, get_uint)
SIMPLE_OP_FUNC (ne_int_double, G_TYPE_BOOLEAN, set_boolean, get_uint, !=, get_double)
SIMPLE_OP_FUNC (ne_uint_double, G_TYPE_BOOLEAN, set_boolean, get_uint, !=, get_double)
#undef SIMPLE_OP_FUNC
static GHashTable *
build_dispatch_table (void)
{
GHashTable *table;
table = g_hash_table_new (NULL, NULL);
#define ADD_DISPATCH_FUNC(type, left, right, func) \
g_hash_table_insert(table, \
GINT_TO_POINTER(build_hash(type, left, right)),\
func)
ADD_DISPATCH_FUNC (TMPL_EXPR_ADD, G_TYPE_DOUBLE, G_TYPE_DOUBLE, add_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_ADD, G_TYPE_STRING, G_TYPE_STRING, add_string_string);
ADD_DISPATCH_FUNC (TMPL_EXPR_SUB, G_TYPE_DOUBLE, G_TYPE_DOUBLE, sub_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_MUL, G_TYPE_DOUBLE, G_TYPE_DOUBLE, mul_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_DIV, G_TYPE_DOUBLE, G_TYPE_DOUBLE, div_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_UNARY_MINUS, G_TYPE_DOUBLE, 0, unary_minus_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_LT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, lt_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_GT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, gt_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_NE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, ne_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_LTE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, lte_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_GTE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, gte_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_EQ, G_TYPE_DOUBLE, G_TYPE_DOUBLE, eq_double_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_MUL, G_TYPE_STRING, G_TYPE_DOUBLE, mul_string_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_MUL, G_TYPE_DOUBLE, G_TYPE_STRING, mul_double_string);
ADD_DISPATCH_FUNC (TMPL_EXPR_EQ, G_TYPE_STRING, G_TYPE_STRING, eq_string_string);
ADD_DISPATCH_FUNC (TMPL_EXPR_NE, G_TYPE_STRING, G_TYPE_STRING, ne_string_string);
ADD_DISPATCH_FUNC (TMPL_EXPR_EQ, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, eq_boolean_boolean);
ADD_DISPATCH_FUNC (TMPL_EXPR_NE, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, ne_boolean_boolean);
ADD_DISPATCH_FUNC (TMPL_EXPR_EQ, G_TYPE_POINTER, G_TYPE_POINTER, eq_pointer_pointer);
ADD_DISPATCH_FUNC (TMPL_EXPR_NE, G_TYPE_POINTER, G_TYPE_POINTER, ne_pointer_pointer);
ADD_DISPATCH_FUNC (TMPL_EXPR_EQ, G_TYPE_UINT, G_TYPE_DOUBLE, eq_uint_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_EQ, G_TYPE_DOUBLE, G_TYPE_UINT, eq_double_uint);
ADD_DISPATCH_FUNC (TMPL_EXPR_NE, G_TYPE_UINT, G_TYPE_DOUBLE, ne_uint_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_NE, G_TYPE_DOUBLE, G_TYPE_UINT, ne_double_uint);
ADD_DISPATCH_FUNC (TMPL_EXPR_GT, G_TYPE_UINT, G_TYPE_DOUBLE, gt_uint_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_GT, G_TYPE_DOUBLE, G_TYPE_UINT, gt_double_uint);
ADD_DISPATCH_FUNC (TMPL_EXPR_LT, G_TYPE_UINT, G_TYPE_DOUBLE, lt_uint_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_LT, G_TYPE_DOUBLE, G_TYPE_UINT, lt_double_uint);
ADD_DISPATCH_FUNC (TMPL_EXPR_EQ, G_TYPE_INT, G_TYPE_DOUBLE, eq_int_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_EQ, G_TYPE_DOUBLE, G_TYPE_INT, eq_double_int);
ADD_DISPATCH_FUNC (TMPL_EXPR_NE, G_TYPE_INT, G_TYPE_DOUBLE, ne_int_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_NE, G_TYPE_DOUBLE, G_TYPE_INT, ne_double_int);
ADD_DISPATCH_FUNC (TMPL_EXPR_GT, G_TYPE_INT, G_TYPE_DOUBLE, gt_int_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_GT, G_TYPE_DOUBLE, G_TYPE_INT, gt_double_int);
ADD_DISPATCH_FUNC (TMPL_EXPR_LT, G_TYPE_INT, G_TYPE_DOUBLE, lt_int_double);
ADD_DISPATCH_FUNC (TMPL_EXPR_LT, G_TYPE_DOUBLE, G_TYPE_INT, lt_double_int);
#undef ADD_DISPATCH_FUNC
return table;
}
gboolean
tmpl_expr_eval (TmplExpr *node,
TmplScope *scope,
GValue *return_value,
GError **error)
{
gboolean ret;
g_return_val_if_fail (node != NULL, FALSE);
g_return_val_if_fail (scope != NULL, FALSE);
g_return_val_if_fail (return_value != NULL, FALSE);
g_return_val_if_fail (G_VALUE_TYPE (return_value) == G_TYPE_INVALID, FALSE);
if (g_once_init_enter (&fast_dispatch))
g_once_init_leave (&fast_dispatch, build_dispatch_table ());
ret = tmpl_expr_eval_internal (node, scope, return_value, error);
g_assert (ret == TRUE || (error == NULL || *error != NULL));
return ret;
}
static gboolean
builtin_abs (const GValue *value,
GValue *return_value,
GError **error)
{
char *errmsg;
if (G_VALUE_HOLDS_DOUBLE (value))
{
g_value_init (return_value, G_TYPE_DOUBLE);
g_value_set_double (return_value, ABS (g_value_get_double (value)));
return TRUE;
}
else if (G_VALUE_HOLDS_FLOAT (value))
{
g_value_init (return_value, G_TYPE_FLOAT);
g_value_set_float (return_value, ABS (g_value_get_float (value)));
return TRUE;
}
else if (G_VALUE_HOLDS_INT (value))
{
g_value_init (return_value, G_TYPE_INT);
g_value_set_int (return_value, ABS (g_value_get_int (value)));
return TRUE;
}
else if (G_VALUE_HOLDS_INT64 (value))
{
g_value_init (return_value, G_TYPE_INT64);
g_value_set_int64 (return_value, ABS (g_value_get_int64 (value)));
return TRUE;
}
else if (G_VALUE_HOLDS_UINT (value) ||
G_VALUE_HOLDS_UINT64 (value) ||
G_VALUE_HOLDS_UCHAR (value))
{
*return_value = *value;
return TRUE;
}
errmsg = g_strdup_printf ("Cannot abs() type %s", G_VALUE_TYPE_NAME (value));
throw_type_mismatch (error, value, NULL, errmsg);
g_free (errmsg);
return FALSE;
}
static gboolean
builtin_assert (const GValue *value,
GValue *return_value,
GError **error)
{
if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
goto failure;
if (G_VALUE_HOLDS_BOOLEAN (value))
{
if (g_value_get_boolean (value) == FALSE)
goto failure;
}
else if (G_VALUE_HOLDS_STRING (value))
{
if (g_value_get_string (value) == NULL)
goto failure;
}
else if (G_VALUE_HOLDS_POINTER (value))
{
if (g_value_get_pointer (value) == NULL)
goto failure;
}
else if (G_VALUE_HOLDS_OBJECT (value))
{
if (g_value_get_object (value) == NULL)
goto failure;
}
else if (G_VALUE_HOLDS_INT (value))
{
if (g_value_get_int (value) == 0)
goto failure;
}
else if (G_VALUE_HOLDS_UINT (value))
{
if (g_value_get_uint (value) == 0)
goto failure;
}
else if (G_VALUE_HOLDS_INT64 (value))
{
if (g_value_get_int64 (value) == 0)
goto failure;
}
else if (G_VALUE_HOLDS_UINT64 (value))
{
if (g_value_get_uint64 (value) == 0)
goto failure;
}
else if (G_VALUE_HOLDS_DOUBLE (value))
{
if (g_value_get_double (value) == .0)
goto failure;
}
else if (G_VALUE_HOLDS_FLOAT (value))
{
if (g_value_get_float (value) == .0f)
goto failure;
}
else if (G_VALUE_HOLDS_GTYPE (value))
{
if (g_value_get_gtype (value) == G_TYPE_INVALID)
goto failure;
}
else
{
goto failure;
}
return TRUE;
failure:
g_set_error_literal (error,
TMPL_ERROR,
TMPL_ERROR_RUNTIME_ERROR,
"Assertion failed");
return FALSE;
}
#define BUILTIN_MATH(func) \
static gboolean \
builtin_##func (const GValue *value, \
GValue *return_value, \
GError **error) \
{ \
GValue translated = G_VALUE_INIT; \
\
if (!G_VALUE_HOLDS_DOUBLE (value)) \
{ \
g_value_init (&translated, G_TYPE_DOUBLE); \
if (!g_value_transform (value, &translated)) \
{ \
g_set_error (error, \
TMPL_ERROR, \
TMPL_ERROR_RUNTIME_ERROR, \
"Cannot convert %s to double", \
G_VALUE_TYPE_NAME (value)); \
return FALSE; \
} \
value = &translated; \
} \
\
g_value_init (return_value, G_TYPE_DOUBLE); \
g_value_set_double (return_value, func (g_value_get_double (value))); \
return TRUE; \
}
BUILTIN_MATH (ceil)
BUILTIN_MATH (floor)
BUILTIN_MATH (log)
BUILTIN_MATH (sqrt)
BUILTIN_MATH (sin)
BUILTIN_MATH (tan)
BUILTIN_MATH (cos)
#define BUILTIN_CAST(func,type) \
static gboolean \
builtin_cast_##func (const GValue *value, \
GValue *return_value, \
GError **error) \
{ \
g_value_init (return_value, type); \
\
if (!g_value_transform (value, return_value)) \
{ \
g_set_error (error, \
TMPL_ERROR, \
TMPL_ERROR_RUNTIME_ERROR, \
"Cannot convert %s to %s", \
G_VALUE_TYPE_NAME (value), \
g_type_name (type)); \
return FALSE; \
} \
\
return TRUE; \
}
BUILTIN_CAST (byte, G_TYPE_UCHAR)
BUILTIN_CAST (char, G_TYPE_CHAR)
BUILTIN_CAST (i32, G_TYPE_INT)
BUILTIN_CAST (u32, G_TYPE_UINT)
BUILTIN_CAST (i64, G_TYPE_INT64)
BUILTIN_CAST (u64, G_TYPE_UINT64)
BUILTIN_CAST (float, G_TYPE_FLOAT)
BUILTIN_CAST (double, G_TYPE_DOUBLE)
static gboolean
builtin_cast_bool (const GValue *value,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_BOOLEAN);
#define BOOL_CAST(type, getter, compare) \
else if (G_VALUE_HOLDS (value, type)) \
g_value_set_boolean (return_value, g_value_get_##getter(value) != compare);
if (0) {}
BOOL_CAST (G_TYPE_BOOLEAN, boolean, FALSE)
BOOL_CAST (G_TYPE_DOUBLE, double, .0)
BOOL_CAST (G_TYPE_FLOAT, float, .0f)
BOOL_CAST (G_TYPE_INT, int, 0)
BOOL_CAST (G_TYPE_UINT, uint, 0)
BOOL_CAST (G_TYPE_CHAR, schar, 0)
BOOL_CAST (G_TYPE_UCHAR, uchar, 0)
BOOL_CAST (G_TYPE_STRING, string, NULL)
BOOL_CAST (G_TYPE_POINTER, pointer, NULL)
else if (!g_value_transform (value, return_value))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_RUNTIME_ERROR,
"Cannot convert %s to bool",
G_VALUE_TYPE_NAME (value));
return FALSE;
}
#undef BOOL_CAST
return TRUE;
}
static gboolean
builtin_print (const GValue *value,
GValue *return_value,
GError **error)
{
gchar *repr;
repr = tmpl_value_repr (value);
g_print ("%s\n", repr);
g_free (repr);
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value, TRUE);
return TRUE;
}
static gboolean
builtin_printerr (const GValue *value,
GValue *return_value,
GError **error)
{
gchar *repr;
repr = tmpl_value_repr (value);
g_printerr ("%s\n", repr);
g_free (repr);
g_value_init (return_value, G_TYPE_BOOLEAN);
g_value_set_boolean (return_value, TRUE);
return TRUE;
}
static gboolean
builtin_typeof (const GValue *value,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_GTYPE);
if (G_VALUE_HOLDS (value, TMPL_TYPE_BASE_INFO) &&
g_value_get_boxed (value) != NULL &&
GI_IS_REGISTERED_TYPE_INFO (g_value_get_boxed (value)))
g_value_set_gtype (return_value,
gi_registered_type_info_get_g_type (g_value_get_boxed (value)));
else if (G_VALUE_HOLDS_OBJECT (value) &&
g_value_get_object (value) != NULL)
g_value_set_gtype (return_value, G_OBJECT_TYPE (g_value_get_object (value)));
else
g_value_set_gtype (return_value, G_VALUE_TYPE (value));
return TRUE;
}
static gboolean
builtin_hex (const GValue *value,
GValue *return_value,
GError **error)
{
if (G_VALUE_HOLDS_DOUBLE (value))
{
gchar *str = g_strdup_printf ("0x%" G_GINT64_MODIFIER "x",
(gint64)g_value_get_double (value));
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, str);
return TRUE;
}
throw_type_mismatch (error, value, NULL, "requires number parameter");
return FALSE;
}
static gboolean
builtin_repr (const GValue *value,
GValue *return_value,
GError **error)
{
g_value_init (return_value, G_TYPE_STRING);
g_value_take_string (return_value, tmpl_value_repr (value));
return TRUE;
}
07070100000046000081A400000000000000000000000168C4C09600000A8C000000000000000000000000000000000000002A00000000template-glib-3.38.0/src/tmpl-expr-node.c/* tmpl-expr-node.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "tmpl-expr-node"
#include "tmpl-debug.h"
#include "tmpl-expr-node.h"
struct _TmplExprNode
{
TmplNode parent_instance;
TmplExpr *expr;
};
G_DEFINE_TYPE (TmplExprNode, tmpl_expr_node, TMPL_TYPE_NODE)
static gboolean
tmpl_expr_node_accept (TmplNode *node,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error)
{
TMPL_ENTRY;
/* no children */
TMPL_RETURN (TRUE);
}
static void
tmpl_expr_node_visit_children (TmplNode *node,
TmplNodeVisitor visitor,
gpointer user_data)
{
TMPL_ENTRY;
/* no children */
TMPL_EXIT;
}
static void
tmpl_expr_node_finalize (GObject *object)
{
TmplExprNode *self = (TmplExprNode *)object;
g_clear_pointer (&self->expr, tmpl_expr_unref);
G_OBJECT_CLASS (tmpl_expr_node_parent_class)->finalize (object);
}
static void
tmpl_expr_node_class_init (TmplExprNodeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
TmplNodeClass *node_class = TMPL_NODE_CLASS (klass);
object_class->finalize = tmpl_expr_node_finalize;
node_class->accept = tmpl_expr_node_accept;
node_class->visit_children = tmpl_expr_node_visit_children;
}
static void
tmpl_expr_node_init (TmplExprNode *self)
{
}
/**
* tmpl_expr_node_new:
* @expr: (transfer full): The expression
*
* Creates a new node, stealing the reference to @expr.
*
* Returns: (transfer full): A #TmplExprNode
*/
TmplNode *
tmpl_expr_node_new (TmplExpr *expr)
{
TmplExprNode *self;
self = g_object_new (TMPL_TYPE_EXPR_NODE, NULL);
self->expr = expr;
return TMPL_NODE (self);
}
/**
* tmpl_expr_node_get_expr:
*
* Gets the expression.
*
* Returns: (transfer none): A #TmplExpr.
*/
TmplExpr *
tmpl_expr_node_get_expr (TmplExprNode *self)
{
g_return_val_if_fail (TMPL_IS_EXPR_NODE (self), NULL);
return self->expr;
}
07070100000047000081A400000000000000000000000168C4C09600000483000000000000000000000000000000000000002A00000000template-glib-3.38.0/src/tmpl-expr-node.h/* tmpl-expr-node.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_EXPR_NODE_H
#define TMPL_EXPR_NODE_H
#include "tmpl-expr.h"
#include "tmpl-node.h"
G_BEGIN_DECLS
#define TMPL_TYPE_EXPR_NODE (tmpl_expr_node_get_type())
G_DECLARE_FINAL_TYPE (TmplExprNode, tmpl_expr_node, TMPL, EXPR_NODE, TmplNode)
TmplNode *tmpl_expr_node_new (TmplExpr *expr);
TmplExpr *tmpl_expr_node_get_expr (TmplExprNode *self);
G_END_DECLS
#endif /* TMPL_EXPR_NODE_H */
07070100000048000081A400000000000000000000000168C4C09600000691000000000000000000000000000000000000003400000000template-glib-3.38.0/src/tmpl-expr-parser-private.h/* tmpl-expr-parser-private.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_EXPR_PARSER_PRIVATE_H
#define TMPL_EXPR_PARSER_PRIVATE_H
#include <glib.h>
G_BEGIN_DECLS
typedef struct
{
TmplExpr *ast;
TmplScope *scope;
gpointer scanner;
gchar *error_str;
gint error_line;
guint reached_eof : 1;
} TmplExprParser;
void tmpl_expr_parser_destroy (TmplExprParser *parser);
void tmpl_expr_parser_flush (TmplExprParser *parser);
void tmpl_expr_parser_error (TmplExprParser *parser,
const char *message);
gboolean tmpl_expr_parser_parse_string (TmplExprParser *parser,
const gchar *input,
GError **error);
gboolean tmpl_expr_parser_init (TmplExprParser *parser,
GError **error);
G_END_DECLS
#endif /* TMPL_EXPR_PARSER_PRIVATE_H */
07070100000049000081A400000000000000000000000168C4C09600001A88000000000000000000000000000000000000002C00000000template-glib-3.38.0/src/tmpl-expr-parser.y%define api.pure
%define parse.error verbose
%name-prefix "tmpl_expr_parser_"
%defines
%parse-param { TmplExprParser *parser }
%lex-param { void *scanner }
%{
# include <glib/gprintf.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "tmpl-expr.h"
# include "tmpl-expr-private.h"
# include "tmpl-expr-parser-private.h"
#pragma GCC diagnostic ignored "-Wswitch-default"
%}
%union {
TmplExpr *a; /* ast node */
double d; /* number */
char *s; /* symbol/string */
GPtrArray *sl; /* symlist */
TmplExprBuiltin fn; /* builtin call */
int b; /* boolean */
int cmp; /* comparison */
int boolcmp; /* boolean comparison */
}
%{
int tmpl_expr_parser_lex (YYSTYPE *, void *scanner);
void
tmpl_expr_parser_error (TmplExprParser *parser,
const gchar *message)
{
g_assert (parser != NULL);
g_assert (message != NULL);
g_clear_pointer (&parser->ast, tmpl_expr_unref);
g_free (parser->error_str);
parser->error_str = g_strdup (message);
}
static void
add_expr_to_parser (TmplExprParser *parser,
TmplExpr *node)
{
if (parser->ast != NULL)
{
if (parser->ast->any.type != TMPL_EXPR_STMT_LIST)
{
GPtrArray *ar = g_ptr_array_new_with_free_func ((GDestroyNotify)tmpl_expr_unref);
g_ptr_array_add (ar, parser->ast);
g_ptr_array_add (ar, node);
parser->ast = tmpl_expr_new_stmt_list (ar);
}
else
{
g_ptr_array_add (parser->ast->stmt_list.stmts, node);
}
}
else
{
parser->ast = node;
}
}
static TmplExpr *
create_function (char *name,
GPtrArray *symlist,
TmplExpr *list)
{
char **strv = NULL;
if (symlist != NULL)
{
g_ptr_array_add (symlist, NULL);
strv = (char **)(gpointer)g_ptr_array_free (symlist, FALSE);
}
return tmpl_expr_new_func (name, strv, list);
}
static void
define_function (TmplExprParser *parser,
char *name,
GPtrArray *symlist,
TmplExpr *list)
{
add_expr_to_parser (parser, create_function (name, symlist, list));
}
static TmplExpr *
add_to_list (TmplExpr *stmt,
TmplExpr *list)
{
g_assert (stmt != NULL);
if (list == NULL)
{
GPtrArray *ar = g_ptr_array_new_with_free_func ((GDestroyNotify)tmpl_expr_unref);
g_ptr_array_add (ar, stmt);
return tmpl_expr_new_stmt_list (ar);
}
g_assert (list->any.type == TMPL_EXPR_STMT_LIST);
g_ptr_array_insert (list->stmt_list.stmts, 0, stmt);
return list;
}
# define scanner parser->scanner
%}
%token <b> BOOL
%token CONSTANT_NULL
%token <d> NUMBER
%token <s> NAME STRING_LITERAL
%token <fn> BUILTIN
%token <s> REQUIRE VERSION
%token EOL
%token DEF END
%token IF THEN ELSE WHILE DO FUNC
%token NOP
%left <cmp> CMP
%left <boolcmp> BOOLCMP
%right '='
%left '+' '-'
%left '*' '/'
%nonassoc '|' UMINUS
%type <a> exp stmt list explist
%type <sl> symlist
%start expr
%%
expr: /* nothing */ EOL {
YYACCEPT;
}
| stmt EOL {
add_expr_to_parser (parser, $1);
YYACCEPT;
}
| stmt ';' {
add_expr_to_parser (parser, $1);
YYACCEPT;
}
| DEF NAME '(' ')' EOL list END {
define_function (parser, $2, NULL, $6);
YYACCEPT;
}
| DEF NAME '(' ')' list END {
define_function (parser, $2, NULL, $5);
YYACCEPT;
}
| DEF NAME '(' ')' EOL END {
define_function (parser, $2, NULL, NULL);
YYACCEPT;
}
| DEF NAME '(' symlist ')' EOL list END {
define_function (parser, $2, $4, $7);
YYACCEPT;
}
| DEF NAME '(' symlist ')' list END {
define_function (parser, $2, $4, $6);
YYACCEPT;
}
| DEF NAME '(' symlist ')' EOL END {
define_function (parser, $2, $4, NULL);
YYACCEPT;
}
;
stmt: IF exp THEN list {
$$ = tmpl_expr_new_flow (TMPL_EXPR_IF, $2, $4, NULL);
}
| IF exp THEN list ELSE list {
$$ = tmpl_expr_new_flow (TMPL_EXPR_IF, $2, $4, $6);
}
| WHILE exp DO list {
$$ = tmpl_expr_new_flow (TMPL_EXPR_WHILE, $2, $4, NULL);
}
| exp
;
list: /* nothing */ { $$ = NULL; }
| stmt ';' list {
$$ = add_to_list ($1, $3);
}
| stmt EOL list {
$$ = add_to_list ($1, $3);
}
;
exp: exp CMP exp {
$$ = tmpl_expr_new_simple ($2, $1, $3);
}
| exp BOOLCMP exp {
$$ = tmpl_expr_new_simple ($2, $1, $3);
}
| exp '+' exp {
$$ = tmpl_expr_new_simple (TMPL_EXPR_ADD, $1, $3);
}
| exp '-' exp {
$$ = tmpl_expr_new_simple (TMPL_EXPR_SUB, $1, $3);
}
| exp '*' exp {
$$ = tmpl_expr_new_simple (TMPL_EXPR_MUL, $1, $3);
}
| exp '/' exp {
$$ = tmpl_expr_new_simple (TMPL_EXPR_DIV, $1, $3);
}
| '(' exp ')' {
$$ = $2;
}
| '-' exp %prec UMINUS {
$$ = tmpl_expr_new_simple (TMPL_EXPR_UNARY_MINUS, $2, NULL);
}
| NUMBER {
$$ = tmpl_expr_new_number ($1);
}
| BOOL {
$$ = tmpl_expr_new_boolean ($1);
}
| CONSTANT_NULL {
$$ = tmpl_expr_new_null ();
}
| STRING_LITERAL {
$$ = tmpl_expr_new_string ($1, -1);
g_free ($1);
}
| NAME {
$$ = tmpl_expr_new_symbol_ref ($1);
g_free ($1);
}
| NAME '=' exp {
$$ = tmpl_expr_new_symbol_assign ($1, $3);
g_free ($1);
}
| BUILTIN '(' explist ')' {
$$ = tmpl_expr_new_fn_call ($1, $3);
}
| NAME '(' explist ')' {
$$ = tmpl_expr_new_user_fn_call ($1, $3);
g_free ($1);
}
| NAME '(' ')' {
$$ = tmpl_expr_new_user_fn_call ($1, NULL);
g_free ($1);
}
| exp '.' NAME '(' ')' {
$$ = tmpl_expr_new_gi_call ($1, $3, NULL);
g_free ($3);
}
| exp '.' NAME '(' explist ')' {
$$ = tmpl_expr_new_gi_call ($1, $3, $5);
g_free ($3);
}
| exp '.' NAME {
$$ = tmpl_expr_new_getattr ($1, $3);
g_free ($3);
}
| exp '.' NAME '=' exp {
$$ = tmpl_expr_new_setattr ($1, $3, $5);
g_free ($3);
}
| exp '(' ')' {
$$ = tmpl_expr_new_anon_call ($1, NULL);
}
| exp '(' explist ')' {
$$ = tmpl_expr_new_anon_call ($1, $3);
}
| '!' exp {
$$ = tmpl_expr_new_invert_boolean ($2);
}
| NOP {
$$ = tmpl_expr_new_nop ();
}
| REQUIRE NAME {
$$ = tmpl_expr_new_require ($2, NULL);
g_free ($2);
}
| REQUIRE NAME VERSION STRING_LITERAL {
$$ = tmpl_expr_new_require ($2, $4);
g_free ($2);
g_free ($4);
}
| FUNC '(' ')' stmt {
$$ = create_function (NULL, NULL, $4);
}
| FUNC '(' symlist ')' stmt {
$$ = create_function (NULL, $3, $5);
}
;
explist: exp
| exp ',' explist {
$$ = tmpl_expr_new_simple (TMPL_EXPR_ARGS, $1, $3);
}
;
symlist: NAME {
$$ = g_ptr_array_new_with_free_func (g_free);
g_ptr_array_add ($$, $1);
}
| NAME ',' symlist {
$$ = $3;
g_ptr_array_insert ($$, 0, $1);
}
;
0707010000004A000081A400000000000000000000000168C4C09600000EF0000000000000000000000000000000000000002D00000000template-glib-3.38.0/src/tmpl-expr-private.h/* tmpl-expr-private.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_EXPR_PRIVATE_H
#define TMPL_EXPR_PRIVATE_H
#include "tmpl-expr.h"
G_BEGIN_DECLS
typedef struct
{
TmplExprType type;
volatile gint ref_count;
TmplExpr *left;
TmplExpr *right;
} TmplExprSimple;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
TmplExpr *object;
gchar *name;
TmplExpr *params;
} TmplExprGiCall;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
TmplExprBuiltin builtin;
TmplExpr *param;
} TmplExprFnCall;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
gchar *symbol;
TmplExpr *params;
} TmplExprUserFnCall;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
TmplExpr *anon;
TmplExpr *params;
} TmplExprAnonFnCall;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
TmplExpr *condition;
TmplExpr *primary;
TmplExpr *secondary;
} TmplExprFlow;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
gdouble number;
} TmplExprNumber;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
guint value: 1;
} TmplExprBoolean;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
gchar *value;
} TmplExprString;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
gchar *symbol;
} TmplExprSymbolRef;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
gchar *symbol;
TmplExpr *right;
} TmplExprSymbolAssign;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
gchar *attr;
TmplExpr *left;
} TmplExprGetattr;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
gchar *attr;
TmplExpr *left;
TmplExpr *right;
} TmplExprSetattr;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
gchar *name;
gchar *version;
} TmplExprRequire;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
} TmplExprAny;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
GPtrArray *stmts;
} TmplExprStmtList;
typedef struct
{
TmplExprType type;
volatile gint ref_count;
char *name;
char **symlist;
TmplExpr *list;
} TmplExprFunc;
union _TmplExpr
{
TmplExprAny any;
TmplExprSimple simple;
TmplExprGiCall gi_call;
TmplExprFnCall fn_call;
TmplExprAnonFnCall anon_fn_call;
TmplExprUserFnCall user_fn_call;
TmplExprFlow flow;
TmplExprNumber number;
TmplExprString string;
TmplExprSymbolRef sym_ref;
TmplExprSymbolAssign sym_assign;
TmplExprGetattr getattr;
TmplExprSetattr setattr;
TmplExprRequire require;
TmplExprStmtList stmt_list;
TmplExprFunc func;
};
G_END_DECLS
#endif /* TMPL_EXPR_PRIVATE_H */
0707010000004B000081A400000000000000000000000168C4C096000018C9000000000000000000000000000000000000002D00000000template-glib-3.38.0/src/tmpl-expr-scanner.l%option reentrant
%option prefix="tmpl_expr_parser_"
%option bison-bridge
%option noyywrap
%option yylineno
%option nodefault
%option header-file="tmpl-expr-scanner.h"
%option outfile="tmpl-expr-scanner.c"
%{
# include "tmpl-error.h"
# include "tmpl-expr-private.h"
# include "tmpl-expr-parser-private.h"
# include "tmpl-expr-parser.h"
#pragma GCC diagnostic ignored "-Wswitch-default"
#pragma GCC diagnostic ignored "-Wunused-function"
static char *
copy_literal (const char *str)
{
gsize len;
if (str[0] == 'L')
str++;
g_assert (str[0] == '\"');
str++;
len = strlen (str);
g_assert (len > 0);
g_assert (str[len-1] == '\"');
return g_strndup (str, len - 1);
}
%}
%option extra-type="TmplExprParser *"
/* float exponent */
EXP ([Ee][-+]?[0-9]+)
%%
%{
TmplExprParser *parser = yyextra;
%}
/* single character ops */
"+" |
"-" |
"*" |
"/" |
"=" |
"," |
"." |
"!" |
";" |
"(" |
")" { return yytext [0]; }
/* comparison ops */
">" { yylval->cmp = TMPL_EXPR_GT; return CMP; }
"<" { yylval->cmp = TMPL_EXPR_LT; return CMP; }
"!=" { yylval->cmp = TMPL_EXPR_NE; return CMP; }
"==" { yylval->cmp = TMPL_EXPR_EQ; return CMP; }
">=" { yylval->cmp = TMPL_EXPR_GTE; return CMP; }
"<=" { yylval->cmp = TMPL_EXPR_LTE; return CMP; }
/* boolean ops */
"||" { yylval->boolcmp = TMPL_EXPR_OR; return BOOLCMP; }
"&&" { yylval->boolcmp = TMPL_EXPR_AND; return BOOLCMP; }
/* keywords */
"if" { return IF; }
"then" { return THEN; }
"else" { return ELSE; }
"while" { return WHILE; }
"do" { return DO; }
"func" { return FUNC; }
"def" { return DEF; }
"end" { return END; }
"require" { return REQUIRE; }
"version" { return VERSION; }
"pass" { return NOP; }
/* booleans */
"true" { yylval->b = 1; return BOOL; }
"false" { yylval->b = 0; return BOOL; }
"True" { yylval->b = 1; return BOOL; }
"False" { yylval->b = 0; return BOOL; }
"TRUE" { yylval->b = 1; return BOOL; }
"FALSE" { yylval->b = 0; return BOOL; }
/* constants */
"null" { return CONSTANT_NULL; }
/* builtin functions */
"assert" { yylval->fn = TMPL_EXPR_BUILTIN_ASSERT; return BUILTIN; }
"abs" { yylval->fn = TMPL_EXPR_BUILTIN_ABS; return BUILTIN; }
"ceil" { yylval->fn = TMPL_EXPR_BUILTIN_CEIL; return BUILTIN; }
"floor" { yylval->fn = TMPL_EXPR_BUILTIN_FLOOR; return BUILTIN; }
"hex" { yylval->fn = TMPL_EXPR_BUILTIN_HEX; return BUILTIN; }
"log" { yylval->fn = TMPL_EXPR_BUILTIN_LOG; return BUILTIN; }
"print" { yylval->fn = TMPL_EXPR_BUILTIN_PRINT; return BUILTIN; }
"printerr" { yylval->fn = TMPL_EXPR_BUILTIN_PRINTERR; return BUILTIN; }
"repr" { yylval->fn = TMPL_EXPR_BUILTIN_REPR; return BUILTIN; }
"sqrt" { yylval->fn = TMPL_EXPR_BUILTIN_SQRT; return BUILTIN; }
"typeof" { yylval->fn = TMPL_EXPR_BUILTIN_TYPEOF; return BUILTIN; }
"sin" { yylval->fn = TMPL_EXPR_BUILTIN_SIN; return BUILTIN; }
"tan" { yylval->fn = TMPL_EXPR_BUILTIN_TAN; return BUILTIN; }
"cos" { yylval->fn = TMPL_EXPR_BUILTIN_COS; return BUILTIN; }
"char" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_CHAR; return BUILTIN; }
"byte" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_BYTE; return BUILTIN; }
"i32" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_I32; return BUILTIN; }
"u32" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_U32; return BUILTIN; }
"i64" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_I64; return BUILTIN; }
"u64" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_U64; return BUILTIN; }
"float" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_FLOAT; return BUILTIN; }
"double" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_DOUBLE; return BUILTIN; }
"bool" { yylval->fn = TMPL_EXPR_BUILTIN_CAST_BOOL; return BUILTIN; }
/* string literals */
L?\"(\\.|[^\\"])*\" { yylval->s = copy_literal (yytext); return STRING_LITERAL; }
/* @ to escape reserved keywords */
@[a-zA-Z_][a-zA-Z0-9_]* {
yylval->s = g_strdup (yytext+1);
return NAME;
}
/* names */
[a-zA-Z_][a-zA-Z0-9_]* {
yylval->s = g_strdup (yytext);
return NAME;
}
[0-9]+"."[0-9]*{EXP}? |
"."?[0-9]+{EXP}? { yylval->d = atof(yytext); return NUMBER; }
"//".*
[ \t] /* ignore whitespace */
"\\\n" /* ignore escpaed newlines */
#[^\n]* { return EOL; } /* line-wise comments should EOL things */
"\n" { return EOL; }
<<EOF>> { parser->reached_eof = TRUE; return EOL; }
. {
g_free (parser->error_str);
parser->error_str = g_strdup (yytext);
parser->error_line = yylineno;
}
%%
void
tmpl_expr_parser_init_scanner (TmplExprParser *parser)
{
g_assert (parser != NULL);
yylex_init (&parser->scanner);
yyset_extra (parser, parser->scanner);
}
void
tmpl_expr_parser_destroy_scanner (TmplExprParser *parser)
{
g_assert (parser != NULL);
yylex_destroy (parser->scanner);
}
void
tmpl_expr_parser_flush (TmplExprParser *parser)
{
struct yyguts_t *yyg;
g_assert (parser != NULL);
yyg = (struct yyguts_t *)parser->scanner;
tmpl_expr_parser__flush_buffer (YY_CURRENT_BUFFER, parser->scanner);
}
gboolean
tmpl_expr_parser_parse_string (TmplExprParser *self,
const gchar *input,
GError **error)
{
YY_BUFFER_STATE buf;
int ret = 0;
g_return_val_if_fail (self != NULL, FALSE);
buf = tmpl_expr_parser__scan_string (input, self->scanner);
while (!self->reached_eof && ret == 0)
ret = tmpl_expr_parser_parse (self);
tmpl_expr_parser__delete_buffer (buf, self->scanner);
if (ret == 0 && self->error_str == NULL)
return TRUE;
if (self->error_str)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"%s", self->error_str);
return FALSE;
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Failed to parse expression");
return FALSE;
}
gboolean
tmpl_expr_parser_init (TmplExprParser *self,
GError **error)
{
g_return_val_if_fail (self != NULL, FALSE);
memset (self, 0, sizeof *self);
tmpl_expr_parser_init_scanner (self);
return TRUE;
}
void
tmpl_expr_parser_destroy (TmplExprParser *self)
{
if (self != NULL)
{
tmpl_expr_parser_destroy_scanner (self);
g_clear_pointer (&self->ast, tmpl_expr_unref);
g_clear_pointer (&self->error_str, g_free);
}
}
0707010000004C000081A400000000000000000000000168C4C09600000B8B000000000000000000000000000000000000002B00000000template-glib-3.38.0/src/tmpl-expr-types.h/* tmpl-expr-types.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_EXPR_TYPES_H
#define TMPL_EXPR_TYPES_H
#include <glib-object.h>
#include "tmpl-version-macros.h"
#include "tmpl-enums.h"
G_BEGIN_DECLS
#define TMPL_TYPE_EXPR (tmpl_expr_get_type())
#define TMPL_TYPE_SCOPE (tmpl_scope_get_type())
#define TMPL_TYPE_SYMBOL (tmpl_symbol_get_type())
typedef union _TmplExpr TmplExpr;
typedef struct _TmplScope TmplScope;
typedef struct _TmplSymbol TmplSymbol;
typedef enum
{
TMPL_SYMBOL_EXPR,
TMPL_SYMBOL_VALUE,
} TmplSymbolType;
typedef enum
{
TMPL_EXPR_ADD = 1,
TMPL_EXPR_SUB,
TMPL_EXPR_MUL,
TMPL_EXPR_DIV,
TMPL_EXPR_BOOLEAN,
TMPL_EXPR_NUMBER,
TMPL_EXPR_STRING,
TMPL_EXPR_GT,
TMPL_EXPR_LT,
TMPL_EXPR_NE,
TMPL_EXPR_EQ,
TMPL_EXPR_GTE,
TMPL_EXPR_LTE,
TMPL_EXPR_UNARY_MINUS,
TMPL_EXPR_STMT_LIST,
TMPL_EXPR_IF,
TMPL_EXPR_WHILE,
TMPL_EXPR_SYMBOL_REF,
TMPL_EXPR_SYMBOL_ASSIGN,
TMPL_EXPR_FN_CALL,
TMPL_EXPR_ANON_FN_CALL,
TMPL_EXPR_USER_FN_CALL,
TMPL_EXPR_GETATTR,
TMPL_EXPR_SETATTR,
TMPL_EXPR_GI_CALL,
TMPL_EXPR_REQUIRE,
TMPL_EXPR_AND,
TMPL_EXPR_OR,
TMPL_EXPR_INVERT_BOOLEAN,
TMPL_EXPR_ARGS,
TMPL_EXPR_FUNC,
TMPL_EXPR_NOP,
TMPL_EXPR_NULL,
} TmplExprType;
typedef enum
{
TMPL_EXPR_BUILTIN_ABS,
TMPL_EXPR_BUILTIN_CEIL,
TMPL_EXPR_BUILTIN_FLOOR,
TMPL_EXPR_BUILTIN_HEX,
TMPL_EXPR_BUILTIN_LOG,
TMPL_EXPR_BUILTIN_PRINT,
TMPL_EXPR_BUILTIN_REPR,
TMPL_EXPR_BUILTIN_SQRT,
TMPL_EXPR_BUILTIN_TYPEOF,
TMPL_EXPR_BUILTIN_ASSERT,
TMPL_EXPR_BUILTIN_SIN,
TMPL_EXPR_BUILTIN_TAN,
TMPL_EXPR_BUILTIN_COS,
TMPL_EXPR_BUILTIN_PRINTERR,
TMPL_EXPR_BUILTIN_CAST_BYTE,
TMPL_EXPR_BUILTIN_CAST_CHAR,
TMPL_EXPR_BUILTIN_CAST_I32,
TMPL_EXPR_BUILTIN_CAST_U32,
TMPL_EXPR_BUILTIN_CAST_I64,
TMPL_EXPR_BUILTIN_CAST_U64,
TMPL_EXPR_BUILTIN_CAST_FLOAT,
TMPL_EXPR_BUILTIN_CAST_DOUBLE,
TMPL_EXPR_BUILTIN_CAST_BOOL,
} TmplExprBuiltin;
TMPL_AVAILABLE_IN_ALL
GType tmpl_expr_get_type (void);
TMPL_AVAILABLE_IN_ALL
GType tmpl_scope_get_type (void);
TMPL_AVAILABLE_IN_ALL
GType tmpl_symbol_get_type (void);
G_END_DECLS
#endif /* TMPL_EXPR_TYPES_H */
0707010000004D000081A400000000000000000000000168C4C096000028D3000000000000000000000000000000000000002500000000template-glib-3.38.0/src/tmpl-expr.c/* tmpl-expr.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tmpl-expr.h"
#include "tmpl-expr-private.h"
#include "tmpl-expr-parser-private.h"
static gpointer tmpl_expr_new (TmplExprType type);
static void tmpl_expr_destroy (TmplExpr *expr);
G_DEFINE_BOXED_TYPE (TmplExpr, tmpl_expr, tmpl_expr_ref, tmpl_expr_unref)
TmplExpr *
tmpl_expr_ref (TmplExpr *self)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (self->any.ref_count > 0, NULL);
g_atomic_int_inc (&self->any.ref_count);
return self;
}
void
tmpl_expr_unref (TmplExpr *self)
{
g_return_if_fail (self != NULL);
g_return_if_fail (self->any.ref_count > 0);
if (g_atomic_int_dec_and_test (&self->any.ref_count))
tmpl_expr_destroy (self);
}
static gpointer
tmpl_expr_new (TmplExprType type)
{
TmplExpr *ret;
ret = g_slice_new0 (TmplExpr);
ret->any.type = type;
ret->any.ref_count = 1;
return ret;
}
static void
tmpl_expr_destroy (TmplExpr *self)
{
g_assert (self != NULL);
g_assert (self->any.ref_count == 0);
/* Set fields to NULL to aid in debugging. */
switch (self->any.type)
{
case TMPL_EXPR_ADD:
case TMPL_EXPR_DIV:
case TMPL_EXPR_EQ:
case TMPL_EXPR_GT:
case TMPL_EXPR_GTE:
case TMPL_EXPR_LT:
case TMPL_EXPR_LTE:
case TMPL_EXPR_MUL:
case TMPL_EXPR_NE:
case TMPL_EXPR_SUB:
case TMPL_EXPR_UNARY_MINUS:
case TMPL_EXPR_AND:
case TMPL_EXPR_OR:
case TMPL_EXPR_INVERT_BOOLEAN:
case TMPL_EXPR_ARGS:
g_clear_pointer (&self->simple.left, tmpl_expr_unref);
g_clear_pointer (&self->simple.right, tmpl_expr_unref);
break;
case TMPL_EXPR_USER_FN_CALL:
g_clear_pointer (&self->user_fn_call.symbol, g_free);
g_clear_pointer (&self->user_fn_call.params, tmpl_expr_unref);
break;
case TMPL_EXPR_ANON_FN_CALL:
g_clear_pointer (&self->anon_fn_call.anon, tmpl_expr_unref);
g_clear_pointer (&self->user_fn_call.params, tmpl_expr_unref);
break;
case TMPL_EXPR_GETATTR:
g_clear_pointer (&self->getattr.attr, g_free);
g_clear_pointer (&self->getattr.left, tmpl_expr_unref);
break;
case TMPL_EXPR_SETATTR:
g_clear_pointer (&self->setattr.attr, g_free);
g_clear_pointer (&self->setattr.left, tmpl_expr_unref);
g_clear_pointer (&self->setattr.right, tmpl_expr_unref);
break;
case TMPL_EXPR_STMT_LIST:
g_clear_pointer (&self->stmt_list.stmts, g_ptr_array_unref);
break;
case TMPL_EXPR_BOOLEAN:
case TMPL_EXPR_NUMBER:
break;
case TMPL_EXPR_STRING:
g_clear_pointer (&self->string.value, g_free);
break;
case TMPL_EXPR_IF:
case TMPL_EXPR_WHILE:
g_clear_pointer (&self->flow.condition, tmpl_expr_unref);
g_clear_pointer (&self->flow.primary, tmpl_expr_unref);
g_clear_pointer (&self->flow.secondary, tmpl_expr_unref);
break;
case TMPL_EXPR_SYMBOL_REF:
g_clear_pointer (&self->sym_ref.symbol, g_free);
break;
case TMPL_EXPR_SYMBOL_ASSIGN:
g_clear_pointer (&self->sym_assign.symbol, g_free);
g_clear_pointer (&self->sym_assign.right, tmpl_expr_unref);
break;
case TMPL_EXPR_FN_CALL:
g_clear_pointer (&self->fn_call.param, tmpl_expr_unref);
break;
case TMPL_EXPR_GI_CALL:
g_clear_pointer (&self->gi_call.name, g_free);
g_clear_pointer (&self->gi_call.object, tmpl_expr_unref);
g_clear_pointer (&self->gi_call.params, tmpl_expr_unref);
break;
case TMPL_EXPR_REQUIRE:
g_clear_pointer (&self->require.name, g_free);
g_clear_pointer (&self->require.version, g_free);
break;
case TMPL_EXPR_FUNC:
g_clear_pointer (&self->func.name, g_free);
g_clear_pointer (&self->func.symlist, g_strfreev);
g_clear_pointer (&self->func.list, tmpl_expr_unref);
break;
case TMPL_EXPR_NOP:
case TMPL_EXPR_NULL:
/* This should never happen,
* but just log it if it does */
g_return_if_reached ();
default:
g_assert_not_reached ();
}
g_slice_free (TmplExpr, self);
}
/**
* tmpl_expr_new_stmt_list:
* @stmts: (transfer full) (element-type TmplExpr): a #GPtrArray of
* #TmplExpr which will be evaluated in sequence.
*
* Creates a new statement list for which the last item will be
* used as the "return value" from execution.
*
* Returns: (transfer full): a new #TmplExpr
*
* Since: 3.36
*/
TmplExpr *
tmpl_expr_new_stmt_list (GPtrArray *stmts)
{
TmplExpr *ret;
g_return_val_if_fail (stmts != NULL, NULL);
g_ptr_array_set_free_func (stmts, (GDestroyNotify)tmpl_expr_unref);
ret = tmpl_expr_new (TMPL_EXPR_STMT_LIST);
((TmplExprStmtList *)ret)->stmts = stmts;
return ret;
}
TmplExpr *
tmpl_expr_new_boolean (gboolean value)
{
TmplExpr *ret;
ret = tmpl_expr_new (TMPL_EXPR_BOOLEAN);
((TmplExprBoolean *)ret)->value = !!value;
return ret;
}
TmplExpr *
tmpl_expr_new_number (gdouble value)
{
TmplExprNumber *ret;
ret = tmpl_expr_new (TMPL_EXPR_NUMBER);
ret->number = value;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_string (const gchar *str,
gssize length)
{
TmplExprString *ret;
ret = tmpl_expr_new (TMPL_EXPR_STRING);
if (length < 0)
ret->value = g_strdup (str);
else
ret->value = g_strndup (str, length);
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_require (const gchar *typelib,
const gchar *version)
{
TmplExprRequire *ret;
ret = tmpl_expr_new (TMPL_EXPR_REQUIRE);
ret->name = g_strdup (typelib);
ret->version = g_strdup (version);
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_simple (TmplExprType type,
TmplExpr *left,
TmplExpr *right)
{
TmplExprSimple *ret;
ret = tmpl_expr_new (type);
ret->left = left;
ret->right = right;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_invert_boolean (TmplExpr *left)
{
TmplExprSimple *ret;
ret = tmpl_expr_new (TMPL_EXPR_INVERT_BOOLEAN);
ret->left = left;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_flow (TmplExprType type,
TmplExpr *condition,
TmplExpr *primary,
TmplExpr *secondary)
{
TmplExprFlow *ret;
ret = tmpl_expr_new (type);
ret->condition = condition;
ret->primary = primary;
ret->secondary = secondary;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_getattr (TmplExpr *left,
const gchar *attr)
{
TmplExprGetattr *ret;
ret = tmpl_expr_new (TMPL_EXPR_GETATTR);
ret->left = left;
ret->attr = g_strdup (attr);
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_setattr (TmplExpr *left,
const gchar *attr,
TmplExpr *right)
{
TmplExprSetattr *ret;
ret = tmpl_expr_new (TMPL_EXPR_SETATTR);
ret->left = left;
ret->attr = g_strdup (attr);
ret->right = right;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_symbol_ref (const gchar *symbol)
{
TmplExprSymbolRef *ret;
ret = tmpl_expr_new (TMPL_EXPR_SYMBOL_REF);
ret->symbol = g_strdup (symbol);
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_symbol_assign (const gchar *symbol,
TmplExpr *right)
{
TmplExprSymbolAssign *ret;
ret = tmpl_expr_new (TMPL_EXPR_SYMBOL_ASSIGN);
ret->symbol = g_strdup (symbol);
ret->right = right;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_fn_call (TmplExprBuiltin builtin,
TmplExpr *param)
{
TmplExprFnCall *ret;
ret = tmpl_expr_new (TMPL_EXPR_FN_CALL);
ret->builtin = builtin;
ret->param = param;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_user_fn_call (const gchar *symbol,
TmplExpr *params)
{
TmplExprUserFnCall *ret;
ret = tmpl_expr_new (TMPL_EXPR_USER_FN_CALL);
ret->symbol = g_strdup (symbol);
ret->params = params;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_gi_call (TmplExpr *object,
const gchar *name,
TmplExpr *params)
{
TmplExprGiCall *ret;
ret = tmpl_expr_new (TMPL_EXPR_GI_CALL);
ret->object = object;
ret->name = g_strdup (name);
ret->params = params;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_from_string (const gchar *str,
GError **error)
{
TmplExprParser parser = { 0 };
TmplExpr *ret = NULL;
g_return_val_if_fail (str != NULL, NULL);
if (!tmpl_expr_parser_init (&parser, error))
return NULL;
if (tmpl_expr_parser_parse_string (&parser, str, error))
ret = parser.ast, parser.ast = NULL;
tmpl_expr_parser_destroy (&parser);
return ret;
}
TmplExpr *
tmpl_expr_new_func (char *name,
char **symlist,
TmplExpr *list)
{
TmplExprFunc *ret;
if (list == NULL)
list = tmpl_expr_new_nop ();
ret = tmpl_expr_new (TMPL_EXPR_FUNC);
ret->name = name;
ret->symlist = symlist;
ret->list = list;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_anon_call (TmplExpr *func,
TmplExpr *params)
{
TmplExprAnonFnCall *ret;
g_return_val_if_fail (func != NULL, NULL);
g_return_val_if_fail (func->any.type == TMPL_EXPR_FUNC, NULL);
ret = tmpl_expr_new (TMPL_EXPR_ANON_FN_CALL);
ret->anon = func;
ret->params = params;
return (TmplExpr *)ret;
}
TmplExpr *
tmpl_expr_new_nop (void)
{
static TmplExpr interned = { .any.type = TMPL_EXPR_NOP, .any.ref_count = 1 };
return tmpl_expr_ref (&interned);
}
TmplExpr *
tmpl_expr_new_null (void)
{
static TmplExpr interned = { .any.type = TMPL_EXPR_NULL, .any.ref_count = 1 };
return tmpl_expr_ref (&interned);
}
0707010000004E000081A400000000000000000000000168C4C09600001180000000000000000000000000000000000000002500000000template-glib-3.38.0/src/tmpl-expr.h/* tmpl-expr.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_EXPR_H
#define TMPL_EXPR_H
#include "tmpl-version-macros.h"
#include "tmpl-expr-types.h"
G_BEGIN_DECLS
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_from_string (const gchar *str,
GError **error);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_ref (TmplExpr *expr);
TMPL_AVAILABLE_IN_ALL
void tmpl_expr_unref (TmplExpr *expr);
TMPL_AVAILABLE_IN_ALL
gboolean tmpl_expr_eval (TmplExpr *expr,
TmplScope *scope,
GValue *return_value,
GError **error);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_boolean (gboolean value);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_invert_boolean(TmplExpr *left);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_getattr (TmplExpr *left,
const gchar *attr);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_setattr (TmplExpr *left,
const gchar *attr,
TmplExpr *right);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_require (const gchar *typelib,
const gchar *version);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_simple (TmplExprType type,
TmplExpr *left,
TmplExpr *right);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_string (const gchar *value,
gssize length);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_number (gdouble value);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_gi_call (TmplExpr *left,
const gchar *name,
TmplExpr *params);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_fn_call (TmplExprBuiltin builtin,
TmplExpr *param);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_user_fn_call (const gchar *name,
TmplExpr *param);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_flow (TmplExprType type,
TmplExpr *condition,
TmplExpr *primary,
TmplExpr *secondary);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_symbol_ref (const gchar *symbol);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_expr_new_symbol_assign (const gchar *symbol,
TmplExpr *right);
TMPL_AVAILABLE_IN_3_36
TmplExpr *tmpl_expr_new_stmt_list (GPtrArray *stmts);
TMPL_AVAILABLE_IN_3_36
TmplExpr *tmpl_expr_new_func (char *name,
char **symlist,
TmplExpr *list);
TMPL_AVAILABLE_IN_3_36
TmplExpr *tmpl_expr_new_anon_call (TmplExpr *func,
TmplExpr *params);
TMPL_AVAILABLE_IN_3_36
TmplExpr *tmpl_expr_new_nop (void);
TMPL_AVAILABLE_IN_3_36
TmplExpr *tmpl_expr_new_null (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (TmplExpr, tmpl_expr_unref)
G_END_DECLS
#endif /* TMPL_EXPR_H */
0707010000004F000081A400000000000000000000000168C4C09600000700000000000000000000000000000000000000002B00000000template-glib-3.38.0/src/tmpl-gi-private.h/* tmpl-gi-private.h
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_GI_PRIVATE_H
#define TMPL_GI_PRIVATE_H
#include <girepository/girepository.h>
G_BEGIN_DECLS
#define TMPL_TYPE_TYPELIB (tmpl_typelib_get_type())
#define TMPL_TYPE_BASE_INFO (tmpl_base_info_get_type())
typedef GType (*TmplGTypeFunc) (void);
GType tmpl_typelib_get_type (void);
GType tmpl_base_info_get_type (void);
gboolean tmpl_gi_argument_from_g_value (const GValue *value,
GITypeInfo *type_info,
GIArgInfo *arg_info,
GIArgument *arg,
GError **error);
gboolean tmpl_gi_argument_to_g_value (GValue *value,
GITypeInfo *type_info,
GIArgument *arg,
GITransfer xfer,
GError **error);
TmplGTypeFunc
tmpl_gi_get_gtype_func (GIBaseInfo *base_info);
G_END_DECLS
#endif /* TMPL_GI_PRIVATE_H */
07070100000050000081A400000000000000000000000168C4C09600005EB9000000000000000000000000000000000000002300000000template-glib-3.38.0/src/tmpl-gi.c/* tmpl-gi.c
*
* Copyright PyGObject authors
* Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tmpl-error.h"
#include "tmpl-gi-private.h"
#include "tmpl-util-private.h"
G_DEFINE_POINTER_TYPE (TmplTypelib, tmpl_typelib)
typedef struct GIBaseInfo TmplBaseInfo;
G_DEFINE_BOXED_TYPE (TmplBaseInfo, tmpl_base_info,
(GBoxedCopyFunc)gi_base_info_ref,
(GBoxedFreeFunc)gi_base_info_unref)
#define return_type_mismatch(value, type) \
G_STMT_START { \
g_set_error (error, \
TMPL_ERROR, \
TMPL_ERROR_TYPE_MISMATCH, \
"Expected %s, got %s", \
g_type_name (type), G_VALUE_TYPE_NAME (value)); \
return FALSE; \
} G_STMT_END
#define return_if_not_type(value, type) \
G_STMT_START { \
if (!G_VALUE_HOLDS (value, type)) \
return_type_mismatch(value, type); \
} G_STMT_END
static gboolean
find_enum_value (GIEnumInfo *info,
const gchar *str,
gint *v_int)
{
guint n = gi_enum_info_get_n_values (info);
for (guint i = 0; i < n; i++)
{
g_autoptr(GIBaseInfo) vinfo = NULL;
vinfo = (GIBaseInfo *)gi_enum_info_get_value (info, i);
if (g_strcmp0 (str, gi_base_info_get_name (vinfo)) == 0)
{
*v_int = gi_value_info_get_value ((GIValueInfo *)vinfo);
return TRUE;
}
}
return FALSE;
}
gboolean
tmpl_gi_argument_from_g_value (const GValue *value,
GITypeInfo *type_info,
GIArgInfo *arg_info,
GIArgument *arg,
GError **error)
{
GITypeTag type_tag = gi_type_info_get_tag (type_info);
GITransfer xfer = gi_arg_info_get_ownership_transfer (arg_info);
/* For the long handling: long can be equivalent to
* int32 or int64, depending on the architecture, but
* gi doesn't tell us (and same for ulong)
*/
if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_TYPE_MISMATCH,
"uninitialized value");
return FALSE;
}
switch (type_tag)
{
case GI_TYPE_TAG_BOOLEAN:
return_if_not_type (value, G_TYPE_BOOLEAN);
arg->v_boolean = g_value_get_boolean (value);
return TRUE;
case GI_TYPE_TAG_INT8:
#define MINVAL G_MININT8
#define MAXVAL G_MAXINT8
if G_LIKELY (G_VALUE_HOLDS (value, G_TYPE_CHAR))
arg->v_int8 = g_value_get_schar (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UCHAR) && g_value_get_uchar (value) <= MAXVAL)
arg->v_int8 = g_value_get_uchar (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT) && g_value_get_int (value) >= MINVAL && g_value_get_int (value) <= MAXVAL)
arg->v_int8 = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT) && g_value_get_uint (value) >= MINVAL && g_value_get_uint (value) <= MAXVAL)
arg->v_int8 = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG) && g_value_get_long (value) >= MINVAL && g_value_get_long (value) <= MAXVAL)
arg->v_int8 = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG) && g_value_get_ulong (value) >= MINVAL && g_value_get_ulong (value) <= MAXVAL)
arg->v_int8 = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64) && g_value_get_int64 (value) >= MINVAL && g_value_get_int64 (value) <= MAXVAL)
arg->v_int8 = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64) && g_value_get_uint64 (value) >= MINVAL && g_value_get_uint64 (value) <= MAXVAL)
arg->v_int8 = g_value_get_uint64 (value);
else
return_type_mismatch (value, G_TYPE_CHAR);
return TRUE;
#undef MINVAL
#undef MAXVAL
case GI_TYPE_TAG_INT16:
#define MINVAL G_MININT16
#define MAXVAL G_MAXINT16
if (G_VALUE_HOLDS (value, G_TYPE_INT) && g_value_get_int (value) >= MINVAL && g_value_get_int (value) <= MAXVAL)
arg->v_int = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT) && g_value_get_uint (value) >= MINVAL && g_value_get_uint (value) <= MAXVAL)
arg->v_int = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG) && g_value_get_long (value) >= MINVAL && g_value_get_long (value) <= MAXVAL)
arg->v_int = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG) && g_value_get_ulong (value) >= MINVAL && g_value_get_ulong (value) <= MAXVAL)
arg->v_int = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64) && g_value_get_int64 (value) >= MINVAL && g_value_get_int64 (value) <= MAXVAL)
arg->v_int = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64) && g_value_get_uint64 (value) >= MINVAL && g_value_get_uint64 (value) <= MAXVAL)
arg->v_int = g_value_get_uint64 (value);
else
return_type_mismatch (value, G_TYPE_INT);
return TRUE;
#undef MINVAL
#undef MAXVAL
case GI_TYPE_TAG_INT32:
#define MINVAL G_MININT32
#define MAXVAL G_MAXINT32
if (G_VALUE_HOLDS (value, G_TYPE_INT))
arg->v_int = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT) && g_value_get_uint (value) >= MINVAL && g_value_get_uint (value) <= MAXVAL)
arg->v_int = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG) && g_value_get_long (value) >= MINVAL && g_value_get_long (value) <= MAXVAL)
arg->v_int = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG) && g_value_get_ulong (value) >= MINVAL && g_value_get_ulong (value) <= MAXVAL)
arg->v_int = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64) && g_value_get_int64 (value) >= MINVAL && g_value_get_int64 (value) <= MAXVAL)
arg->v_int = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64) && g_value_get_uint64 (value) >= MINVAL && g_value_get_uint64 (value) <= MAXVAL)
arg->v_int = g_value_get_uint64 (value);
else
return_type_mismatch (value, G_TYPE_INT);
return TRUE;
#undef MINVAL
#undef MAXVAL
case GI_TYPE_TAG_INT64:
#define MINVAL G_MININT64
#define MAXVAL G_MAXINT64
if (G_VALUE_HOLDS (value, G_TYPE_INT64))
arg->v_int64 = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT))
arg->v_int64 = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT))
arg->v_int64 = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG))
arg->v_int64 = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG))
arg->v_int64 = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64) && g_value_get_uint64 (value) <= MAXVAL)
arg->v_int64 = g_value_get_uint64 (value);
else
return_type_mismatch (value, G_TYPE_INT);
return TRUE;
#undef MINVAL
#undef MAXVAL
case GI_TYPE_TAG_UINT8:
#define MINVAL 0
#define MAXVAL G_MAXUINT8
if (G_VALUE_HOLDS (value, G_TYPE_UCHAR))
arg->v_uint8 = g_value_get_uchar (value);
else if G_LIKELY (G_VALUE_HOLDS (value, G_TYPE_CHAR) && g_value_get_schar (value) >= MINVAL)
arg->v_uint8 = g_value_get_schar (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT) && g_value_get_int (value) >= MINVAL && g_value_get_int (value) <= MAXVAL)
arg->v_uint8 = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT) && g_value_get_uint (value) <= MAXVAL)
arg->v_uint8 = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG) && g_value_get_long (value) >= MINVAL && g_value_get_long (value) <= MAXVAL)
arg->v_uint8 = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG) && g_value_get_ulong (value) <= MAXVAL)
arg->v_uint8 = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64) && g_value_get_int64 (value) >= MINVAL && g_value_get_int64 (value) <= MAXVAL)
arg->v_uint8 = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64) && g_value_get_uint64 (value) <= MAXVAL)
arg->v_uint8 = g_value_get_uint64 (value);
else
return_type_mismatch (value, G_TYPE_CHAR);
return TRUE;
#undef MINVAL
#undef MAXVAL
case GI_TYPE_TAG_UINT16:
#define MINVAL 0
#define MAXVAL G_MAXUINT16
if (G_VALUE_HOLDS (value, G_TYPE_UINT) && g_value_get_uint (value) <= MAXVAL)
arg->v_uint = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT) && g_value_get_int (value) >= MINVAL && g_value_get_int (value) <= MAXVAL)
arg->v_uint = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG) && g_value_get_long (value) >= MINVAL && g_value_get_long (value) <= MAXVAL)
arg->v_uint = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG) && g_value_get_ulong (value) <= MAXVAL)
arg->v_uint = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64) && g_value_get_int64 (value) >= MINVAL && g_value_get_int64 (value) <= MAXVAL)
arg->v_uint = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64) && g_value_get_uint64 (value) <= MAXVAL)
arg->v_uint = g_value_get_uint64 (value);
else
return_type_mismatch (value, G_TYPE_UINT);
return TRUE;
#undef MINVAL
#undef MAXVAL
case GI_TYPE_TAG_UINT32:
#define MINVAL 0
#define MAXVAL G_MAXUINT32
if (G_VALUE_HOLDS (value, G_TYPE_UINT))
arg->v_uint = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT) && g_value_get_int (value) >= MINVAL)
arg->v_uint = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG) && g_value_get_long (value) >= MINVAL && g_value_get_long (value) <= MAXVAL)
arg->v_uint = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG) && g_value_get_ulong (value) <= MAXVAL)
arg->v_uint = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64) && g_value_get_int64 (value) >= MINVAL && g_value_get_int64 (value) <= MAXVAL)
arg->v_uint = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64) && g_value_get_uint64 (value) <= MAXVAL)
arg->v_uint = g_value_get_uint64 (value);
else
return_type_mismatch (value, G_TYPE_UINT);
return TRUE;
#undef MINVAL
#undef MAXVAL
case GI_TYPE_TAG_UINT64:
#define MINVAL 0
#define MAXVAL G_MAXINT64
if (G_VALUE_HOLDS (value, G_TYPE_UINT64))
arg->v_uint64 = g_value_get_uint64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64) && g_value_get_int64 (value) >= MINVAL)
arg->v_uint64 = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT) && g_value_get_int (value) >= MINVAL)
arg->v_uint64 = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT))
arg->v_uint64 = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG) && g_value_get_long (value) >= MINVAL)
arg->v_uint64 = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG))
arg->v_uint64 = g_value_get_ulong (value);
else
return_type_mismatch (value, G_TYPE_INT);
return TRUE;
#undef MINVAL
#undef MAXVAL
case GI_TYPE_TAG_UNICHAR:
if (G_VALUE_HOLDS (value, G_TYPE_CHAR))
arg->v_uint32 = g_value_get_schar (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT) && g_value_get_int (value) >= 0)
arg->v_uint32 = (guint)g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT))
arg->v_uint32 = g_value_get_uint (value);
else
return_type_mismatch (value, G_TYPE_CHAR);
return TRUE;
case GI_TYPE_TAG_FLOAT:
if (G_VALUE_HOLDS (value, G_TYPE_DOUBLE))
arg->v_float = g_value_get_double (value);
else if (G_VALUE_HOLDS (value, G_TYPE_FLOAT))
arg->v_float = g_value_get_float (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT))
arg->v_float = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT))
arg->v_float = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG))
arg->v_float = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG))
arg->v_float = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64))
arg->v_float = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64))
arg->v_float = g_value_get_uint64 (value);
return TRUE;
case GI_TYPE_TAG_DOUBLE:
if (G_VALUE_HOLDS (value, G_TYPE_DOUBLE))
arg->v_double = g_value_get_double (value);
else if (G_VALUE_HOLDS (value, G_TYPE_FLOAT))
arg->v_double = g_value_get_float (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT))
arg->v_double = g_value_get_int (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT))
arg->v_double = g_value_get_uint (value);
else if (G_VALUE_HOLDS (value, G_TYPE_LONG))
arg->v_double = g_value_get_long (value);
else if (G_VALUE_HOLDS (value, G_TYPE_ULONG))
arg->v_double = g_value_get_ulong (value);
else if (G_VALUE_HOLDS (value, G_TYPE_INT64))
arg->v_double = g_value_get_int64 (value);
else if (G_VALUE_HOLDS (value, G_TYPE_UINT64))
arg->v_double = g_value_get_uint64 (value);
else
return_type_mismatch (value, G_TYPE_DOUBLE);
return TRUE;
case GI_TYPE_TAG_GTYPE:
if (G_VALUE_HOLDS (value, G_TYPE_GTYPE))
arg->v_long = g_value_get_gtype (value);
else if (G_VALUE_HOLDS (value, TMPL_TYPE_BASE_INFO) &&
g_value_get_boxed (value) != NULL &&
GI_IS_REGISTERED_TYPE_INFO (g_value_get_boxed (value)))
arg->v_long = gi_registered_type_info_get_g_type (g_value_get_boxed (value));
else
return_type_mismatch (value, G_TYPE_GTYPE);
return TRUE;
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
/* Callers are responsible for ensuring the GValue stays alive
* long enough for the string to be copied. */
if (G_VALUE_HOLDS (value, G_TYPE_STRING))
{
if (xfer == GI_TRANSFER_NOTHING)
arg->v_string = (char *)g_value_get_string (value);
else
arg->v_string = g_value_dup_string (value);
}
else
return_type_mismatch (value, G_TYPE_STRING);
return TRUE;
case GI_TYPE_TAG_GLIST:
case GI_TYPE_TAG_GSLIST:
case GI_TYPE_TAG_ARRAY:
case GI_TYPE_TAG_GHASH:
if (G_VALUE_HOLDS_BOXED (value))
arg->v_pointer = g_value_get_boxed (value);
else if (G_VALUE_HOLDS (value, G_TYPE_POINTER))
/* e. g. GSettings::change-event */
arg->v_pointer = g_value_get_pointer (value);
else
return_type_mismatch (value, G_TYPE_POINTER);
return TRUE;
case GI_TYPE_TAG_INTERFACE:
{
g_autoptr(GIBaseInfo) info = NULL;
info = gi_type_info_get_interface (type_info);
if (GI_IS_FLAGS_INFO (info))
{
if (G_VALUE_HOLDS (value, G_TYPE_FLAGS))
arg->v_uint = g_value_get_flags (value);
else
return_type_mismatch (value, G_TYPE_FLAGS);
return TRUE;
}
else if (GI_IS_ENUM_INFO (info))
{
if (G_VALUE_HOLDS_STRING (value))
{
if (find_enum_value ((GIEnumInfo *)info, g_value_get_string (value), &arg->v_int))
return TRUE;
}
if (!G_VALUE_HOLDS_ENUM (value))
{
return_type_mismatch (value, G_TYPE_ENUM);
return FALSE;
}
arg->v_int = g_value_get_enum (value);
return TRUE;
}
else if (GI_IS_INTERFACE_INFO (info) || GI_IS_OBJECT_INFO (info))
{
if (G_VALUE_HOLDS_PARAM (value))
arg->v_pointer = xfer == GI_TRANSFER_NOTHING ? g_value_get_param (value) : g_value_dup_param (value);
else
arg->v_pointer = xfer == GI_TRANSFER_NOTHING ? g_value_get_object (value) : g_value_dup_object (value);
return TRUE;
}
else if (GI_IS_STRUCT_INFO (info) || GI_IS_UNION_INFO (info))
{
if (G_VALUE_HOLDS (value, G_TYPE_BOXED))
arg->v_pointer = xfer == GI_TRANSFER_NOTHING ? g_value_get_boxed (value) : g_value_dup_boxed (value);
else if (G_VALUE_HOLDS (value, G_TYPE_VARIANT))
arg->v_pointer = xfer == GI_TRANSFER_NOTHING ? g_value_get_variant (value) : g_value_dup_variant (value);
else if (G_VALUE_HOLDS (value, G_TYPE_POINTER))
arg->v_pointer = g_value_get_pointer (value);
else
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_IMPLEMENTED,
"Converting GValue's of type '%s' is not implemented.",
g_type_name (G_VALUE_TYPE (value)));
return FALSE;
}
return TRUE;
}
else
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_IMPLEMENTED,
"Converting GValue's of type '%s' is not implemented.",
g_type_name (G_TYPE_FROM_INSTANCE (info)));
return FALSE;
}
g_assert_not_reached ();
}
case GI_TYPE_TAG_ERROR:
if (G_VALUE_HOLDS (value, G_TYPE_ERROR))
arg->v_pointer = xfer == GI_TRANSFER_NOTHING ? g_value_get_boxed (value) : g_value_dup_boxed (value);
else
return_type_mismatch (value, G_TYPE_ERROR);
return TRUE;
case GI_TYPE_TAG_VOID:
if (G_VALUE_HOLDS (value, G_TYPE_POINTER))
arg->v_pointer = g_value_get_pointer (value);
else
return_type_mismatch (value, G_TYPE_POINTER);
return TRUE;
default:
break;
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_NOT_IMPLEMENTED,
"Unknown marshaling error.");
return FALSE;
}
gboolean
tmpl_gi_argument_to_g_value (GValue *value,
GITypeInfo *type_info,
GIArgument *arg,
GITransfer xfer,
GError **error)
{
GITypeTag tag;
g_assert (value != NULL);
g_assert (type_info != NULL);
g_assert (arg != NULL);
tag = gi_type_info_get_tag (type_info);
switch (tag)
{
case GI_TYPE_TAG_VOID:
/* No type info */
return TRUE;
case GI_TYPE_TAG_BOOLEAN:
g_value_init (value, G_TYPE_BOOLEAN);
g_value_set_boolean (value, arg->v_boolean);
return TRUE;
case GI_TYPE_TAG_INT8:
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, arg->v_int8);
return TRUE;
case GI_TYPE_TAG_INT16:
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, arg->v_int16);
return TRUE;
case GI_TYPE_TAG_INT32:
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, arg->v_int32);
return TRUE;
case GI_TYPE_TAG_INT64:
g_value_init (value, G_TYPE_INT64);
g_value_set_int64 (value, arg->v_int64);
return TRUE;
case GI_TYPE_TAG_UINT8:
g_value_init (value, G_TYPE_UINT);
g_value_set_uint (value, arg->v_uint8);
return TRUE;
case GI_TYPE_TAG_UINT16:
g_value_init (value, G_TYPE_UINT);
g_value_set_uint (value, arg->v_uint16);
return TRUE;
case GI_TYPE_TAG_UINT32:
g_value_init (value, G_TYPE_UINT);
g_value_set_uint (value, arg->v_uint32);
return TRUE;
case GI_TYPE_TAG_UINT64:
g_value_init (value, G_TYPE_UINT64);
g_value_set_uint64 (value, arg->v_uint64);
return TRUE;
case GI_TYPE_TAG_FLOAT:
g_value_init (value, G_TYPE_FLOAT);
g_value_set_float (value, arg->v_float);
return TRUE;
case GI_TYPE_TAG_DOUBLE:
g_value_init (value, G_TYPE_DOUBLE);
g_value_set_float (value, arg->v_double);
return TRUE;
case GI_TYPE_TAG_GTYPE:
g_value_init (value, G_TYPE_GTYPE);
g_value_set_gtype (value, arg->v_long);
return TRUE;
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
g_value_init (value, G_TYPE_STRING);
if (xfer == GI_TRANSFER_NOTHING)
g_value_set_string (value, arg->v_string);
else
g_value_take_string (value, arg->v_string);
return TRUE;
case GI_TYPE_TAG_INTERFACE:
{
g_autoptr(GIBaseInfo) info = gi_type_info_get_interface (type_info);
if (GI_IS_OBJECT_INFO (info) || GI_IS_INTERFACE_INFO (info))
{
g_value_init (value, G_TYPE_OBJECT);
if (xfer == GI_TRANSFER_NOTHING)
g_value_set_object (value, arg->v_pointer);
else
g_value_take_object (value, arg->v_pointer);
return TRUE;
}
g_critical ("Cannot marshal type %s", g_type_name (G_TYPE_FROM_INSTANCE (info)));
}
break;
case GI_TYPE_TAG_ARRAY:
{
g_autoptr(GITypeInfo) param_type = gi_type_info_get_param_type (type_info, 0);
/* Handle NULL terminated char** */
if (param_type &&
gi_type_info_get_tag (param_type) == GI_TYPE_TAG_UTF8 &&
gi_type_info_is_zero_terminated (type_info))
{
g_value_init (value, G_TYPE_STRV);
if (xfer != GI_TRANSFER_EVERYTHING)
g_value_set_boxed (value, arg->v_pointer);
else
g_value_take_boxed (value, arg->v_pointer);
return TRUE;
}
}
break;
case GI_TYPE_TAG_GLIST:
case GI_TYPE_TAG_GSLIST:
case GI_TYPE_TAG_GHASH:
case GI_TYPE_TAG_ERROR:
break;
case GI_TYPE_TAG_UNICHAR:
{
gchar str[8];
str [g_unichar_to_utf8 (arg->v_int32, str)] = '\0';
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, str);
return TRUE;
}
default:
break;
}
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_TYPE_MISMATCH,
"Failed to decode value from GObject Introspection (0x%x)", tag);
return FALSE;
}
TmplGTypeFunc
tmpl_gi_get_gtype_func (GIBaseInfo *base_info)
{
GITypelib *typelib;
const char *symbol_name;
TmplGTypeFunc symbol = NULL;
if (base_info == NULL || !GI_IS_OBJECT_INFO (base_info))
return NULL;
if (!(typelib = gi_base_info_get_typelib (base_info)))
return NULL;
if (!(symbol_name = gi_object_info_get_type_init_function_name (GI_OBJECT_INFO (base_info))))
return NULL;
if (!gi_typelib_symbol (typelib, symbol_name, (gpointer *)&symbol))
return NULL;
return symbol;
}
07070100000051000081A400000000000000000000000168C4C096000004BF000000000000000000000000000000000000002500000000template-glib-3.38.0/src/tmpl-glib.h/* tmpl-glib.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_GLIB_H
#define TMPL_GLIB_H
#include <gio/gio.h>
G_BEGIN_DECLS
#define TMPL_GLIB_INSIDE
# include "tmpl-debug.h"
# include "tmpl-enums.h"
# include "tmpl-error.h"
# include "tmpl-expr.h"
# include "tmpl-expr-types.h"
# include "tmpl-scope.h"
# include "tmpl-symbol.h"
# include "tmpl-template.h"
# include "tmpl-template-locator.h"
# include "tmpl-version.h"
# include "tmpl-version-macros.h"
#undef TMPL_GLIB_INSIDE
G_END_DECLS
#endif /* TMPL_GLIB_H */
07070100000052000081A400000000000000000000000168C4C096000012C4000000000000000000000000000000000000002A00000000template-glib-3.38.0/src/tmpl-iter-node.c/* tmpl-iter-node.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "tmpl-iter-node"
#include "tmpl-debug.h"
#include "tmpl-error.h"
#include "tmpl-iter-node.h"
struct _TmplIterNode
{
TmplNode parent_instance;
gchar *identifier;
TmplExpr *expr;
GPtrArray *children;
};
G_DEFINE_TYPE (TmplIterNode, tmpl_iter_node, TMPL_TYPE_NODE)
static gboolean
tmpl_iter_node_accept (TmplNode *node,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error)
{
TmplIterNode *self = (TmplIterNode *)node;
TMPL_ENTRY;
g_assert (TMPL_IS_ITER_NODE (self));
g_assert (lexer != NULL);
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
while (TRUE)
{
TmplToken *token;
TmplNode *child;
if (!tmpl_lexer_next (lexer, &token, cancellable, error))
TMPL_RETURN (FALSE);
switch (tmpl_token_type (token))
{
case TMPL_TOKEN_EOF:
tmpl_token_free (token);
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Unexpectedly reached end of file");
TMPL_RETURN (FALSE);
case TMPL_TOKEN_END:
tmpl_token_free (token);
TMPL_RETURN (TRUE);
case TMPL_TOKEN_TEXT:
case TMPL_TOKEN_IF:
case TMPL_TOKEN_ELSE:
case TMPL_TOKEN_ELSE_IF:
case TMPL_TOKEN_FOR:
case TMPL_TOKEN_EXPRESSION:
case TMPL_TOKEN_INCLUDE:
default:
if (!(child = tmpl_node_new_for_token (token, error)))
{
tmpl_token_free (token);
TMPL_RETURN (FALSE);
}
g_ptr_array_add (self->children, child);
tmpl_token_free (token);
if (!tmpl_node_accept (child, lexer, cancellable, error))
TMPL_RETURN (FALSE);
break;
}
}
g_assert_not_reached ();
}
static void
tmpl_iter_node_visit_children (TmplNode *node,
TmplNodeVisitor visitor,
gpointer user_data)
{
TmplIterNode *self = (TmplIterNode *)node;
g_assert (TMPL_IS_ITER_NODE (self));
g_assert (visitor != NULL);
for (guint i = 0; i < self->children->len; i++)
{
TmplNode *child = g_ptr_array_index (self->children, i);
visitor (child, user_data);
}
}
static void
tmpl_iter_node_finalize (GObject *object)
{
TmplIterNode *self = (TmplIterNode *)object;
g_clear_pointer (&self->identifier, g_free);
g_clear_pointer (&self->expr, tmpl_expr_unref);
g_clear_pointer (&self->children, g_ptr_array_unref);
G_OBJECT_CLASS (tmpl_iter_node_parent_class)->finalize (object);
}
static void
tmpl_iter_node_class_init (TmplIterNodeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
TmplNodeClass *node_class = TMPL_NODE_CLASS (klass);
object_class->finalize = tmpl_iter_node_finalize;
node_class->accept = tmpl_iter_node_accept;
node_class->visit_children = tmpl_iter_node_visit_children;
}
static void
tmpl_iter_node_init (TmplIterNode *self)
{
self->children = g_ptr_array_new_with_free_func (g_object_unref);
}
/**
* tmpl_iter_node_new:
* @identifier: the name of the variable inside the loop.
* @expr: (transfer full): A #TmplExpr.
*
* Returns: (transfer full): A #TmplIterNode.
*/
TmplNode *
tmpl_iter_node_new (const gchar *identifier,
TmplExpr *expr)
{
TmplIterNode *self;
g_return_val_if_fail (expr != NULL, NULL);
self = g_object_new (TMPL_TYPE_ITER_NODE, NULL);
self->identifier = g_strdup (identifier);
self->expr = expr;
return TMPL_NODE (self);
}
/**
* tmpl_iter_node_get_expr:
*
* Returns: (transfer none): An #TmplExpr.
*/
TmplExpr *
tmpl_iter_node_get_expr (TmplIterNode *self)
{
g_return_val_if_fail (TMPL_IS_ITER_NODE (self), NULL);
return self->expr;
}
const gchar *
tmpl_iter_node_get_identifier (TmplIterNode *self)
{
g_return_val_if_fail (TMPL_IS_ITER_NODE (self), NULL);
return self->identifier;
}
07070100000053000081A400000000000000000000000168C4C0960000059F000000000000000000000000000000000000002A00000000template-glib-3.38.0/src/tmpl-iter-node.h/* tmpl-iter-node.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_ITER_NODE_H
#define TMPL_ITER_NODE_H
#include "tmpl-expr.h"
#include "tmpl-node.h"
G_BEGIN_DECLS
#define TMPL_TYPE_ITER_NODE (tmpl_iter_node_get_type())
G_DECLARE_FINAL_TYPE (TmplIterNode, tmpl_iter_node, TMPL, ITER_NODE, TmplNode)
TmplNode *tmpl_iter_node_new (const gchar *identifier,
TmplExpr *expr);
TmplExpr *tmpl_iter_node_get_expr (TmplIterNode *self);
const gchar *tmpl_iter_node_get_identifier (TmplIterNode *self);
G_END_DECLS
#endif /* TMPL_ITER_NODE_H */
07070100000054000081A400000000000000000000000168C4C096000014C7000000000000000000000000000000000000002900000000template-glib-3.38.0/src/tmpl-iterator.c/* tmpl-iterator.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gio/gio.h>
#include <string.h>
#include "tmpl-iterator.h"
typedef gboolean (*GetValue) (TmplIterator *iter,
GValue *value);
typedef gboolean (*MoveNext) (TmplIterator *iter);
typedef void (*Destroy) (TmplIterator *iter);
static gboolean
string_move_next (TmplIterator *iter)
{
if (iter->instance)
{
iter->instance = g_utf8_next_char ((gchar *)iter->instance);
return (*(gchar *)iter->instance) != 0;
}
return FALSE;
}
static gboolean
string_get_value (TmplIterator *iter,
GValue *value)
{
if (iter->instance)
{
gunichar ch = g_utf8_get_char ((gchar *)iter->instance);
gchar str[8];
str [g_unichar_to_utf8 (ch, str)] = '\0';
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, str);
return TRUE;
}
return FALSE;
}
static gboolean
strv_move_next (TmplIterator *iter)
{
guint index = GPOINTER_TO_INT (iter->data1);
index++;
if (iter->instance)
{
gchar **strv = iter->instance;
iter->data1 = GINT_TO_POINTER (index);
if (!strv[index])
{
iter->instance = NULL;
}
return strv[index] != 0;
}
return FALSE;
}
static gboolean
strv_get_value (TmplIterator *iter,
GValue *value)
{
guint index = GPOINTER_TO_INT (iter->data1);
if (iter->instance)
{
gchar **strv = iter->instance;
gchar *str = strv[index];
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, str);
return TRUE;
}
return FALSE;
}
static gboolean
list_model_move_next (TmplIterator *iter)
{
guint index = GPOINTER_TO_INT (iter->data1);
guint n_items = GPOINTER_TO_INT (iter->data2);
index++;
/* We are 1 based indexing here */
if (index <= n_items)
{
iter->data1 = GINT_TO_POINTER (index);
return TRUE;
}
return FALSE;
}
static gboolean
list_model_get_value (TmplIterator *iter,
GValue *value)
{
guint index = GPOINTER_TO_INT (iter->data1);
GObject *obj;
g_return_val_if_fail (index > 0, FALSE);
obj = g_list_model_get_item (iter->instance, index - 1);
g_value_init (value, g_list_model_get_item_type (iter->instance));
if (obj != NULL)
g_value_take_object (value, obj);
return TRUE;
}
void
tmpl_iterator_init (TmplIterator *iter,
const GValue *value)
{
memset (iter, 0, sizeof *iter);
if (value == NULL)
return;
if (G_VALUE_HOLDS_STRING (value))
{
iter->instance = (gchar *)g_value_get_string (value);
iter->move_next = string_move_next;
iter->get_value = string_get_value;
iter->destroy = NULL;
}
else if (G_VALUE_HOLDS (value, G_TYPE_OBJECT) &&
G_IS_LIST_MODEL (g_value_get_object (value)))
{
iter->instance = g_value_get_object (value);
iter->move_next = list_model_move_next;
iter->get_value = list_model_get_value;
iter->destroy = NULL;
if (iter->instance != NULL)
{
guint n_items;
n_items = g_list_model_get_n_items (iter->instance);
iter->data1 = GUINT_TO_POINTER (iter->data1);
iter->data2 = GUINT_TO_POINTER (n_items);
}
}
else if (G_VALUE_HOLDS_VARIANT(value) &&
g_variant_is_of_type (
g_value_get_variant(value), G_VARIANT_TYPE_STRING_ARRAY))
{
iter->instance = (const gchar **) g_variant_get_strv (
g_value_get_variant (value), NULL);
iter->move_next = strv_move_next;
iter->get_value = strv_get_value;
iter->destroy = NULL;
iter->data1 = GINT_TO_POINTER (-1);
}
else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
{
iter->instance = (const gchar **) g_value_get_boxed (value);
iter->move_next = strv_move_next;
iter->get_value = strv_get_value;
iter->destroy = NULL;
iter->data1 = GINT_TO_POINTER (-1);
}
else
{
g_critical ("Don't know how to iterate %s",
g_strdup_value_contents (value));
}
/* TODO: More iter types */
}
gboolean
tmpl_iterator_next (TmplIterator *iter)
{
if (iter == NULL || iter->move_next == NULL)
return FALSE;
return ((MoveNext)iter->move_next) (iter);
}
void
tmpl_iterator_get_value (TmplIterator *iter,
GValue *value)
{
((GetValue)iter->get_value) (iter, value);
}
void
tmpl_iterator_destroy (TmplIterator *iter)
{
if (iter->destroy != NULL)
((Destroy)(iter->destroy)) (iter);
memset (iter, 0, sizeof *iter);
}
07070100000055000081A400000000000000000000000168C4C0960000066E000000000000000000000000000000000000002900000000template-glib-3.38.0/src/tmpl-iterator.h/* tmpl-iterator.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_ITERATOR_H
#define TMPL_ITERATOR_H
#include <glib-object.h>
G_BEGIN_DECLS
typedef struct _TmplIterator TmplIterator;
struct _TmplIterator
{
/*< private >*/
gpointer instance; /* Data */
gpointer move_next; /* MoveNext */
gpointer get_value; /* GetValue */
gpointer destroy; /* Destroy */
gpointer data1;
gpointer data2;
gpointer data3;
gpointer data4;
};
void tmpl_iterator_init (TmplIterator *self,
const GValue *value);
gboolean tmpl_iterator_next (TmplIterator *self);
void tmpl_iterator_get_value (TmplIterator *self,
GValue *value);
void tmpl_iterator_destroy (TmplIterator *self);
G_END_DECLS
#endif /* TMPL_ITERATOR_H */
07070100000056000081A400000000000000000000000168C4C0960000183E000000000000000000000000000000000000002600000000template-glib-3.38.0/src/tmpl-lexer.c/* tmpl-lexer.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "tmpl-lexer"
#include "tmpl-error.h"
#include "tmpl-debug.h"
#include "tmpl-lexer.h"
#include "tmpl-template-locator.h"
#include "tmpl-token-input-stream.h"
struct _TmplLexer
{
GQueue *stream_stack;
TmplTemplateLocator *locator;
GHashTable *circular;
GQueue unget;
};
G_DEFINE_POINTER_TYPE (TmplLexer, tmpl_lexer)
TmplLexer *
tmpl_lexer_new (GInputStream *stream,
TmplTemplateLocator *locator)
{
TmplLexer *self;
g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
g_return_val_if_fail (!locator || TMPL_IS_TEMPLATE_LOCATOR (locator), NULL);
self = g_slice_new0 (TmplLexer);
self->stream_stack = g_queue_new ();
self->locator = locator ? g_object_ref (locator) : tmpl_template_locator_new ();
self->circular = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_queue_push_head (self->stream_stack, tmpl_token_input_stream_new (stream));
return self;
}
void
tmpl_lexer_free (TmplLexer *self)
{
if (self != NULL)
{
const GList *iter;
for (iter = self->stream_stack->head; iter != NULL; iter = iter->next)
{
TmplTokenInputStream *stream = iter->data;
g_object_unref (stream);
}
g_queue_clear_full (&self->unget, (GDestroyNotify)tmpl_token_free);
g_clear_pointer (&self->circular, g_hash_table_unref);
g_clear_pointer (&self->stream_stack, g_queue_free);
g_clear_object (&self->locator);
g_slice_free (TmplLexer, self);
}
}
/**
* tmpl_lexer_next:
* @self: A #TmplLexer.
* @token: (out) (transfer full): A location for a #TmplToken.
* @cancellable: (nullable): A #GCancellable or %NULL.
* @error: A location for a #GError or %NULL.
*
* Reads the next token.
*
* It is possible for %FALSE to be returned and @error left unset.
* This happens at the end of the stream.
*
* Returns: %TRUE if @token was set, otherwise %FALSE.
*/
gboolean
tmpl_lexer_next (TmplLexer *self,
TmplToken **token,
GCancellable *cancellable,
GError **error)
{
TmplTokenInputStream *stream;
GError *local_error = NULL;
gboolean ret = FALSE;
TMPL_ENTRY;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (token != NULL, FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
*token = NULL;
if (self->unget.length > 0)
{
*token = g_queue_pop_head (&self->unget);
TMPL_RETURN (TRUE);
}
while ((stream = g_queue_peek_head (self->stream_stack)))
{
if (!(*token = tmpl_token_input_stream_read_token (stream, cancellable, &local_error)))
{
/*
* If we finished this stream, try to move to the next one.
*/
if (local_error == NULL)
{
const gchar *path = g_object_get_data (G_OBJECT (stream), "PATH");
if (path != NULL && self->circular != NULL)
g_hash_table_remove (self->circular, path);
g_queue_pop_head (self->stream_stack);
g_object_unref (stream);
continue;
}
TMPL_GOTO (finish);
}
/*
* If the current token is an include token, we need to resolve the
* include path and read tokens from it.
*/
if (tmpl_token_type (*token) == TMPL_TOKEN_INCLUDE)
{
const gchar *path = tmpl_token_include_get_path (*token);
GInputStream *input;
g_assert (self->circular != NULL);
if (path == NULL)
{
local_error = g_error_new (TMPL_ERROR,
TMPL_ERROR_NOT_A_VALUE,
"Expected template path, got null");
g_clear_pointer (token, tmpl_token_free);
TMPL_GOTO (finish);
}
if (g_hash_table_contains (self->circular, path))
{
local_error = g_error_new (TMPL_ERROR,
TMPL_ERROR_CIRCULAR_INCLUDE,
"A circular include was detected: \"%s\"",
path);
g_clear_pointer (token, tmpl_token_free);
TMPL_GOTO (finish);
}
if (!(input = tmpl_template_locator_locate (self->locator, path, &local_error)))
{
g_clear_pointer (token, tmpl_token_free);
TMPL_GOTO (finish);
}
g_hash_table_insert (self->circular, g_strdup (path), NULL);
stream = tmpl_token_input_stream_new (input);
g_object_set_data_full (G_OBJECT (stream), "PATH", g_strdup (path), g_free);
g_queue_push_head (self->stream_stack, stream);
g_clear_pointer (token, tmpl_token_free);
g_object_unref (input);
continue;
}
ret = TRUE;
break;
}
if (*token == NULL)
{
*token = tmpl_token_new_eof ();
ret = TRUE;
}
finish:
if ((ret == FALSE) && (local_error != NULL))
g_propagate_error (error, local_error);
g_assert (ret == FALSE || *token != NULL);
TMPL_RETURN (ret);
}
void
tmpl_lexer_unget (TmplLexer *self,
TmplToken *token)
{
g_return_if_fail (self != NULL);
g_return_if_fail (token != NULL);
g_queue_push_head (&self->unget, token);
}
07070100000057000081A400000000000000000000000168C4C0960000069D000000000000000000000000000000000000002600000000template-glib-3.38.0/src/tmpl-lexer.h/* tmpl-lexer.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_LEXER_H
#define TMPL_LEXER_H
#include <gio/gio.h>
#include "tmpl-token.h"
#include "tmpl-template-locator.h"
G_BEGIN_DECLS
typedef struct _TmplLexer TmplLexer;
GType tmpl_lexer_get_type (void);
TmplLexer *tmpl_lexer_new (GInputStream *stream,
TmplTemplateLocator *locator);
void tmpl_lexer_free (TmplLexer *self);
void tmpl_lexer_unget (TmplLexer *self,
TmplToken *token);
gboolean tmpl_lexer_next (TmplLexer *self,
TmplToken **token,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* TMPL_LEXER_H */
07070100000058000081A400000000000000000000000168C4C096000020D3000000000000000000000000000000000000002500000000template-glib-3.38.0/src/tmpl-node.c/* tmpl-node.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "tmpl-node"
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include "tmpl-branch-node.h"
#include "tmpl-debug.h"
#include "tmpl-error.h"
#include "tmpl-expr-node.h"
#include "tmpl-iter-node.h"
#include "tmpl-node.h"
#include "tmpl-parser.h"
#include "tmpl-text-node.h"
typedef struct
{
GPtrArray *children;
} TmplNodePrivate;
typedef struct
{
GString *str;
gint depth;
} TmplNodePrintf;
static void tmpl_node_printf_string (TmplNode *self,
GString *str,
gint depth);
G_DEFINE_TYPE_WITH_PRIVATE (TmplNode, tmpl_node, G_TYPE_OBJECT)
static gboolean
tmpl_node_real_accept (TmplNode *self,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error)
{
TmplNodePrivate *priv = tmpl_node_get_instance_private (self);
TmplToken *token = NULL;
TmplNode *child;
TMPL_ENTRY;
g_assert (TMPL_IS_NODE (self));
g_assert (lexer != NULL);
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
while (TRUE)
{
if (!tmpl_lexer_next (lexer, &token, cancellable, error))
TMPL_RETURN (FALSE);
switch (tmpl_token_type (token))
{
case TMPL_TOKEN_TEXT:
case TMPL_TOKEN_EXPRESSION:
case TMPL_TOKEN_IF:
case TMPL_TOKEN_FOR:
if (!(child = tmpl_node_new_for_token (token, error)))
{
tmpl_token_free (token);
TMPL_RETURN (FALSE);
}
tmpl_token_free (token);
if (priv->children == NULL)
priv->children = g_ptr_array_new_with_free_func (g_object_unref);
g_ptr_array_add (priv->children, child);
if (!tmpl_node_accept (child, lexer, cancellable, error))
TMPL_RETURN (FALSE);
break;
case TMPL_TOKEN_EOF:
tmpl_token_free (token);
TMPL_RETURN (TRUE);
case TMPL_TOKEN_ELSE_IF:
case TMPL_TOKEN_ELSE:
case TMPL_TOKEN_END:
case TMPL_TOKEN_INCLUDE:
default:
tmpl_token_free (token);
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Received invalid token from lexer");
TMPL_RETURN (FALSE);
}
}
g_assert_not_reached ();
}
static void
tmpl_node_real_visit_children (TmplNode *self,
TmplNodeVisitor visitor,
gpointer user_data)
{
TmplNodePrivate *priv = tmpl_node_get_instance_private (self);
TMPL_ENTRY;
g_assert (TMPL_IS_NODE (self));
g_assert (visitor != NULL);
if (priv->children != NULL)
{
for (guint i = 0; i < priv->children->len; i++)
{
TmplNode *child = g_ptr_array_index (priv->children, i);
visitor (child, user_data);
}
}
TMPL_EXIT;
}
static void
tmpl_node_finalize (GObject *object)
{
TmplNode *self = (TmplNode *)object;
TmplNodePrivate *priv = tmpl_node_get_instance_private (self);
g_clear_pointer (&priv->children, g_ptr_array_unref);
G_OBJECT_CLASS (tmpl_node_parent_class)->finalize (object);
}
static void
tmpl_node_class_init (TmplNodeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = tmpl_node_finalize;
klass->accept = tmpl_node_real_accept;
klass->visit_children = tmpl_node_real_visit_children;
}
static void
tmpl_node_init (TmplNode *self)
{
}
TmplNode *
tmpl_node_new (void)
{
return g_object_new (TMPL_TYPE_NODE, NULL);
}
gboolean
tmpl_node_accept (TmplNode *self,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (TMPL_IS_NODE (self), FALSE);
g_return_val_if_fail (lexer != NULL, FALSE);
return TMPL_NODE_GET_CLASS (self)->accept (self, lexer, cancellable, error);
}
void
tmpl_node_visit_children (TmplNode *self,
TmplNodeVisitor visitor,
gpointer user_data)
{
g_return_if_fail (TMPL_IS_NODE (self));
g_return_if_fail (visitor != NULL);
return TMPL_NODE_GET_CLASS (self)->visit_children (self, visitor, user_data);
}
TmplNode *
tmpl_node_new_for_token (TmplToken *token,
GError **error)
{
TmplNode *ret;
TMPL_ENTRY;
g_return_val_if_fail (token != NULL, NULL);
switch (tmpl_token_type (token))
{
case TMPL_TOKEN_TEXT:
ret = tmpl_text_node_new (g_strdup (tmpl_token_get_text (token)));
TMPL_RETURN (ret);
case TMPL_TOKEN_IF:
{
TmplExpr *expr;
const gchar *exprstr;
exprstr = tmpl_token_get_text (token);
if (!(expr = tmpl_expr_from_string (exprstr, error)))
TMPL_RETURN (NULL);
ret = tmpl_branch_node_new (expr);
TMPL_RETURN (ret);
}
case TMPL_TOKEN_FOR:
{
const gchar *item_in_expr;
TmplExpr *expr;
TmplNode *node = NULL;
char *item = NULL;
char *exprstr = NULL;
if (!(item_in_expr = tmpl_token_get_text (token)))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Invalid for expression");
TMPL_RETURN (NULL);
}
if (2 != sscanf (item_in_expr, "%ms in %ms", &item, &exprstr))
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_SYNTAX_ERROR,
"Invalid for expression: %s", item_in_expr);
goto for_cleanup;
}
if (!(expr = tmpl_expr_from_string (exprstr, error)))
goto for_cleanup;
node = tmpl_iter_node_new (item, expr);
for_cleanup:
free (item);
free (exprstr);
return node;
}
case TMPL_TOKEN_EXPRESSION:
{
TmplExpr *expr;
const gchar *exprstr;
exprstr = tmpl_token_get_text (token);
if (!(expr = tmpl_expr_from_string (exprstr, error)))
TMPL_RETURN (NULL);
ret = tmpl_expr_node_new (expr);
TMPL_RETURN (ret);
}
case TMPL_TOKEN_ELSE_IF:
case TMPL_TOKEN_ELSE:
case TMPL_TOKEN_END:
case TMPL_TOKEN_INCLUDE:
case TMPL_TOKEN_EOF:
default:
g_assert_not_reached ();
TMPL_RETURN (NULL);
}
}
static void
tmpl_node_printf_visitor (TmplNode *node,
gpointer user_data)
{
TmplNodePrintf *state = user_data;
g_assert (TMPL_IS_NODE (node));
g_assert (state != NULL);
g_assert (state->str != NULL);
g_assert (state->depth > 0);
tmpl_node_printf_string (node, state->str, state->depth);
}
static void
tmpl_node_printf_string (TmplNode *self,
GString *str,
gint depth)
{
TmplNodePrintf state = { str, depth + 1 };
gint i;
g_assert (TMPL_IS_NODE (self));
g_assert (str != NULL);
for (i = 0; i < depth; i++)
g_string_append (str, " ");
g_string_append (str, G_OBJECT_TYPE_NAME (self));
g_string_append_c (str, '\n');
tmpl_node_visit_children (self,
tmpl_node_printf_visitor,
&state);
}
gchar *
tmpl_node_printf (TmplNode *self)
{
GString *str;
g_return_val_if_fail (TMPL_IS_NODE (self), NULL);
str = g_string_new (NULL);
tmpl_node_printf_string (self, str, 0);
return g_string_free (str, FALSE);
}
07070100000059000081A400000000000000000000000168C4C09600000930000000000000000000000000000000000000002500000000template-glib-3.38.0/src/tmpl-node.h/* tmpl-node.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_NODE_H
#define TMPL_NODE_H
#include <gio/gio.h>
#include "tmpl-lexer.h"
G_BEGIN_DECLS
#define TMPL_TYPE_NODE (tmpl_node_get_type())
G_DECLARE_DERIVABLE_TYPE (TmplNode, tmpl_node, TMPL, NODE, GObject)
typedef void (*TmplNodeVisitor) (TmplNode *self,
gpointer user_data);
struct _TmplNodeClass
{
GObjectClass parent_class;
gboolean (*accept) (TmplNode *self,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error);
void (*visit_children) (TmplNode *self,
TmplNodeVisitor visitor,
gpointer user_data);
};
TmplNode *tmpl_node_new (void);
TmplNode *tmpl_node_new_for_token (TmplToken *token,
GError **error);
gboolean tmpl_node_accept (TmplNode *self,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error);
gchar *tmpl_node_printf (TmplNode *self);
void tmpl_node_visit_children (TmplNode *self,
TmplNodeVisitor visitor,
gpointer user_data);
G_END_DECLS
#endif /* TMPL_NODE_H */
0707010000005A000081A400000000000000000000000168C4C09600001AD8000000000000000000000000000000000000002700000000template-glib-3.38.0/src/tmpl-parser.c/* tmpl-parser.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <glib/gi18n.h>
#include "tmpl-error.h"
#include "tmpl-lexer.h"
#include "tmpl-node.h"
#include "tmpl-parser.h"
struct _TmplParser
{
GObject parent_instance;
TmplNode *root;
GInputStream *stream;
TmplTemplateLocator *locator;
guint has_parsed : 1;
};
enum {
PROP_0,
PROP_LOCATOR,
PROP_STREAM,
LAST_PROP
};
G_DEFINE_TYPE (TmplParser, tmpl_parser, G_TYPE_OBJECT)
static GParamSpec *properties [LAST_PROP];
static void
tmpl_parser_set_stream (TmplParser *self,
GInputStream *stream)
{
g_assert (TMPL_IS_PARSER (self));
g_assert (!stream || G_IS_INPUT_STREAM (stream));
if (stream == NULL)
{
g_warning ("TmplParser created without a stream!");
return;
}
g_set_object (&self->stream, stream);
}
static void
tmpl_parser_finalize (GObject *object)
{
TmplParser *self = (TmplParser *)object;
g_clear_object (&self->locator);
g_clear_object (&self->stream);
g_clear_object (&self->root);
G_OBJECT_CLASS (tmpl_parser_parent_class)->finalize (object);
}
static void
tmpl_parser_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
TmplParser *self = TMPL_PARSER(object);
switch (prop_id)
{
case PROP_LOCATOR:
g_value_set_object (value, tmpl_parser_get_locator (self));
break;
case PROP_STREAM:
g_value_set_object (value, self->stream);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void
tmpl_parser_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
TmplParser *self = TMPL_PARSER(object);
switch (prop_id)
{
case PROP_LOCATOR:
tmpl_parser_set_locator (self, g_value_get_object (value));
break;
case PROP_STREAM:
tmpl_parser_set_stream (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void
tmpl_parser_class_init (TmplParserClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = tmpl_parser_finalize;
object_class->get_property = tmpl_parser_get_property;
object_class->set_property = tmpl_parser_set_property;
properties [PROP_LOCATOR] =
g_param_spec_object ("locator",
"Locator",
"The template locator for resolving includes",
TMPL_TYPE_TEMPLATE_LOCATOR,
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
properties [PROP_STREAM] =
g_param_spec_object ("stream",
"Stream",
"The stream to parse",
G_TYPE_INPUT_STREAM,
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, LAST_PROP, properties);
}
static void
tmpl_parser_init (TmplParser *self)
{
self->root = tmpl_node_new ();
}
TmplParser *
tmpl_parser_new (GInputStream *stream)
{
g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
return g_object_new (TMPL_TYPE_PARSER,
"stream", stream,
NULL);
}
/**
* tmpl_parser_get_root:
* @self: A #TmplNode.
*
* Gets the root node for the parser.
*
* See tmpl_parser_visit_children() to apply a visitor to all nodes created
* by the parser.
*
* Returns: (transfer none): An #TmplNode.
*/
TmplNode *
tmpl_parser_get_root (TmplParser *self)
{
g_return_val_if_fail (TMPL_IS_PARSER (self), NULL);
return self->root;
}
gboolean
tmpl_parser_parse (TmplParser *self,
GCancellable *cancellable,
GError **error)
{
TmplLexer *lexer;
GError *local_error = NULL;
g_return_val_if_fail (TMPL_IS_PARSER (self), FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
if (self->has_parsed)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_INVALID_STATE,
_("%s() may only be called once"),
G_STRFUNC);
return FALSE;
}
self->has_parsed = TRUE;
if (self->stream == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_INVALID_STATE,
_("Parser does not contain an input stream"));
return FALSE;
}
lexer = tmpl_lexer_new (self->stream, self->locator);
tmpl_node_accept (self->root, lexer, cancellable, &local_error);
tmpl_lexer_free (lexer);
if (local_error != NULL)
{
g_propagate_error (error, local_error);
return FALSE;
}
return TRUE;
}
/**
* tmpl_parser_get_locator:
* @self: an #TmplParser
*
* Gets the template loader used for resolving includes when parsing template
* files.
*
* Includes are performed using the {{include "path"}} token. The locator can
* be used to restrict where the templates are located from. By default, the
* search path is empty, and includes cannot be performed.
*
* Returns: (transfer none): A #TmplTemplateLocator.
*/
TmplTemplateLocator *
tmpl_parser_get_locator (TmplParser *self)
{
g_return_val_if_fail (TMPL_IS_PARSER (self), NULL);
return self->locator;
}
/**
* tmpl_parser_set_locator:
* @self: A #TmplParser
* @locator: A #TmplTemplateLocator
*
* Sets the template locator used to resolve {{include "path"}} directives.
*
* See tmpl_parser_get_locator() for more information.
*/
void
tmpl_parser_set_locator (TmplParser *self,
TmplTemplateLocator *locator)
{
g_return_if_fail (TMPL_IS_PARSER (self));
g_return_if_fail (!locator || TMPL_IS_TEMPLATE_LOCATOR (locator));
if (g_set_object (&self->locator, locator))
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LOCATOR]);
}
0707010000005B000081A400000000000000000000000168C4C096000006FF000000000000000000000000000000000000002700000000template-glib-3.38.0/src/tmpl-parser.h/* tmpl-parser.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_PARSER_H
#define TMPL_PARSER_H
#include <gio/gio.h>
#include "tmpl-node.h"
#include "tmpl-template-locator.h"
G_BEGIN_DECLS
#define TMPL_TYPE_PARSER (tmpl_parser_get_type())
G_DECLARE_FINAL_TYPE (TmplParser, tmpl_parser, TMPL, PARSER, GObject)
TmplNode *tmpl_parser_get_root (TmplParser *self);
TmplParser *tmpl_parser_new (GInputStream *stream);
TmplTemplateLocator *tmpl_parser_get_locator (TmplParser *self);
void tmpl_parser_set_locator (TmplParser *self,
TmplTemplateLocator *locator);
gboolean tmpl_parser_parse (TmplParser *self,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* TMPL_PARSER_H */
0707010000005C000081A400000000000000000000000168C4C096000034C0000000000000000000000000000000000000002600000000template-glib-3.38.0/src/tmpl-scope.c/* tmpl-scope.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "tmpl-gi-private.h"
#include "tmpl-scope.h"
#include "tmpl-symbol.h"
#include "tmpl-util-private.h"
struct _TmplScope
{
volatile gint ref_count;
TmplScope *parent;
GHashTable *symbols;
TmplScopeResolver resolver;
gpointer resolver_data;
GDestroyNotify resolver_destroy;
};
G_DEFINE_BOXED_TYPE (TmplScope, tmpl_scope, tmpl_scope_ref, tmpl_scope_unref)
TmplScope *
tmpl_scope_ref (TmplScope *self)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (self->ref_count > 0, NULL);
g_atomic_int_inc (&self->ref_count);
return self;
}
void
tmpl_scope_unref (TmplScope *self)
{
g_return_if_fail (self != NULL);
g_return_if_fail (self->ref_count > 0);
if (g_atomic_int_dec_and_test (&self->ref_count))
{
if (self->resolver_destroy)
g_clear_pointer (&self->resolver_data, self->resolver_destroy);
self->resolver = NULL;
self->resolver_destroy = NULL;
g_clear_pointer (&self->symbols, g_hash_table_unref);
g_clear_pointer (&self->parent, tmpl_scope_unref);
g_slice_free (TmplScope, self);
}
}
/**
* tmpl_scope_new:
*
* Creates a new scope to contain variables and custom expressions,
*
* Returns: (transfer full): A newly created #TmplScope.
*/
TmplScope *
tmpl_scope_new (void)
{
TmplScope *self;
self = g_slice_new0 (TmplScope);
self->ref_count = 1;
self->parent = NULL;
return self;
}
/**
* tmpl_scope_new_with_parent:
* @parent: (nullable): An optional parent scope
*
* Creates a new scope to contain variables and custom expressions,
* If @parent is set, the parent scope will be inherited.
*
* Returns: (transfer full): A newly created #TmplScope.
*/
TmplScope *
tmpl_scope_new_with_parent (TmplScope *parent)
{
TmplScope *self;
self = g_slice_new0 (TmplScope);
self->ref_count = 1;
self->parent = parent != NULL ? tmpl_scope_ref (parent) : NULL;
return self;
}
static TmplSymbol *
tmpl_scope_get_full (TmplScope *self,
const gchar *name,
gboolean create)
{
TmplSymbol *symbol = NULL;
TmplScope *parent;
g_return_val_if_fail (self != NULL, NULL);
/* See if this scope has the symbol */
if (self->symbols != NULL)
{
if ((symbol = g_hash_table_lookup (self->symbols, name)))
return symbol;
}
/* Try to locate the symbol in a parent scope */
for (parent = self->parent; parent != NULL; parent = parent->parent)
{
if (parent->symbols != NULL)
{
if ((symbol = g_hash_table_lookup (parent->symbols, name)))
return symbol;
}
}
/* Call our resolver helper to locate the symbol */
for (parent = self; parent != NULL; parent = parent->parent)
{
if (parent->resolver != NULL)
{
if (parent->resolver (parent, name, &symbol, parent->resolver_data) && symbol)
{
/* Pass ownership to our scope, and return a weak ref */
tmpl_scope_take (self, name, symbol);
return symbol;
}
}
}
if (create)
{
/* Define the symbol in this scope */
symbol = tmpl_symbol_new ();
tmpl_scope_take (self, name, symbol);
}
return symbol;
}
/**
* tmpl_scope_get:
*
* If the symbol could not be found, it will be allocated.
*
* Returns: (transfer none): A #TmplSymbol.
*/
TmplSymbol *
tmpl_scope_get (TmplScope *self,
const gchar *name)
{
return tmpl_scope_get_full (self, name, TRUE);
}
/**
* tmpl_scope_take:
* @self: A #TmplScope
* @name: The name of the symbol
* @symbol: (nullable) (transfer full): A #TmplSymbol or %NULL
*
* Sets the symbol named @name to @symbol in @scope.
*
* This differs from tmpl_scope_set() in that it takes ownership
* of @symbol.
*/
void
tmpl_scope_take (TmplScope *self,
const gchar *name,
TmplSymbol *symbol)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
if G_UNLIKELY (symbol == NULL)
{
if G_LIKELY (self->symbols != NULL)
g_hash_table_remove (self->symbols, name);
return;
}
if (self->symbols == NULL)
self->symbols = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify) tmpl_symbol_unref);
g_hash_table_insert (self->symbols, g_strdup (name), symbol);
}
/**
* tmpl_scope_set:
* @self: A #TmplScope
* @name: the name of the symbol
* @symbol: (nullable) (transfer none): An #TmplSymbol or %NULL.
*
* If the symbol already exists, it will be overwritten.
*
* If @symbol is %NULL, the symbol will be removed from scope.
*/
void
tmpl_scope_set (TmplScope *self,
const gchar *name,
TmplSymbol *symbol)
{
g_return_if_fail (self != NULL);
if (symbol != NULL)
tmpl_symbol_ref (symbol);
tmpl_scope_take (self, name, symbol);
}
/**
* tmpl_scope_set_value:
* @self: A #TmplScope
* @name: a name for the symbol
* @value: (nullable): A #GValue or %NULL
*
* Sets the contents of the symbol named @name to the value @value.
*/
void
tmpl_scope_set_value (TmplScope *self,
const gchar *name,
const GValue *value)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
tmpl_symbol_assign_value (tmpl_scope_get_full (self, name, TRUE), value);
}
/**
* tmpl_scope_set_boolean:
* @self: A #TmplScope
* @name: a name for the symbol
* @value: a #gboolean
*
* Sets the value of the symbol named @name to a gboolean value of @value.
*/
void
tmpl_scope_set_boolean (TmplScope *self,
const gchar *name,
gboolean value)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
tmpl_symbol_assign_boolean (tmpl_scope_get_full (self, name, TRUE), value);
}
/**
* tmpl_scope_set_double:
* @self: A #TmplScope
* @name: a name for the symbol
* @value: a #gdouble
*
* Sets the value of the symbol named @name to a gdouble value of @value.
*/
void
tmpl_scope_set_double (TmplScope *self,
const gchar *name,
gdouble value)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
tmpl_symbol_assign_double (tmpl_scope_get_full (self, name, TRUE), value);
}
/**
* tmpl_scope_set_object:
* @self: A #TmplScope
* @name: a name for the symbol
* @value: (type GObject.Object) (nullable): a #GObject or %NULL.
*
* Sets the value of the symbol named @name to the object @value.
*/
void
tmpl_scope_set_object (TmplScope *self,
const gchar *name,
gpointer value)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
g_return_if_fail (!value || G_IS_OBJECT (value));
tmpl_symbol_assign_object (tmpl_scope_get_full (self, name, TRUE), value);
}
/**
* tmpl_scope_set_variant:
* @self: A #TmplScope
* @name: a name for the symbol
* @value: (nullable): the variant to set it to, or %NULL
*
* Sets the value of the symbol named @name to the variant @value.
*
* If @value has a floating reference, it is consumed.
*/
void
tmpl_scope_set_variant (TmplScope *self,
const gchar *name,
GVariant *value)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
tmpl_symbol_assign_variant (tmpl_scope_get_full (self, name, TRUE),
value);
}
/**
* tmpl_scope_set_strv:
* @self: A #TmplScope
* @name: a name for the symbol
* @value: (nullable) (array zero-terminated=1): the value to set it to, or %NULL
*
* Sets the value of the symbol named @name to the strv @value.
*/
void
tmpl_scope_set_strv (TmplScope *self,
const gchar *name,
const gchar **value)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
tmpl_symbol_assign_variant (tmpl_scope_get_full (self, name, TRUE),
g_variant_new_strv (value, -1));
}
/**
* tmpl_scope_set_string:
* @self: A #TmplScope
* @name: a name for the symbol
* @value: (nullable): A string or %NULL.
*
* Sets the value of the symbol named @name to a string matching @value.
*/
void
tmpl_scope_set_string (TmplScope *self,
const gchar *name,
const gchar *value)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
tmpl_symbol_assign_string (tmpl_scope_get_full (self, name, TRUE), value);
}
/**
* tmpl_scope_peek:
*
* If the symbol could not be found, %NULL is returned.
*
* Returns: (transfer none) (nullable): A #TmplSymbol or %NULL.
*/
TmplSymbol *
tmpl_scope_peek (TmplScope *self,
const gchar *name)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (name != NULL, NULL);
return tmpl_scope_get_full (self, name, FALSE);
}
void
tmpl_scope_set_resolver (TmplScope *self,
TmplScopeResolver resolver,
gpointer user_data,
GDestroyNotify destroy)
{
g_return_if_fail (self != NULL);
if (resolver != self->resolver ||
user_data != self->resolver_data ||
destroy != self->resolver_destroy)
{
if (self->resolver && self->resolver_destroy && self->resolver_data)
{
g_clear_pointer (&self->resolver_data, self->resolver_destroy);
self->resolver_destroy = NULL;
self->resolver = NULL;
}
self->resolver = resolver;
self->resolver_data = user_data;
self->resolver_destroy = destroy;
}
}
/**
* tmpl_scope_require:
* @self: a #TmplScope
* @namespace_: the namespace to import into the scope
* @version: (nullable): the version of @namespace_ to import
*
* Imports @namespace_ into @self so it can be used by expressions.
*
* Returns: %TRUE if successful; otherwise %FALSE
*/
gboolean
tmpl_scope_require (TmplScope *self,
const char *namespace_,
const char *version)
{
GITypelib *typelib;
GValue value = G_VALUE_INIT;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (namespace_ != NULL, FALSE);
if (!(typelib = gi_repository_require (tmpl_repository_get_default (), namespace_, version, 0, NULL)))
return FALSE;
g_value_init (&value, TMPL_TYPE_TYPELIB);
g_value_set_pointer (&value, typelib);
tmpl_scope_set_value (self, namespace_, &value);
g_value_unset (&value);
return TRUE;
}
static void
tmpl_scope_list_symbols_internal (TmplScope *self,
GPtrArray *ar,
gboolean recursive)
{
GHashTableIter iter;
const char *key;
g_assert (self != NULL);
g_assert (ar != NULL);
g_hash_table_iter_init (&iter, self->symbols);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
g_ptr_array_add (ar, g_strdup (key));
if (recursive && self->parent)
tmpl_scope_list_symbols_internal (self->parent, ar, recursive);
}
/**
* tmpl_scope_list_symbols:
* @self: a #TmplScope
* @recursive: if the parent scopes should be included
*
* Gets the names of all symbols within the scope.
*
* Returns: (array zero-terminated=1) (element-type utf8) (transfer full):
* an array containing the names of all symbols within the scope.
*/
char **
tmpl_scope_list_symbols (TmplScope *self,
gboolean recursive)
{
GPtrArray *ar;
g_return_val_if_fail (self != NULL, NULL);
ar = g_ptr_array_new ();
tmpl_scope_list_symbols_internal (self, ar, recursive);
g_ptr_array_add (ar, NULL);
return (char **)g_ptr_array_free (ar, FALSE);
}
void
tmpl_scope_set_null (TmplScope *self,
const char *name)
{
GValue value = G_VALUE_INIT;
g_value_init (&value, G_TYPE_POINTER);
g_value_set_pointer (&value, NULL);
tmpl_scope_set_value (self, name, &value);
}
/**
* tmpl_scope_dup_string:
* @self: a #TmplScope
*
* Gets a string if the symbol @name is a string.
*
* Otherwise, %NULL is returned.
*
* Returns: (transfer full) (nullable): a string or %NULL
*
* Since: 3.36
*/
char *
tmpl_scope_dup_string (TmplScope *self,
const char *name)
{
GValue value = G_VALUE_INIT;
TmplSymbol *symbol;
char *ret = NULL;
if (!(symbol = tmpl_scope_peek (self, name)))
return NULL;
tmpl_symbol_get_value (symbol, &value);
if (G_VALUE_HOLDS_STRING (&value))
ret = g_value_dup_string (&value);
g_value_unset (&value);
return ret;
}
0707010000005D000081A400000000000000000000000168C4C09600001335000000000000000000000000000000000000002600000000template-glib-3.38.0/src/tmpl-scope.h/* tmpl-scope.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_SCOPE_H
#define TMPL_SCOPE_H
#include "tmpl-version-macros.h"
#include "tmpl-expr-types.h"
G_BEGIN_DECLS
typedef gboolean (*TmplScopeResolver) (TmplScope *scope,
const gchar *name,
TmplSymbol **symbol,
gpointer user_data);
TMPL_AVAILABLE_IN_ALL
TmplScope *tmpl_scope_new (void);
TMPL_AVAILABLE_IN_ALL
TmplScope *tmpl_scope_new_with_parent (TmplScope *parent);
TMPL_AVAILABLE_IN_ALL
TmplScope *tmpl_scope_ref (TmplScope *self);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_unref (TmplScope *self);
TMPL_AVAILABLE_IN_ALL
TmplSymbol *tmpl_scope_peek (TmplScope *self,
const gchar *name);
TMPL_AVAILABLE_IN_ALL
TmplSymbol *tmpl_scope_get (TmplScope *self,
const gchar *name);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_set (TmplScope *self,
const gchar *name,
TmplSymbol *symbol);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_take (TmplScope *self,
const gchar *name,
TmplSymbol *symbol);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_set_value (TmplScope *self,
const gchar *name,
const GValue *value);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_set_boolean (TmplScope *self,
const gchar *name,
gboolean value);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_set_double (TmplScope *self,
const gchar *name,
gdouble value);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_set_string (TmplScope *self,
const gchar *name,
const gchar *value);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_set_object (TmplScope *self,
const gchar *name,
gpointer value);
TMPL_AVAILABLE_IN_3_28
void tmpl_scope_set_strv (TmplScope *self,
const gchar *name,
const gchar **value);
TMPL_AVAILABLE_IN_3_28
void tmpl_scope_set_variant (TmplScope *self,
const gchar *name,
GVariant *value);
TMPL_AVAILABLE_IN_ALL
void tmpl_scope_set_resolver (TmplScope *self,
TmplScopeResolver resolver,
gpointer user_data,
GDestroyNotify destroy);
TMPL_AVAILABLE_IN_3_36
gboolean tmpl_scope_require (TmplScope *self,
const char *namespace_,
const char *version);
TMPL_AVAILABLE_IN_3_36
char **tmpl_scope_list_symbols (TmplScope *self,
gboolean recursive);
TMPL_AVAILABLE_IN_3_36
void tmpl_scope_set_null (TmplScope *self,
const char *name);
TMPL_AVAILABLE_IN_3_36
char *tmpl_scope_dup_string (TmplScope *self,
const char *name);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (TmplScope, tmpl_scope_unref)
G_END_DECLS
#endif /* TMPL_SCOPE_H */
0707010000005E000081A400000000000000000000000168C4C09600001C31000000000000000000000000000000000000002700000000template-glib-3.38.0/src/tmpl-symbol.c/* tmpl-symbol.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tmpl-expr.h"
#include "tmpl-symbol.h"
G_DEFINE_BOXED_TYPE (TmplSymbol, tmpl_symbol, tmpl_symbol_ref, tmpl_symbol_unref)
struct _TmplSymbol
{
volatile gint ref_count;
TmplSymbolType type;
union {
GValue value;
struct {
TmplExpr *expr;
GPtrArray *params;
} expr;
} u;
};
TmplSymbol *
tmpl_symbol_new (void)
{
TmplSymbol *self;
self = g_slice_new0 (TmplSymbol);
self->ref_count = 1;
self->type = TMPL_SYMBOL_VALUE;
return self;
}
static inline void
tmpl_symbol_clear (TmplSymbol *self)
{
if ((self->type == TMPL_SYMBOL_VALUE) &&
(G_VALUE_TYPE (&self->u.value) != G_TYPE_INVALID))
g_value_unset (&self->u.value);
else if (self->type == TMPL_SYMBOL_EXPR)
{
g_clear_pointer (&self->u.expr.expr, tmpl_expr_unref);
g_clear_pointer (&self->u.expr.params, g_ptr_array_unref);
}
}
TmplSymbol *
tmpl_symbol_ref (TmplSymbol *self)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (self->ref_count > 0, NULL);
g_atomic_int_inc (&self->ref_count);
return self;
}
void
tmpl_symbol_unref (TmplSymbol *self)
{
g_return_if_fail (self != NULL);
g_return_if_fail (self->ref_count > 0);
if (g_atomic_int_dec_and_test (&self->ref_count))
{
tmpl_symbol_clear (self);
g_slice_free (TmplSymbol, self);
}
}
void
tmpl_symbol_assign_value (TmplSymbol *self,
const GValue *value)
{
g_return_if_fail (self != NULL);
tmpl_symbol_clear (self);
self->type = TMPL_SYMBOL_VALUE;
if ((value != NULL) && (G_VALUE_TYPE (value) != G_TYPE_INVALID))
{
g_value_init (&self->u.value, G_VALUE_TYPE (value));
g_value_copy (value, &self->u.value);
}
}
/**
* tmpl_symbol_assign_expr: (skip)
* @self: A #TmplSymbol.
* @expr: (nullable): An expression to assign, or %NULL.
* @args: (element-type utf8): A #GPtrArray of strings.
*
* Sets the symbol as a %TMPL_SYMBOL_EXPR with the given ordered and
* named parameters.
*/
void
tmpl_symbol_assign_expr (TmplSymbol *self,
TmplExpr *expr,
GPtrArray *args)
{
g_return_if_fail (self != NULL);
tmpl_symbol_clear (self);
self->type = TMPL_SYMBOL_EXPR;
if (expr != NULL)
self->u.expr.expr = tmpl_expr_ref (expr);
if (args != NULL)
self->u.expr.params = g_ptr_array_ref (args);
}
TmplSymbolType
tmpl_symbol_get_symbol_type (TmplSymbol *self)
{
g_return_val_if_fail (self != NULL, 0);
return self->type;
}
/**
* tmpl_symbol_get_expr:
* @self: A #TmplSymbol
* @params: (out) (element-type utf8) (transfer none) (nullable): A list of parameters
*
* Returns: (transfer none): A #TmplExpr.
*/
TmplExpr *
tmpl_symbol_get_expr (TmplSymbol *self,
GPtrArray **params)
{
g_return_val_if_fail (self != NULL, 0);
if (self->type != TMPL_SYMBOL_EXPR)
{
g_warning ("Attempt to fetch TmplExpr from a value symbol");
return NULL;
}
if (params != NULL)
*params = self->u.expr.params;
return self->u.expr.expr;
}
void
tmpl_symbol_get_value (TmplSymbol *self,
GValue *value)
{
g_return_if_fail (self != NULL);
g_return_if_fail (value != NULL);
if (self->type != TMPL_SYMBOL_VALUE)
{
g_warning ("Attempt to fetch value from a expr symbol");
return;
}
if (G_VALUE_TYPE (&self->u.value) != G_TYPE_INVALID)
{
g_value_init (value, G_VALUE_TYPE (&self->u.value));
g_value_copy (&self->u.value, value);
}
}
void
tmpl_symbol_assign_boolean (TmplSymbol *self,
gboolean v_bool)
{
GValue value = G_VALUE_INIT;
g_return_if_fail (self != NULL);
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, v_bool);
tmpl_symbol_assign_value (self, &value);
g_value_unset (&value);
}
void
tmpl_symbol_assign_double (TmplSymbol *self,
gdouble v_double)
{
GValue value = G_VALUE_INIT;
g_return_if_fail (self != NULL);
g_value_init (&value, G_TYPE_DOUBLE);
g_value_set_double (&value, v_double);
tmpl_symbol_assign_value (self, &value);
g_value_unset (&value);
}
void
tmpl_symbol_assign_string (TmplSymbol *self,
const gchar *v_string)
{
GValue value = G_VALUE_INIT;
g_return_if_fail (self != NULL);
g_value_init (&value, G_TYPE_STRING);
g_value_set_string (&value, v_string);
tmpl_symbol_assign_value (self, &value);
g_value_unset (&value);
}
/**
* tmpl_symbol_assign_object:
* @self: A #TmplSymbol
* @v_object: (type GObject.Object) (nullable): a #GObject or %NULL.
*
* Sets the value to the object @v_object.
*/
void
tmpl_symbol_assign_object (TmplSymbol *self,
gpointer v_object)
{
GValue value = G_VALUE_INIT;
g_return_if_fail (self != NULL);
g_value_init (&value, G_TYPE_OBJECT);
g_value_set_object (&value, v_object);
tmpl_symbol_assign_value (self, &value);
g_value_unset (&value);
}
/**
* tmpl_symbol_assign_variant:
* @self: A #TmplSymbol
* @v_variant: (nullable): a #GVariant or %NULL.
*
* Sets the value to the #GVariant @v_variant.
*
* If @v_variant has a floating reference, it is consumed.
*/
void
tmpl_symbol_assign_variant (TmplSymbol *self,
GVariant *v_variant)
{
GValue value = G_VALUE_INIT;
g_return_if_fail (self != NULL);
g_value_init (&value, G_TYPE_VARIANT);
g_value_set_variant (&value, v_variant);
tmpl_symbol_assign_value (self, &value);
g_value_unset (&value);
}
/**
* tmpl_symbol_assign_strv:
* @self: A #TmplSymbol
* @strv: (nullable) (array zero-terminated=1): the value to set, or %NULL
*
* Sets the value to the strv @strv.
*/
void
tmpl_symbol_assign_strv (TmplSymbol *self,
const gchar **strv)
{
GValue value = G_VALUE_INIT;
g_return_if_fail (self != NULL);
g_value_init (&value, G_TYPE_VARIANT);
g_value_set_variant (&value, g_variant_new_strv (strv, -1));
tmpl_symbol_assign_value (self, &value);
g_value_unset (&value);
}
gboolean
tmpl_symbol_holds (TmplSymbol *self,
GType type)
{
return self != NULL &&
self->type == TMPL_SYMBOL_VALUE &&
self->u.value.g_type == type;
}
gpointer
tmpl_symbol_get_boxed (TmplSymbol *self)
{
if (self != NULL &&
self->type == TMPL_SYMBOL_VALUE &&
G_VALUE_HOLDS_BOXED (&self->u.value))
return g_value_get_boxed (&self->u.value);
return NULL;
}
0707010000005F000081A400000000000000000000000168C4C09600000CA3000000000000000000000000000000000000002700000000template-glib-3.38.0/src/tmpl-symbol.h/* tmpl-symbol.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_SYMBOL_H
#define TMPL_SYMBOL_H
#include "tmpl-version-macros.h"
#include "tmpl-expr-types.h"
G_BEGIN_DECLS
TMPL_AVAILABLE_IN_ALL
TmplSymbol *tmpl_symbol_new (void);
TMPL_AVAILABLE_IN_ALL
TmplSymbol *tmpl_symbol_ref (TmplSymbol *self);
TMPL_AVAILABLE_IN_ALL
void tmpl_symbol_unref (TmplSymbol *self);
TMPL_AVAILABLE_IN_ALL
TmplSymbolType tmpl_symbol_get_symbol_type (TmplSymbol *self);
TMPL_AVAILABLE_IN_3_36
gboolean tmpl_symbol_holds (TmplSymbol *self,
GType type);
TMPL_AVAILABLE_IN_ALL
void tmpl_symbol_get_value (TmplSymbol *self,
GValue *value);
TMPL_AVAILABLE_IN_3_36
gpointer tmpl_symbol_get_boxed (TmplSymbol *self);
TMPL_AVAILABLE_IN_ALL
TmplExpr *tmpl_symbol_get_expr (TmplSymbol *self,
GPtrArray **params);
TMPL_AVAILABLE_IN_ALL
void tmpl_symbol_assign_value (TmplSymbol *self,
const GValue *value);
TMPL_AVAILABLE_IN_ALL
void tmpl_symbol_assign_boolean (TmplSymbol *self,
gboolean v_bool);
TMPL_AVAILABLE_IN_ALL
void tmpl_symbol_assign_double (TmplSymbol *self,
gdouble v_double);
TMPL_AVAILABLE_IN_ALL
void tmpl_symbol_assign_string (TmplSymbol *self,
const gchar *v_string);
TMPL_AVAILABLE_IN_ALL
void tmpl_symbol_assign_object (TmplSymbol *self,
gpointer v_object);
TMPL_AVAILABLE_IN_3_28
void tmpl_symbol_assign_variant (TmplSymbol *self,
GVariant *v_variant);
TMPL_AVAILABLE_IN_3_28
void tmpl_symbol_assign_strv (TmplSymbol *self,
const gchar **strv);
TMPL_AVAILABLE_IN_ALL
void tmpl_symbol_assign_expr (TmplSymbol *self,
TmplExpr *expr,
GPtrArray *args);
G_END_DECLS
#endif /* TMPL_SYMBOL_H */
07070100000060000081A400000000000000000000000168C4C09600001A7D000000000000000000000000000000000000003100000000template-glib-3.38.0/src/tmpl-template-locator.c/* tmpl-template-locator.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <glib/gi18n.h>
#include "tmpl-error.h"
#include "tmpl-template-locator.h"
/**
* TmplTemplateLocator:
*
* The #TmplTemplateLoader class is used to specify how templates
* should be loaded. This can be used directly by your code that
* will compile the data streams into #TmplTemplate instances, or
* by a #TmplTemplate that is resolving includes from the
* `{{include "path.tmpl"}}` directive.
*
* See #TmplTemplate:locator for more information.
*/
typedef struct
{
GQueue *search_path;
} TmplTemplateLocatorPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (TmplTemplateLocator, tmpl_template_locator, G_TYPE_OBJECT)
static GInputStream *
tmpl_template_locator_locate_in_path (TmplTemplateLocator *self,
const gchar *path_base,
const gchar *path)
{
GInputStream *ret = NULL;
gchar *full_path;
g_assert (TMPL_IS_TEMPLATE_LOCATOR (self));
g_assert (path_base != NULL);
g_assert (path != NULL);
full_path = g_build_filename (path_base, path, NULL);
if (g_str_has_prefix (full_path, "resource://"))
{
/*
* A mediocre attempt to prevent escapes using ../
*/
if (strstr (full_path, "..") == NULL)
ret = g_resources_open_stream (full_path + strlen ("resource://"), 0, NULL);
}
else
{
GFile *parent = g_file_new_for_path (path_base);
GFile *file = g_file_new_for_path (full_path);
gchar *relative;
/*
* If the path tries to escape the search path, using ../../ or
* something clever, we will get an invalid path here.
*/
if ((relative = g_file_get_relative_path (parent, file)))
{
g_free (relative);
ret = (GInputStream *)g_file_read (file, NULL, NULL);
}
g_object_unref (parent);
g_object_unref (file);
}
g_free (full_path);
return ret;
}
static GInputStream *
tmpl_template_locator_real_locate (TmplTemplateLocator *self,
const gchar *path,
GError **error)
{
TmplTemplateLocatorPrivate *priv = tmpl_template_locator_get_instance_private (self);
GInputStream *ret = NULL;
const GList *iter;
const GList *search_path;
g_assert (TMPL_IS_TEMPLATE_LOCATOR (self));
g_assert (path != NULL);
search_path = priv->search_path->head;
for (iter = search_path; ret == NULL && iter != NULL; iter = iter->next)
{
const gchar *path_base = iter->data;
ret = tmpl_template_locator_locate_in_path (self, path_base, path);
}
if (ret == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_TEMPLATE_NOT_FOUND,
_("Failed to locate template “%s”"),
path);
return NULL;
}
return ret;
}
static void
tmpl_template_locator_finalize (GObject *object)
{
TmplTemplateLocator *self = (TmplTemplateLocator *)object;
TmplTemplateLocatorPrivate *priv = tmpl_template_locator_get_instance_private (self);
g_queue_free_full (priv->search_path, g_free);
priv->search_path = NULL;
G_OBJECT_CLASS (tmpl_template_locator_parent_class)->finalize (object);
}
static void
tmpl_template_locator_class_init (TmplTemplateLocatorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = tmpl_template_locator_finalize;
klass->locate = tmpl_template_locator_real_locate;
}
static void
tmpl_template_locator_init (TmplTemplateLocator *self)
{
TmplTemplateLocatorPrivate *priv = tmpl_template_locator_get_instance_private (self);
priv->search_path = g_queue_new ();
}
void
tmpl_template_locator_append_search_path (TmplTemplateLocator *self,
const gchar *path)
{
TmplTemplateLocatorPrivate *priv = tmpl_template_locator_get_instance_private (self);
g_return_if_fail (TMPL_IS_TEMPLATE_LOCATOR (self));
g_return_if_fail (path != NULL);
g_queue_push_tail (priv->search_path, g_strdup (path));
}
void
tmpl_template_locator_prepend_search_path (TmplTemplateLocator *self,
const gchar *path)
{
TmplTemplateLocatorPrivate *priv = tmpl_template_locator_get_instance_private (self);
g_return_if_fail (TMPL_IS_TEMPLATE_LOCATOR (self));
g_return_if_fail (path != NULL);
g_queue_push_head (priv->search_path, g_strdup (path));
}
/**
* tmpl_template_locator_get_search_path:
* @self: A #TmplTemplateLocator
*
* Gets the current search path used by the template locator.
*
* Returns: (transfer full): A %NULL-terminated array of strings.
*/
gchar **
tmpl_template_locator_get_search_path (TmplTemplateLocator *self)
{
TmplTemplateLocatorPrivate *priv = tmpl_template_locator_get_instance_private (self);
GPtrArray *ar;
const GList *iter;
g_return_val_if_fail (TMPL_IS_TEMPLATE_LOCATOR (self), NULL);
ar = g_ptr_array_new ();
for (iter = priv->search_path->head; iter != NULL; iter = iter->next)
{
const gchar *path = iter->data;
g_ptr_array_add (ar, g_strdup (path));
}
g_ptr_array_add (ar, NULL);
return (gchar **)g_ptr_array_free (ar, FALSE);
}
TmplTemplateLocator *
tmpl_template_locator_new (void)
{
return g_object_new (TMPL_TYPE_TEMPLATE_LOCATOR, NULL);
}
/**
* tmpl_template_locator_locate:
* @self: A #TmplTemplateLocator.
* @path: a relative path to the file
*
* This will resolve the relative path using the search paths found within
* the template loader.
*
* Returns: (transfer full): A #GInputStream or %NULL and @error is set.
*/
GInputStream *
tmpl_template_locator_locate (TmplTemplateLocator *self,
const gchar *path,
GError **error)
{
g_return_val_if_fail (TMPL_IS_TEMPLATE_LOCATOR (self), NULL);
g_return_val_if_fail (path != NULL, NULL);
return TMPL_TEMPLATE_LOCATOR_GET_CLASS (self)->locate (self, path, error);
}
07070100000061000081A400000000000000000000000168C4C09600000997000000000000000000000000000000000000003100000000template-glib-3.38.0/src/tmpl-template-locator.h/* tmpl-template-locator.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_TEMPLATE_LOCATOR_H
#define TMPL_TEMPLATE_LOCATOR_H
#include <gio/gio.h>
#include "tmpl-version-macros.h"
#include "tmpl-template-locator.h"
G_BEGIN_DECLS
#define TMPL_TYPE_TEMPLATE_LOCATOR (tmpl_template_locator_get_type())
G_DECLARE_DERIVABLE_TYPE (TmplTemplateLocator, tmpl_template_locator, TMPL, TEMPLATE_LOCATOR, GObject)
struct _TmplTemplateLocatorClass
{
GObjectClass parent_instance;
GInputStream *(*locate) (TmplTemplateLocator *self,
const gchar *path,
GError **error);
};
TMPL_AVAILABLE_IN_ALL
TmplTemplateLocator *tmpl_template_locator_new (void);
TMPL_AVAILABLE_IN_ALL
void tmpl_template_locator_append_search_path (TmplTemplateLocator *self,
const gchar *path);
TMPL_AVAILABLE_IN_ALL
void tmpl_template_locator_prepend_search_path (TmplTemplateLocator *self,
const gchar *path);
TMPL_AVAILABLE_IN_ALL
GInputStream *tmpl_template_locator_locate (TmplTemplateLocator *self,
const gchar *path,
GError **error);
TMPL_AVAILABLE_IN_ALL
gchar **tmpl_template_locator_get_search_path (TmplTemplateLocator *self);
G_END_DECLS
#endif /* TMPL_TEMPLATE_LOCATOR_H */
07070100000062000081A400000000000000000000000168C4C09600003D3B000000000000000000000000000000000000002900000000template-glib-3.38.0/src/tmpl-template.c/* tmpl-template.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "tmpl-template"
#include <glib/gi18n.h>
#include <string.h>
#include "tmpl-branch-node.h"
#include "tmpl-condition-node.h"
#include "tmpl-error.h"
#include "tmpl-expr-node.h"
#include "tmpl-iter-node.h"
#include "tmpl-iterator.h"
#include "tmpl-parser.h"
#include "tmpl-scope.h"
#include "tmpl-symbol.h"
#include "tmpl-template.h"
#include "tmpl-text-node.h"
#include "tmpl-util-private.h"
typedef struct
{
TmplParser *parser;
TmplTemplateLocator *locator;
} TmplTemplatePrivate;
typedef struct
{
TmplTemplate *self;
TmplNode *root;
GString *output;
TmplScope *scope;
GError **error;
gboolean result;
} TmplTemplateExpandState;
G_DEFINE_TYPE_WITH_PRIVATE (TmplTemplate, tmpl_template, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_LOCATOR,
LAST_PROP
};
static GParamSpec *properties [LAST_PROP];
static void
tmpl_template_finalize (GObject *object)
{
TmplTemplate *self = (TmplTemplate *)object;
TmplTemplatePrivate *priv = tmpl_template_get_instance_private (self);
g_clear_object (&priv->parser);
G_OBJECT_CLASS (tmpl_template_parent_class)->finalize (object);
}
static void
tmpl_template_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
TmplTemplate *self = TMPL_TEMPLATE(object);
switch (prop_id)
{
case PROP_LOCATOR:
g_value_set_object (value, tmpl_template_get_locator (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void
tmpl_template_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
TmplTemplate *self = TMPL_TEMPLATE(object);
switch (prop_id)
{
case PROP_LOCATOR:
tmpl_template_set_locator (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
}
}
static void
tmpl_template_class_init (TmplTemplateClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = tmpl_template_finalize;
object_class->get_property = tmpl_template_get_property;
object_class->set_property = tmpl_template_set_property;
properties [PROP_LOCATOR] =
g_param_spec_object ("locator",
"Locator",
"The locator used for resolving includes",
TMPL_TYPE_TEMPLATE_LOCATOR,
(G_PARAM_READWRITE |
G_PARAM_EXPLICIT_NOTIFY |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, LAST_PROP, properties);
}
static void
tmpl_template_init (TmplTemplate *self)
{
}
/**
* tmpl_template_new:
* @locator: (nullable): A #TmplTemplateLocator or %NULL.
*
* Creates a new #TmplTemplate.
*
* If @locator is specified, @locator will be used to resolve include
* directives when parsing the template.
*
* Returns: (transfer full): A #TmplTemplate.
*/
TmplTemplate *
tmpl_template_new (TmplTemplateLocator *locator)
{
return g_object_new (TMPL_TYPE_TEMPLATE,
"locator", locator,
NULL);
}
gboolean
tmpl_template_parse_file (TmplTemplate *self,
GFile *file,
GCancellable *cancellable,
GError **error)
{
GInputStream *stream;
gboolean ret = FALSE;
g_return_val_if_fail (TMPL_IS_TEMPLATE (self), FALSE);
g_return_val_if_fail (G_IS_FILE (file), FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
stream = (GInputStream *)g_file_read (file, cancellable, error);
if (stream != NULL)
{
ret = tmpl_template_parse (self, stream, cancellable, error);
g_object_unref (stream);
}
return ret;
}
gboolean
tmpl_template_parse_path (TmplTemplate *self,
const gchar *path,
GCancellable *cancellable,
GError **error)
{
gboolean ret;
GFile *file;
g_return_val_if_fail (TMPL_IS_TEMPLATE (self), FALSE);
g_return_val_if_fail (path != NULL, FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
file = g_file_new_for_path (path);
ret = tmpl_template_parse_file (self, file, cancellable, error);
g_object_unref (file);
return ret;
}
gboolean
tmpl_template_parse_resource (TmplTemplate *self,
const gchar *resource_path,
GCancellable *cancellable,
GError **error)
{
gchar *copied = NULL;
gboolean ret;
GFile *file;
g_return_val_if_fail (TMPL_IS_TEMPLATE (self), FALSE);
g_return_val_if_fail (resource_path != NULL, FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
if (!g_str_has_prefix (resource_path, "resource://"))
resource_path = copied = g_strdup_printf ("resource://%s", resource_path);
file = g_file_new_for_uri (resource_path);
ret = tmpl_template_parse_file (self, file, cancellable, error);
g_object_unref (file);
g_free (copied);
return ret;
}
gboolean
tmpl_template_parse_string (TmplTemplate *self,
const gchar *str,
GError **error)
{
GInputStream *stream;
gboolean ret;
g_return_val_if_fail (TMPL_IS_TEMPLATE (self), FALSE);
g_return_val_if_fail (str, FALSE);
stream = g_memory_input_stream_new_from_data (g_strdup (str), strlen (str), g_free);
ret = tmpl_template_parse (self, stream, NULL, error);
g_object_unref (stream);
return ret;
}
gboolean
tmpl_template_parse (TmplTemplate *self,
GInputStream *stream,
GCancellable *cancellable,
GError **error)
{
TmplTemplatePrivate *priv = tmpl_template_get_instance_private (self);
TmplParser *parser;
gboolean ret = FALSE;
g_return_val_if_fail (TMPL_IS_TEMPLATE (self), FALSE);
g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
parser = tmpl_parser_new (stream);
tmpl_parser_set_locator (parser, priv->locator);
if (tmpl_parser_parse (parser, cancellable, error))
{
g_set_object (&priv->parser, parser);
ret = TRUE;
}
g_object_unref (parser);
return ret;
}
static void
value_into_string (const GValue *value,
GString *str)
{
GValue transform = G_VALUE_INIT;
g_value_init (&transform, G_TYPE_STRING);
if (g_value_transform (value, &transform))
{
const gchar *tmp;
if (NULL != (tmp = g_value_get_string (&transform)))
g_string_append (str, tmp);
}
g_value_unset (&transform);
}
static void
tmpl_template_expand_visitor (TmplNode *node,
gpointer user_data)
{
TmplTemplateExpandState *state = user_data;
g_assert (TMPL_IS_NODE (node));
g_assert (state != NULL);
/* Short cirtcuit if an error occurred */
if (state->result == FALSE)
return;
if (TMPL_IS_TEXT_NODE (node))
{
g_string_append (state->output, tmpl_text_node_get_text (TMPL_TEXT_NODE (node)));
}
else if (TMPL_IS_EXPR_NODE (node))
{
GValue return_value = { 0 };
TmplExpr *expr;
expr = tmpl_expr_node_get_expr (TMPL_EXPR_NODE (node));
if (!tmpl_expr_eval (expr, state->scope, &return_value, state->error))
{
state->result = FALSE;
return;
}
value_into_string (&return_value, state->output);
g_value_unset (&return_value);
}
else if (TMPL_IS_BRANCH_NODE (node))
{
TmplNode *child;
GError *local_error = NULL;
child = tmpl_branch_node_branch (TMPL_BRANCH_NODE (node), state->scope, &local_error);
if (child != NULL)
tmpl_node_visit_children (child, tmpl_template_expand_visitor, state);
else if (local_error != NULL)
{
g_propagate_error (state->error, local_error);
state->result = FALSE;
}
}
else if (TMPL_IS_CONDITION_NODE (node))
{
TmplExpr *expr;
GValue value = G_VALUE_INIT;
expr = tmpl_condition_node_get_condition (TMPL_CONDITION_NODE (node));
if (!tmpl_expr_eval (expr, state->scope, &value, state->error))
{
state->result = FALSE;
return;
}
if (tmpl_value_as_boolean (&value))
tmpl_node_visit_children (node, tmpl_template_expand_visitor, state);
TMPL_CLEAR_VALUE (&value);
}
else if (TMPL_IS_ITER_NODE (node))
{
const gchar *identifier;
TmplExpr *expr;
GValue return_value = G_VALUE_INIT;
identifier = tmpl_iter_node_get_identifier (TMPL_ITER_NODE (node));
expr = tmpl_iter_node_get_expr (TMPL_ITER_NODE (node));
if (!tmpl_expr_eval (expr, state->scope, &return_value, state->error))
{
state->result = FALSE;
return;
}
if (tmpl_value_as_boolean (&return_value))
{
TmplIterator iter;
TmplScope *old_scope = state->scope;
TmplScope *new_scope = tmpl_scope_new_with_parent (old_scope);
TmplSymbol *symbol;
state->scope = new_scope;
symbol = tmpl_scope_get (new_scope, identifier);
tmpl_iterator_init (&iter, &return_value);
while (tmpl_iterator_next (&iter))
{
GValue value = G_VALUE_INIT;
tmpl_iterator_get_value (&iter, &value);
tmpl_symbol_assign_value (symbol, &value);
TMPL_CLEAR_VALUE (&value);
tmpl_node_visit_children (node, tmpl_template_expand_visitor, state);
if (state->result == FALSE)
break;
}
state->scope = old_scope;
tmpl_scope_unref (new_scope);
}
g_value_unset (&return_value);
}
else
{
g_warning ("Teach me how to expand %s", G_OBJECT_TYPE_NAME (node));
}
}
/**
* tmpl_template_expand:
* @self: A TmplTemplate.
* @stream: a #GOutputStream to write the results to
* @scope: (nullable): A #TmplScope containing state for the template, or %NULL.
* @cancellable: (nullable): An optional cancellable for the operation.
* @error: A location for a #GError, or %NULL.
*
* Expands a template into @stream using the @scope provided.
*
* @scope should have all of the variables set that are required to expand
* the template, or you will get a symbol reference error and %FALSE will
* be returned.
*
* To set a symbol value, get the symbol with tmpl_scope_get() and assign
* a value using tmpl_scope_assign_value() or similar methods.
*
* Returns: %TRUE if successful, otherwise %FALSE and @error is set.
*/
gboolean
tmpl_template_expand (TmplTemplate *self,
GOutputStream *stream,
TmplScope *scope,
GCancellable *cancellable,
GError **error)
{
TmplTemplatePrivate *priv = tmpl_template_get_instance_private (self);
TmplTemplateExpandState state = { 0 };
TmplScope *local_scope = NULL;
g_return_val_if_fail (TMPL_IS_TEMPLATE (self), FALSE);
g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
if (priv->parser == NULL)
{
g_set_error (error,
TMPL_ERROR,
TMPL_ERROR_INVALID_STATE,
_("Must parse template before expanding"));
return FALSE;
}
if (scope == NULL)
scope = local_scope = tmpl_scope_new ();
state.root = tmpl_parser_get_root (priv->parser);
state.self = self;
state.output = g_string_new (NULL);
state.result = TRUE;
state.error = error;
state.scope = scope;
tmpl_node_visit_children (state.root, tmpl_template_expand_visitor, &state);
if (state.result != FALSE)
state.result = g_output_stream_write_all (stream,
state.output->str,
state.output->len,
NULL,
cancellable,
error);
g_string_free (state.output, TRUE);
if (local_scope != NULL)
tmpl_scope_unref (local_scope);
g_assert (state.result == TRUE || (state.error == NULL || *state.error != NULL));
return state.result;
}
/**
* tmpl_template_expand_string:
* @self: A #TmplTemplate.
* @scope: (nullable): A #TmplScope or %NULL.
* @error: A location for a #GError, or %NULL
*
* Expands the template and returns the result as a string.
*
* Returns: A newly allocated string, or %NULL upon failure.
*/
gchar *
tmpl_template_expand_string (TmplTemplate *self,
TmplScope *scope,
GError **error)
{
GOutputStream *stream;
gchar zero = 0;
gchar *ret;
g_return_val_if_fail (TMPL_IS_TEMPLATE (self), NULL);
stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
if (!tmpl_template_expand (self, stream, scope, NULL, error) ||
!g_output_stream_write_all (stream, &zero, 1, NULL, NULL, error) ||
!g_output_stream_close (stream, NULL, error))
{
g_object_unref (stream);
if (error != NULL && *error == NULL)
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_UNKNOWN,
"An unknown error occurred while expanding the template");
return NULL;
}
ret = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (stream));
g_object_unref (stream);
return ret;
}
/**
* tmpl_template_get_locator:
* @self: A #TmplTemplate
*
* Gets the template locator used when resolving template includes.
*
* Returns: (transfer none): a #TmplTemplateLocator or %NULL.
*/
TmplTemplateLocator *
tmpl_template_get_locator (TmplTemplate *self)
{
TmplTemplatePrivate *priv = tmpl_template_get_instance_private (self);
g_return_val_if_fail (TMPL_IS_TEMPLATE (self), NULL);
return priv->locator;
}
void
tmpl_template_set_locator (TmplTemplate *self,
TmplTemplateLocator *locator)
{
TmplTemplatePrivate *priv = tmpl_template_get_instance_private (self);
g_return_if_fail (TMPL_IS_TEMPLATE (self));
g_return_if_fail (!locator || TMPL_IS_TEMPLATE_LOCATOR (locator));
if (g_set_object (&priv->locator, locator))
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LOCATOR]);
}
07070100000063000081A400000000000000000000000168C4C09600000FC1000000000000000000000000000000000000002900000000template-glib-3.38.0/src/tmpl-template.h/* tmpl-template.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_TEMPLATE_H
#define TMPL_TEMPLATE_H
#include <gio/gio.h>
#include "tmpl-version-macros.h"
#include "tmpl-scope.h"
#include "tmpl-template-locator.h"
G_BEGIN_DECLS
#define TMPL_TYPE_TEMPLATE (tmpl_template_get_type())
G_DECLARE_DERIVABLE_TYPE (TmplTemplate, tmpl_template, TMPL, TEMPLATE, GObject)
struct _TmplTemplateClass
{
GObjectClass parent_class;
};
TMPL_AVAILABLE_IN_ALL
TmplTemplate *tmpl_template_new (TmplTemplateLocator *locator);
TMPL_AVAILABLE_IN_ALL
TmplTemplateLocator *tmpl_template_get_locator (TmplTemplate *self);
TMPL_AVAILABLE_IN_ALL
void tmpl_template_set_locator (TmplTemplate *self,
TmplTemplateLocator *locator);
TMPL_AVAILABLE_IN_ALL
gboolean tmpl_template_parse_file (TmplTemplate *self,
GFile *file,
GCancellable *cancellable,
GError **error);
TMPL_AVAILABLE_IN_ALL
gboolean tmpl_template_parse_resource (TmplTemplate *self,
const gchar *path,
GCancellable *cancellable,
GError **error);
TMPL_AVAILABLE_IN_ALL
gboolean tmpl_template_parse_path (TmplTemplate *self,
const gchar *path,
GCancellable *cancellable,
GError **error);
TMPL_AVAILABLE_IN_ALL
gboolean tmpl_template_parse_string (TmplTemplate *self,
const gchar *input,
GError **error);
TMPL_AVAILABLE_IN_ALL
gboolean tmpl_template_parse (TmplTemplate *self,
GInputStream *stream,
GCancellable *cancellable,
GError **error);
TMPL_AVAILABLE_IN_ALL
gboolean tmpl_template_expand (TmplTemplate *self,
GOutputStream *stream,
TmplScope *scope,
GCancellable *cancellable,
GError **error);
TMPL_AVAILABLE_IN_ALL
gchar *tmpl_template_expand_string (TmplTemplate *self,
TmplScope *scope,
GError **error);
G_END_DECLS
#endif /* TMPL_TEMPLATE_H */
07070100000064000081A400000000000000000000000168C4C09600000A00000000000000000000000000000000000000002A00000000template-glib-3.38.0/src/tmpl-text-node.c/* tmpl-text-node.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "tmpl-text-node"
#include "tmpl-debug.h"
#include "tmpl-text-node.h"
struct _TmplTextNode
{
TmplNode parent_instance;
gchar *text;
};
G_DEFINE_TYPE (TmplTextNode, tmpl_text_node, TMPL_TYPE_NODE)
static gboolean
tmpl_text_node_accept (TmplNode *node,
TmplLexer *lexer,
GCancellable *cancellable,
GError **error)
{
TMPL_ENTRY;
/* no children */
TMPL_RETURN (TRUE);
}
static void
tmpl_text_node_visit_children (TmplNode *node,
TmplNodeVisitor visitor,
gpointer user_data)
{
TMPL_ENTRY;
/* no children */
TMPL_EXIT;
}
static void
tmpl_text_node_finalize (GObject *object)
{
TmplTextNode *self = (TmplTextNode *)object;
g_clear_pointer (&self->text, g_free);
G_OBJECT_CLASS (tmpl_text_node_parent_class)->finalize (object);
}
static void
tmpl_text_node_class_init (TmplTextNodeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
TmplNodeClass *node_class = TMPL_NODE_CLASS (klass);
object_class->finalize = tmpl_text_node_finalize;
node_class->accept = tmpl_text_node_accept;
node_class->visit_children = tmpl_text_node_visit_children;
}
static void
tmpl_text_node_init (TmplTextNode *node)
{
}
/**
* tmpl_text_node_new:
* @text: (transfer full): the text for the node
*
* Creates a new text node.
*
* Returns: (transfer full): the new node.
*/
TmplNode *
tmpl_text_node_new (gchar *text)
{
TmplTextNode *self;
self = g_object_new (TMPL_TYPE_TEXT_NODE, NULL);
self->text = text;
return TMPL_NODE (self);
}
const gchar *
tmpl_text_node_get_text (TmplTextNode *self)
{
g_return_val_if_fail (TMPL_IS_TEXT_NODE (self), NULL);
return self->text;
}
07070100000065000081A400000000000000000000000168C4C096000004EB000000000000000000000000000000000000002A00000000template-glib-3.38.0/src/tmpl-text-node.h/* tmpl-text-node.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_TEXT_NODE_H
#define TMPL_TEXT_NODE_H
#include "tmpl-node.h"
G_BEGIN_DECLS
#define TMPL_TYPE_TEXT_NODE (tmpl_text_node_get_type())
G_DECLARE_FINAL_TYPE (TmplTextNode, tmpl_text_node, TMPL, TEXT_NODE, TmplNode)
TmplNode *tmpl_text_node_new (gchar *text);
const gchar *tmpl_text_node_get_text (TmplTextNode *self);
void tmpl_text_node_set_text (TmplTextNode *self,
const gchar *text);
G_END_DECLS
#endif /* TMPL_TEXT_NODE_H */
07070100000066000081A400000000000000000000000168C4C096000021C2000000000000000000000000000000000000003300000000template-glib-3.38.0/src/tmpl-token-input-stream.c/* tmpl-token-input-stream.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "tmpl-token-input-stream.h"
#include "tmpl-token-private.h"
struct _TmplTokenInputStream
{
GDataInputStream parent_instance;
guint swallow_newline : 1;
guint last_was_text_with_newline : 1;
};
G_DEFINE_TYPE (TmplTokenInputStream, tmpl_token_input_stream, G_TYPE_DATA_INPUT_STREAM)
static void
tmpl_token_input_stream_class_init (TmplTokenInputStreamClass *klass)
{
}
static void
tmpl_token_input_stream_init (TmplTokenInputStream *self)
{
self->last_was_text_with_newline = TRUE;
}
static gboolean
tmpl_token_input_stream_read_unichar (TmplTokenInputStream *self,
gunichar *unichar,
GCancellable *cancellable,
GError **error)
{
GBufferedInputStream *stream = (GBufferedInputStream *)self;
gchar str[8] = { 0 };
gint c;
gint n;
gint i;
g_assert (TMPL_IS_TOKEN_INPUT_STREAM (self));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
if (-1 == (c = g_buffered_input_stream_read_byte (stream, cancellable, error)))
return FALSE;
if ((c & 0x80) == 0)
n = 1;
else if ((c & 0xE0) == 0xC0)
n = 2;
else if ((c & 0xF0) == 0xE0)
n = 3;
else if ((c & 0xF8) == 0xF0)
n = 4;
else if ((c & 0xFC) == 0xF8)
n = 5;
else if ((c & 0xFE) == 0xFC)
n = 6;
else
n = 0;
str [0] = c;
for (i = 1; i < n; i++)
{
if (-1 == (c = g_buffered_input_stream_read_byte (stream, cancellable, error)))
return FALSE;
str [i] = (gchar)c;
}
*unichar = g_utf8_get_char (str);
return TRUE;
}
static gchar *
tmpl_token_input_stream_read_tag (TmplTokenInputStream *self,
gsize *length,
GCancellable *cancellable,
GError **error)
{
GBufferedInputStream *stream = (GBufferedInputStream *)self;
GByteArray *ar;
GError *local_error = NULL;
gboolean in_string = FALSE;
guchar byte;
gint c;
g_assert (TMPL_IS_TOKEN_INPUT_STREAM (self));
g_assert (length != NULL);
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
ar = g_byte_array_new ();
while (TRUE)
{
if (-1 == (c = g_buffered_input_stream_read_byte (stream, cancellable, &local_error)))
goto failure;
switch (c)
{
case '\\':
if (in_string)
{
g_byte_array_append (ar, (const guchar *)"\\", 1);
if (-1 == (c = g_buffered_input_stream_read_byte (stream, cancellable, &local_error)))
goto failure;
}
break;
case '"':
in_string = !in_string;
break;
case '}':
if (!in_string)
{
if (-1 == (c = g_buffered_input_stream_read_byte (stream, cancellable, &local_error)))
goto failure;
/* Check if we got }} */
if (c == '}')
goto finish;
g_byte_array_append (ar, (const guchar *)"}", 1);
}
break;
default:
break;
}
byte = (guchar)c;
g_byte_array_append (ar, (const guchar *)&byte, 1);
}
finish:
*length = ar->len;
byte = 0;
g_byte_array_append (ar, (const guchar *)&byte, 1);
return (gchar *)g_byte_array_free (ar, FALSE);
failure:
*length = 0;
g_byte_array_free (ar, TRUE);
if (local_error)
g_propagate_error (error, local_error);
return FALSE;
}
/**
* tmpl_token_input_stream_read_token:
* @self: An #TmplTokenInputStream
* @error: (nullable): An optional location for a #GError
*
* Reads the next token from the underlying stream.
*
* If there was an error, %NULL is returned and @error is set.
*
* Returns: (transfer full): A #TmplToken or %NULL.
*/
TmplToken *
tmpl_token_input_stream_read_token (TmplTokenInputStream *self,
GCancellable *cancellable,
GError **error)
{
GDataInputStream *stream = (GDataInputStream *)self;
TmplToken *ret;
GError *local_error = NULL;
gunichar ch;
gchar *text;
gsize len;
g_return_val_if_fail (TMPL_IS_TOKEN_INPUT_STREAM (self), NULL);
/*
* The syntax of the template language is very simple. All of our symbols
* start with {{ and end with }}. We use \ to escape, and you only ever
* need to escape the opening of {{ like \{{.
*
* We scan ahead until a { or \ and take appropriate action based upon
* peeking at the next char.
*
* Once we resolve that, we walk forward past the expression until }}.
* To walk past the expression, we need to know when we are in a
* string, since }} could theoretically be in there too.
*/
text = g_data_input_stream_read_upto (stream, "\\{", -1, &len, cancellable, error);
/*
* Handle end of stream.
*/
if (text == NULL)
return NULL;
/*
* If we start with a newline, and need to swallow it (as can happen if the
* last tag was at the end of the line), skip past the newline.
*/
if (self->swallow_newline && *text == '\n')
{
gchar *tmp = g_strdup (text + 1);
g_free (text);
text = tmp;
}
self->swallow_newline = FALSE;
/*
* Handle successful read up to \ or {.
*/
if (*text != '\0')
{
self->last_was_text_with_newline = g_str_has_suffix (text, "\n");
return tmpl_token_new_text (text);
}
g_free (text);
/*
* Peek what type of delimiter we hit.
*/
ch = g_data_input_stream_read_byte (stream, cancellable, &local_error);
/* Probably just end of file */
if (ch == 0)
return NULL;
/*
* Handle possible escaped \{.
*/
if (ch == '\\')
{
gchar str[8] = { 0 };
self->last_was_text_with_newline = FALSE;
/*
* Get the next char after \.
*/
if (!tmpl_token_input_stream_read_unichar (self, &ch, cancellable, error))
return tmpl_token_new_unichar ('\\');
/*
* Handle escaping {.
*/
if (ch == '{')
return tmpl_token_new_unichar ('{');
/*
* Nothing escaped, return string as it was read.
*/
g_unichar_to_utf8 (ch, str);
return tmpl_token_new_text (g_strdup_printf ("\\%s", str));
}
g_assert (ch == '{');
/*
* Look for { following {. If we reached the end of the stream, just
* return a token for the final {.
*/
if (!tmpl_token_input_stream_read_unichar (self, &ch, cancellable, error))
{
self->last_was_text_with_newline = FALSE;
return tmpl_token_new_unichar ('{');
}
/*
* If this is not a {{, then just return a string for the pair.
*/
if (ch != '{')
{
gchar str[8] = { 0 };
g_unichar_to_utf8 (ch, str);
self->last_was_text_with_newline = FALSE;
return tmpl_token_new_text (g_strdup_printf ("{%s", str));
}
/*
* Scan ahead until we find }}.
*/
if (!(text = tmpl_token_input_stream_read_tag (self, &len, cancellable, error)))
return NULL;
ret = tmpl_token_new_generic (g_steal_pointer (&text));
self->swallow_newline = ret != NULL && ret->type != TMPL_TOKEN_EXPRESSION;
self->last_was_text_with_newline = FALSE;
return ret;
}
/**
* tmpl_token_input_stream_new:
* @base_stream: the stream to read from
*
* Creates a #TmplTokenInputStream using @base_stream for the raw
* text stream.
*
* Returns: (transfer full): An #TmplTokenInputStream.
*/
TmplTokenInputStream *
tmpl_token_input_stream_new (GInputStream *base_stream)
{
g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL);
return g_object_new (TMPL_TYPE_TOKEN_INPUT_STREAM,
"base-stream", base_stream,
NULL);
}
07070100000067000081A400000000000000000000000168C4C0960000065B000000000000000000000000000000000000003300000000template-glib-3.38.0/src/tmpl-token-input-stream.h/* tmpl-token-input-stream.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_TOKEN_INPUT_STREAM_H
#define TMPL_TOKEN_INPUT_STREAM_H
#include <gio/gio.h>
#include "tmpl-token.h"
G_BEGIN_DECLS
#define TMPL_TYPE_TOKEN_INPUT_STREAM (tmpl_token_input_stream_get_type())
G_DECLARE_FINAL_TYPE (TmplTokenInputStream, tmpl_token_input_stream, TMPL, TOKEN_INPUT_STREAM, GDataInputStream)
TmplTokenInputStream *tmpl_token_input_stream_new (GInputStream *base_stream);
TmplToken *tmpl_token_input_stream_read_token (TmplTokenInputStream *self,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif /* TMPL_TOKEN_INPUT_STREAM_H */
07070100000068000081A400000000000000000000000168C4C096000003C0000000000000000000000000000000000000002E00000000template-glib-3.38.0/src/tmpl-token-private.h/* tmpl-token-private.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_TOKEN_PRIVATE_H
#define TMPL_TOKEN_PRIVATE_H
#include "tmpl-token.h"
G_BEGIN_DECLS
struct _TmplToken
{
TmplTokenType type;
gchar *text;
};
G_END_DECLS
#endif /* TMPL_TOKEN_PRIVATE_H */
07070100000069000081A400000000000000000000000168C4C09600000ED1000000000000000000000000000000000000002600000000template-glib-3.38.0/src/tmpl-token.c/* tmpl-token.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include "tmpl-token-private.h"
static TmplToken *
tmpl_token_new (void)
{
TmplToken *self;
self = g_slice_new0 (TmplToken);
return self;
}
void
tmpl_token_free (TmplToken *self)
{
if (self != NULL)
{
g_free (self->text);
g_slice_free (TmplToken, self);
}
}
TmplToken *
tmpl_token_new_eof (void)
{
TmplToken *ret;
ret = tmpl_token_new ();
ret->type = TMPL_TOKEN_EOF;
return ret;
}
/**
* tmpl_token_new_text:
* @text: (transfer full): The text for the token.
*
* Creates a new #TmplToken containing @text.
* This is a text literal type.
*
* Returns: (transfer full): A newly allocated #TmplToken.
*/
TmplToken *
tmpl_token_new_text (gchar *text)
{
TmplToken *self;
self = tmpl_token_new ();
self->type = TMPL_TOKEN_TEXT;
self->text = text;
return self;
}
TmplToken *
tmpl_token_new_unichar (gunichar ch)
{
gchar utf8[8];
gint len;
len = g_unichar_to_utf8 (ch, utf8);
utf8 [len] = '\0';
return tmpl_token_new_text (g_strdup (utf8));
}
TmplTokenType
tmpl_token_type (TmplToken *self)
{
g_return_val_if_fail (self != NULL, 0);
return self->type;
}
gchar *
tmpl_token_include_get_path (TmplToken *self)
{
const char *str;
char *path = NULL;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (self->type == TMPL_TOKEN_INCLUDE, NULL);
str = self->text;
if (!g_str_has_prefix (str, "include "))
return NULL;
str += strlen ("include ");
while (*str == ' ') str++;
if (str[0] != '"')
return NULL;
path = g_strdup (str+1);
if (path[0] == 0 || path[strlen(path)-1] != '"')
{
g_free (path);
return NULL;
}
path[strlen(path)-1] = 0;
return path;
}
TmplToken *
tmpl_token_new_generic (gchar *text)
{
TmplToken *self;
g_return_val_if_fail (text != NULL, NULL);
self = g_slice_new0 (TmplToken);
if (g_str_has_prefix (text, "if "))
{
self->type = TMPL_TOKEN_IF;
self->text = g_strstrip (g_strdup (text + 3));
}
else if (g_str_has_prefix (text, "else if "))
{
self->type = TMPL_TOKEN_ELSE_IF;
self->text = g_strstrip (g_strdup (text + 8));
}
else if (g_str_has_prefix (text, "else"))
{
self->type = TMPL_TOKEN_ELSE;
self->text = NULL;
}
else if (g_str_has_prefix (text, "end"))
{
self->type = TMPL_TOKEN_END;
self->text = NULL;
}
else if (g_str_has_prefix (text, "for "))
{
self->type = TMPL_TOKEN_FOR;
self->text = g_strstrip (g_strdup (text + 4));
}
else if (g_str_has_prefix (text, "include "))
{
self->type = TMPL_TOKEN_INCLUDE;
self->text = g_strstrip (g_strdup (text));
}
else
{
self->type = TMPL_TOKEN_EXPRESSION;
self->text = g_strstrip (text);
text = NULL;
}
g_free (text);
return self;
}
const gchar *
tmpl_token_get_text (TmplToken *self)
{
g_return_val_if_fail (self != NULL, NULL);
return self->text;
}
0707010000006A000081A400000000000000000000000168C4C096000006C4000000000000000000000000000000000000002600000000template-glib-3.38.0/src/tmpl-token.h/* tmpl-token.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (TMPL_GLIB_INSIDE) && !defined (TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#ifndef TMPL_TOKEN_H
#define TMPL_TOKEN_H
#include <glib-object.h>
G_BEGIN_DECLS
typedef struct _TmplToken TmplToken;
typedef enum
{
TMPL_TOKEN_EOF,
TMPL_TOKEN_TEXT,
TMPL_TOKEN_IF,
TMPL_TOKEN_ELSE_IF,
TMPL_TOKEN_ELSE,
TMPL_TOKEN_END,
TMPL_TOKEN_FOR,
TMPL_TOKEN_EXPRESSION,
TMPL_TOKEN_INCLUDE,
} TmplTokenType;
TmplToken *tmpl_token_new_generic (gchar *str);
TmplToken *tmpl_token_new_unichar (gunichar ch);
TmplToken *tmpl_token_new_text (gchar *text);
TmplToken *tmpl_token_new_eof (void);
const gchar *tmpl_token_get_text (TmplToken *self);
TmplTokenType tmpl_token_type (TmplToken *self);
void tmpl_token_free (TmplToken *self);
gchar *tmpl_token_include_get_path (TmplToken *self);
G_END_DECLS
#endif /* TMPL_TOKEN_H */
0707010000006B000081A400000000000000000000000168C4C09600000564000000000000000000000000000000000000002D00000000template-glib-3.38.0/src/tmpl-util-private.h/* tmpl-util-private.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_UTIL_PRIVATE_H
#define TMPL_UTIL_PRIVATE_H
#include <girepository/girepository.h>
G_BEGIN_DECLS
#define TMPL_CLEAR_VALUE(v) { if (G_VALUE_TYPE(v)) g_value_unset(v); }
void tmpl_destroy_in_main_context (GMainContext *main_context,
gpointer data,
GDestroyNotify destroy);
gchar *tmpl_value_repr (const GValue *value);
gboolean tmpl_value_as_boolean (const GValue *value);
GIRepository *tmpl_repository_get_default (void);
G_END_DECLS
#endif /* TMPL_UTIL_PRIVATE_H */
0707010000006C000081A400000000000000000000000168C4C09600001551000000000000000000000000000000000000002500000000template-glib-3.38.0/src/tmpl-util.c/* tmpl-util-private.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <glib-object.h>
#include "tmpl-gi-private.h"
#include "tmpl-util-private.h"
static gboolean
destroy_in_main_context_cb (gpointer data)
{
struct {
gpointer data;
GDestroyNotify destroy;
} *state = data;
g_assert (state != NULL);
g_assert (state->data != NULL);
g_assert (state->destroy != NULL);
state->destroy (state->data);
g_slice_free1 (sizeof *state, state);
return G_SOURCE_REMOVE;
}
void
tmpl_destroy_in_main_context (GMainContext *main_context,
gpointer data,
GDestroyNotify destroy)
{
GSource *idle;
struct {
gpointer data;
GDestroyNotify destroy;
} *state;
g_assert (main_context != NULL);
g_assert (data != NULL);
g_assert (destroy != NULL);
state = g_slice_alloc (sizeof *state);
state->data = data;
state->destroy = destroy;
idle = g_idle_source_new ();
g_source_set_callback (idle, destroy_in_main_context_cb, state, NULL);
g_source_attach (idle, main_context);
}
gchar *
tmpl_value_repr (const GValue *value)
{
GValue coerced = G_VALUE_INIT;
gchar *ret = NULL;
g_return_val_if_fail (value != NULL, NULL);
if (G_VALUE_TYPE (value) != G_TYPE_INVALID)
{
g_value_init (&coerced, G_TYPE_STRING);
if (G_VALUE_HOLDS_BOOLEAN (value))
{
ret = g_strdup (g_value_get_boolean (value) ? "true" : "false");
}
else if (G_VALUE_HOLDS_STRING (value) && g_value_get_string (value))
{
gchar *escaped;
escaped = g_strescape (g_value_get_string (value), NULL);
ret = g_strdup_printf ("\"%s\"", escaped);
g_free (escaped);
}
else if (G_VALUE_HOLDS (value, TMPL_TYPE_TYPELIB))
{
GITypelib *tl = g_value_get_pointer (value);
if (tl != NULL)
{
const gchar *ns = gi_typelib_get_namespace (tl);
ret = g_strdup_printf ("<Namespace \"%s\">", ns);
}
else
{
ret = g_strdup_printf ("<Namespace at %p>", tl);
}
}
else if (g_value_transform (value, &coerced))
ret = g_value_dup_string (&coerced);
else if (G_VALUE_HOLDS_OBJECT (value))
{
GObject *obj = g_value_get_object (value);
ret = g_strdup_printf ("<%s at %p>",
obj ? G_OBJECT_TYPE_NAME (obj)
: G_VALUE_TYPE_NAME (value),
obj);
}
else if (G_VALUE_HOLDS_BOXED (value))
ret = g_strdup_printf ("<%s at %p>",
G_VALUE_TYPE_NAME (value),
g_value_get_boxed (value));
else
ret = g_strdup_printf ("<%s>", G_VALUE_TYPE_NAME (value));
g_value_unset (&coerced);
}
return ret;
}
gboolean
tmpl_value_as_boolean (const GValue *value)
{
gboolean ret = FALSE;
if (value != NULL && G_VALUE_TYPE (value) != G_TYPE_INVALID)
{
GValue coerced = G_VALUE_INIT;
g_value_init (&coerced, G_TYPE_BOOLEAN);
if (!g_value_transform (value, &coerced))
{
if (G_VALUE_HOLDS_STRING (value))
ret = g_value_get_string (value) && *g_value_get_string (value);
else if (G_VALUE_HOLDS_DOUBLE (value))
ret = g_value_get_double (value) != 0.0;
else if (G_VALUE_HOLDS_INT (value))
ret = !!g_value_get_int (value);
else if (G_VALUE_HOLDS_UINT (value))
ret = !!g_value_get_uint (value);
else if (G_VALUE_HOLDS_INT64 (value))
ret = !!g_value_get_int64 (value);
else if (G_VALUE_HOLDS_UINT64 (value))
ret = !!g_value_get_uint64 (value);
else if (G_VALUE_HOLDS_LONG (value))
ret = !!g_value_get_long (value);
else if (G_VALUE_HOLDS_ULONG (value))
ret = !!g_value_get_ulong (value);
else if (G_VALUE_HOLDS_FLOAT (value))
ret = g_value_get_float (value) != 0.0;
else if (G_VALUE_HOLDS_BOXED (value))
ret = !!g_value_get_boxed (value);
else if (G_VALUE_HOLDS_OBJECT (value))
ret = !!g_value_get_object (value);
else if (G_VALUE_HOLDS_VARIANT (value))
ret = !!g_value_get_variant (value);
}
else
ret = g_value_get_boolean (&coerced);
}
return ret;
}
GIRepository *
tmpl_repository_get_default (void)
{
static GIRepository *instance;
if (instance == NULL)
#if GLIB_CHECK_VERSION(2, 85, 0)
instance = gi_repository_dup_default ();
#else
instance = gi_repository_new ();
#endif
return instance;
}
0707010000006D000081A400000000000000000000000168C4C09600001388000000000000000000000000000000000000002F00000000template-glib-3.38.0/src/tmpl-version-macros.h/* tmpl-version-macros.h
*
* Copyright (C) 2017 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_VERSION_MACROS_H
#define TMPL_VERSION_MACROS_H
#if !defined(TMPL_GLIB_INSIDE) && !defined(TMPL_GLIB_COMPILATION)
# error "Only <tmpl-glib.h> can be included directly."
#endif
#include <glib.h>
#include "tmpl-version.h"
#ifndef _TMPL_EXTERN
#define _TMPL_EXTERN extern
#endif
#ifdef TMPL_DISABLE_DEPRECATION_WARNINGS
#define TMPL_DEPRECATED _TMPL_EXTERN
#define TMPL_DEPRECATED_FOR(f) _TMPL_EXTERN
#define TMPL_UNAVAILABLE(maj,min) _TMPL_EXTERN
#else
#define TMPL_DEPRECATED G_DEPRECATED _TMPL_EXTERN
#define TMPL_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _TMPL_EXTERN
#define TMPL_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _TMPL_EXTERN
#endif
#define TMPL_VERSION_3_28 (G_ENCODE_VERSION (3, 28))
#define TMPL_VERSION_3_36 (G_ENCODE_VERSION (3, 36))
#if (TMPL_MINOR_VERSION == 99)
# define TMPL_VERSION_CUR_STABLE (G_ENCODE_VERSION (TMPL_MAJOR_VERSION + 1, 0))
#elif (TMPL_MINOR_VERSION % 2)
# define TMPL_VERSION_CUR_STABLE (G_ENCODE_VERSION (TMPL_MAJOR_VERSION, TMPL_MINOR_VERSION + 1))
#else
# define TMPL_VERSION_CUR_STABLE (G_ENCODE_VERSION (TMPL_MAJOR_VERSION, TMPL_MINOR_VERSION))
#endif
#if (TMPL_MINOR_VERSION == 99)
# define TMPL_VERSION_PREV_STABLE (G_ENCODE_VERSION (TMPL_MAJOR_VERSION + 1, 0))
#elif (TMPL_MINOR_VERSION % 2)
# define TMPL_VERSION_PREV_STABLE (G_ENCODE_VERSION (TMPL_MAJOR_VERSION, TMPL_MINOR_VERSION - 1))
#else
# define TMPL_VERSION_PREV_STABLE (G_ENCODE_VERSION (TMPL_MAJOR_VERSION, TMPL_MINOR_VERSION - 2))
#endif
/**
* TMPL_VERSION_MIN_REQUIRED:
*
* A macro that should be defined by the user prior to including
* the tmpl-glib.h header.
*
* The definition should be one of the predefined TMPL version
* macros: %TMPL_VERSION_3_28, ...
*
* This macro defines the lower bound for the Template-GLib API to use.
*
* If a function has been deprecated in a newer version of Template-GLib,
* it is possible to use this symbol to avoid the compiler warnings
* without disabling warning for every deprecated function.
*
* Since: 3.28
*/
#ifndef TMPL_VERSION_MIN_REQUIRED
# define TMPL_VERSION_MIN_REQUIRED (TMPL_VERSION_CUR_STABLE)
#endif
/**
* TMPL_VERSION_MAX_ALLOWED:
*
* A macro that should be defined by the user prior to including
* the tmpl-glib.h header.
* The definition should be one of the predefined Template-GLib version
* macros: %TMPL_VERSION_1_0, %TMPL_VERSION_1_2,...
*
* This macro defines the upper bound for the TMPL API to use.
*
* If a function has been introduced in a newer version of Template-GLib,
* it is possible to use this symbol to get compiler warnings when
* trying to use that function.
*
* Since: 3.28
*/
#ifndef TMPL_VERSION_MAX_ALLOWED
# if TMPL_VERSION_MIN_REQUIRED > TMPL_VERSION_PREV_STABLE
# define TMPL_VERSION_MAX_ALLOWED (TMPL_VERSION_MIN_REQUIRED)
# else
# define TMPL_VERSION_MAX_ALLOWED (TMPL_VERSION_CUR_STABLE)
# endif
#endif
#if TMPL_VERSION_MAX_ALLOWED < TMPL_VERSION_MIN_REQUIRED
#error "TMPL_VERSION_MAX_ALLOWED must be >= TMPL_VERSION_MIN_REQUIRED"
#endif
#if TMPL_VERSION_MIN_REQUIRED < TMPL_VERSION_3_28
#error "TMPL_VERSION_MIN_REQUIRED must be >= TMPL_VERSION_3_28"
#endif
#define TMPL_AVAILABLE_IN_ALL _TMPL_EXTERN
#if TMPL_VERSION_MIN_REQUIRED >= TMPL_VERSION_3_28
# define TMPL_DEPRECATED_IN_3_28 TMPL_DEPRECATED
# define TMPL_DEPRECATED_IN_3_28_FOR(f) TMPL_DEPRECATED_FOR(f)
#else
# define TMPL_DEPRECATED_IN_3_28 _TMPL_EXTERN
# define TMPL_DEPRECATED_IN_3_28_FOR(f) _TMPL_EXTERN
#endif
#if TMPL_VERSION_MAX_ALLOWED < TMPL_VERSION_3_28
# define TMPL_AVAILABLE_IN_3_28 TMPL_UNAVAILABLE(3, 28)
#else
# define TMPL_AVAILABLE_IN_3_28 _TMPL_EXTERN
#endif
#if TMPL_VERSION_MIN_REQUIRED >= TMPL_VERSION_3_36
# define TMPL_DEPRECATED_IN_3_36 TMPL_DEPRECATED
# define TMPL_DEPRECATED_IN_3_36_FOR(f) TMPL_DEPRECATED_FOR(f)
#else
# define TMPL_DEPRECATED_IN_3_36 _TMPL_EXTERN
# define TMPL_DEPRECATED_IN_3_36_FOR(f) _TMPL_EXTERN
#endif
#if TMPL_VERSION_MAX_ALLOWED < TMPL_VERSION_3_36
# define TMPL_AVAILABLE_IN_3_36 TMPL_UNAVAILABLE(3, 36)
#else
# define TMPL_AVAILABLE_IN_3_36 _TMPL_EXTERN
#endif
#endif /* TMPL_VERSION_MACROS_H */
0707010000006E000081A400000000000000000000000168C4C09600000A6F000000000000000000000000000000000000002B00000000template-glib-3.38.0/src/tmpl-version.h.in/* tmpl-version.h.in
*
* Copyright (C) 2015-2017 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TMPL_VERSION_H
#define TMPL_VERSION_H
#if !defined(TMPL_GLIB_INSIDE) && !defined(TMPL_GLIB_COMPILATION)
#error "Only <tmpl-glib.h> can be included directly."
#endif
/**
* TMPL_MAJOR_VERSION:
*
* Template-GLibl major version component (e.g. 1 if %TMPL_VERSION is 1.2.3)
*/
#define TMPL_MAJOR_VERSION (@TMPL_MAJOR_VERSION@)
/**
* TMPL_MINOR_VERSION:
*
* Template-GLibl minor version component (e.g. 2 if %TMPL_VERSION is 1.2.3)
*/
#define TMPL_MINOR_VERSION (@TMPL_MINOR_VERSION@)
/**
* TMPL_MICRO_VERSION:
*
* Template-GLibl micro version component (e.g. 3 if %TMPL_VERSION is 1.2.3)
*/
#define TMPL_MICRO_VERSION (@TMPL_MICRO_VERSION@)
/**
* TMPL_VERSION
*
* Template-GLibl version.
*/
#define TMPL_VERSION (@TMPL_VERSION@)
/**
* TMPL_VERSION_S:
*
* Template-GLib version, encoded as a string, useful for printing and
* concatenation.
*/
#define TMPL_VERSION_S "@TMPL_VERSION@"
#define TMPL_ENCODE_VERSION(major,minor,micro) \
((major) << 24 | (minor) << 16 | (micro) << 8)
/**
* TMPL_VERSION_HEX:
*
* Template-GLib version, encoded as an hexadecimal number, useful for
* integer comparisons.
*/
#define TMPL_VERSION_HEX \
(TMPL_ENCODE_VERSION (TMPL_MAJOR_VERSION, TMPL_MINOR_VERSION, TMPL_MICRO_VERSION))
/**
* TMPL_CHECK_VERSION:
* @major: required major version
* @minor: required minor version
* @micro: required micro version
*
* Compile-time version checking. Evaluates to %TRUE if the version
* of template-glib is greater than the required one.
*/
#define TMPL_CHECK_VERSION(major,minor,micro) \
(TMPL_MAJOR_VERSION > (major) || \
(TMPL_MAJOR_VERSION == (major) && TMPL_MINOR_VERSION > (minor)) || \
(TMPL_MAJOR_VERSION == (major) && TMPL_MINOR_VERSION == (minor) && \
TMPL_MICRO_VERSION >= (micro)))
#endif /* TMPL_VERSION_H */
0707010000006F000081A400000000000000000000000168C4C096000004F0000000000000000000000000000000000000002800000000template-glib-3.38.0/template-glib.doap<?xml version="1.0" encoding="UTF-8"?>
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:gnome="http://api.gnome.org/doap-extensions#"
xmlns="http://usefulinc.com/ns/doap#">
<name>Template-GLib</name>
<shortname>template-glib</shortname>
<shortdesc>A templating library for GLib</shortdesc>
<description>Template-GLib is a templating library for GLib. It includes a simple template format along with integration into GObject-Introspection for properties and methods. It separates the parsing of templates and the expansion of templates for faster expansion. You can also define scope, custom functions, and more with the embedded expression language.</description>
<homepage rdf:resource="https://wiki.gnome.org/Projects/TemplateGlib" />
<download-page rdf:resource="http://download.gnome.org/sources/template-glib/" />
<programming-language>C</programming-language>
<maintainer>
<foaf:Person>
<foaf:name>Christian Hergert</foaf:name>
<foaf:mbox rdf:resource="mailto:chergert@gnome.org" />
<gnome:userid>chergert</gnome:userid>
</foaf:Person>
</maintainer>
</Project>
07070100000070000041ED00000000000000000000000268C4C09600000000000000000000000000000000000000000000001B00000000template-glib-3.38.0/tests07070100000071000081A400000000000000000000000168C4C09600000299000000000000000000000000000000000000002700000000template-glib-3.38.0/tests/meson.buildtest_env = [
'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()),
'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()),
'G_DEBUG=gc-friendly',
'GSETTINGS_BACKEND=memory',
'MALLOC_CHECK_=2',
'NO_AT_BRIDGE=1',
]
testsuite_c_args = [
'-UG_DISABLE_ASSERT',
'-UG_DISABLE_CAST_CHECKS',
]
testsuite_sources = [
['test-expr'],
['test-template'],
]
foreach test: testsuite_sources
test_name = test.get(0)
test_sources = ['@0@.c'.format(test_name)]
test_exe = executable(test_name, test_sources,
c_args: testsuite_c_args,
dependencies: [core_lib_dep],
)
test(test_name, test_exe, env: test_env)
endforeach
07070100000072000081A400000000000000000000000168C4C096000007F5000000000000000000000000000000000000002700000000template-glib-3.38.0/tests/test-expr.c/* test-expr.c
*
* Copyright 2022 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "tmpl-glib.h"
static char *
get_test_file (const char *name)
{
GFile *file;
char *data = NULL;
gsize len = 0;
g_assert_nonnull (g_getenv ("G_TEST_SRCDIR"));
file = g_file_new_build_filename (g_getenv ("G_TEST_SRCDIR"), name, NULL);
g_file_load_contents (file, NULL, &data, &len, NULL, NULL);
g_object_unref (file);
return data;
}
static void
test1 (void)
{
GError *error = NULL;
char *contents = get_test_file ("test1.script");
TmplExpr *expr = tmpl_expr_from_string (contents, &error);
TmplScope *scope = tmpl_scope_new ();
GValue ret = G_VALUE_INIT;
gboolean r;
g_assert_no_error (error);
g_assert_nonnull (expr);
r = tmpl_expr_eval (expr, scope, &ret, &error);
g_assert_no_error (error);
g_assert_true (r);
if (!G_VALUE_HOLDS_DOUBLE (&ret))
g_printerr ("Expected double, got %s\n",
G_VALUE_TYPE_NAME (&ret));
g_assert_true (G_VALUE_HOLDS_DOUBLE (&ret));
g_assert_cmpint (g_value_get_double (&ret), ==, 1234.0);
g_value_unset (&ret);
tmpl_scope_unref (scope);
tmpl_expr_unref (expr);
g_free (contents);
}
int
main (int argc,
char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/Tmpl/Expr/test1", test1);
return g_test_run ();
}
07070100000073000081A400000000000000000000000168C4C0960000009A000000000000000000000000000000000000003400000000template-glib-3.38.0/tests/test-template-test1.tmpl<html>
<head>
<title>
{{title}}
</title>
</head>
<body>
{{if title}}
<h1>{{title}}</h1>
{{else}}
<h1>Untitled</h1>
{{end}}
</body>
</html>
07070100000074000081A400000000000000000000000168C4C09600000066000000000000000000000000000000000000003D00000000template-glib-3.38.0/tests/test-template-test1.tmpl.expected<html>
<head>
<title>
My Title
</title>
</head>
<body>
<h1>My Title</h1>
</body>
</html>
07070100000075000081A400000000000000000000000168C4C096000008B0000000000000000000000000000000000000002B00000000template-glib-3.38.0/tests/test-template.c/* test-template.c
*
* Copyright 2022 Christian Hergert <chergert@redhat.com>
*
* This file is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include <tmpl-glib.h>
static char *
get_file_contents (GFile *file)
{
char *ret = NULL;
gsize len;
if (!g_file_load_contents (file, NULL, &ret, &len, NULL, NULL))
return NULL;
return ret;
}
static GFile *
get_test_file (const char *name)
{
g_assert_nonnull (g_getenv ("G_TEST_SRCDIR"));
return g_file_new_build_filename (g_getenv ("G_TEST_SRCDIR"), name, NULL);
}
static void
test1 (void)
{
GFile *file = get_test_file ("test-template-test1.tmpl");
GFile *expected = get_test_file ("test-template-test1.tmpl.expected");
TmplTemplate *tmpl = NULL;
TmplScope *scope = NULL;
GError *error = NULL;
char *str = NULL;
char *estr = NULL;
gboolean r;
tmpl = tmpl_template_new (NULL);
r = tmpl_template_parse_file (tmpl, file, NULL, &error);
g_assert_no_error (error);
g_assert_true (r);
scope = tmpl_scope_new ();
tmpl_scope_set_string (scope, "title", "My Title");
str = tmpl_template_expand_string (tmpl, scope, &error);
g_assert_no_error (error);
g_assert_nonnull (str);
estr = get_file_contents (expected);
g_assert_cmpstr (str, ==, estr);
g_free (estr);
g_free (str);
tmpl_scope_unref (scope);
g_assert_finalize_object (file);
g_assert_finalize_object (expected);
g_assert_finalize_object (tmpl);
}
gint
main (gint argc,
gchar *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/Tmpl/Template/test1", test1);
return g_test_run ();
}
07070100000076000081A400000000000000000000000168C4C09600000E24000000000000000000000000000000000000002800000000template-glib-3.38.0/tests/test1.scriptrequire GLib
require Gio version "2.0"
assert(true)
assert(true != false)
assert(!false)
assert(TRUE)
assert(TRUE != false)
assert(TRUE == true)
assert(True == true)
assert(False == FALSE)
assert(False == false)
assert(123 == 123)
assert(123 != 124)
assert(123 != -123)
assert(123 == abs(-123))
assert(1 - 10 == -9)
assert(1 / 10 == .1)
abc = "abc"
assert(abc == "abc")
assert(abc != "abc\n")
assert(abc != "def")
# we can't do builtins yet w/ >1 param so this is a
# very bad pow() implementation that works on integers only.
pow = func(a,b) while b > 1 do a = a * a; b = b - 1; a
assert(pow(2,3) == 8)
assert(pow(2,3) == 8) # and here
multiply = func(x,y) x*y
assert(multiply(10, 10) == 100)
assert(multiply(-10, 10) == -100)
nop = func() pass
nop()
def order2(a,b) assert(a==1); assert(b==2); end
order2(1,2)
def order3(a,b,c)
assert(a == 1)
assert(b == 2)
assert(c == 3)
end
order3(1,2,3)
def weird1(a) assert(a==1)
end
# anonymous functions can have a single statement
(func() 123)()
(func(a,b) assert((a==1)&&(b==2)))(1,2)
myfunc = func() 9*3
assert(myfunc() == 27);
# test out construction
group = Gio.SimpleActionGroup.new()
assert(group)
assert(group != null)
assert(typeof(group).is_a(typeof(Gio.ActionGroup)))
assert(typeof(group).is_a(typeof(Gio.ActionMap)))
assert(!typeof(group).is_a(typeof(Gio.Action)))
assert(typeof(group).name() == "GSimpleActionGroup")
t1 = typeof(group)
t2 = typeof(Gio.SimpleActionGroup)
assert(t1)
assert(t2)
assert(t1 == t2)
Nil = null
assert(Nil == null)
assert(null == null)
assert(group != null)
action = Gio.SimpleAction.new("myaction", null)
assert(action != null)
assert(typeof(action) != null)
assert(typeof(action) == typeof(Gio.SimpleAction))
assert(typeof(action) != typeof(Gio.SimpleActionGroup))
assert(typeof(action).is_a(typeof(Gio.Action)))
assert(!typeof(action).is_a(typeof(Gio.ActionMap)))
def count()
mycount+1
end
mycount = 2
assert(count() == 3)
multiline = (1 + \
2 + \
3)
assert(multiline == 6)
# test left associativity
val = true && true || false
assert(val == true)
# if only we had compiler warnings
val = true && false || true
assert(val == true)
# Implicit floor() in GType conversion
assert(double(i32(1234.56)) == 1234)
# Test boolean casts
assert(bool(1) == true)
assert(bool(0) == false)
assert(bool("") == true)
assert(bool(null) == false)
assert(bool(char(0)) == false)
assert(bool(char(1)) == true)
assert(bool(byte(0)) == false)
assert(bool(byte(1)) == true)
assert(bool(i32(0)) == false)
assert(bool(i32(1)) == true)
assert(bool(u32(0)) == false)
assert(bool(u32(1)) == true)
assert(bool(i64(0)) == false)
assert(bool(i64(1)) == true)
assert(bool(u64(0)) == false)
assert(bool(u64(1)) == true)
# FIXME: broken exp priority
a1 = 1 < 3
(a2 = 1) < 3
assert(a1 == a2)
scoped = 1
ret = (true || (scoped = 2))
assert(scoped == 1)
assert(ret == true)
ret = ((scoped = 2) || (scoped = 3))
assert(scoped == 2)
assert(ret == true)
ret = ((scoped = 3) && (scoped = 4))
assert(scoped == 4)
assert(ret == true)
ret = ((scoped = 3) && (scoped = 0))
assert(scoped == 0)
assert(ret == false)
assert(1 == i32(1))
assert(-2 == i32(-2))
assert(1 == u32(1))
assert(2 == abs(-2))
assert(GLib.strjoinv("_", GLib.strsplit("abc", "b", i32(2))) == "a_c")
assert(GLib.strsplit("123", "2", i32(0)) == GLib.strsplit("123", "2", i32(0)))
def m(x,y)
x * y
end
a = 10
if true then a = m(10, 2)
assert(a == 20)
libname = "libfoo"
if GLib.str_has_prefix(libname, "lib") then libname = GLib.utf8_substring(libname, i64(3), i64(-1))
assert(libname == "foo")
aa = 30
if false then aa = 10
assert(aa == 30)
1234;
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!826 blocks