1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/.hgignore Wed Oct 10 22:58:21 2012 +0100
1.3 @@ -0,0 +1,28 @@
1.4 +.*\.o$
1.5 +.*\.lo$
1.6 +.*\.la$
1.7 +.*\.pc$
1.8 +/Makefile$
1.9 +/Makefile.in$
1.10 +^Makefile$
1.11 +^Makefile.in$
1.12 +^src/xexpr$
1.13 +/\.libs/
1.14 +/\.deps/
1.15 +^configure$
1.16 +^config\.
1.17 +^config/
1.18 +^libtool$
1.19 +^gtk-doc\.make$
1.20 +^autom4te\.cache/
1.21 +^aclocal\.m4$
1.22 +^stamp-h1$
1.23 +^m4/
1.24 +^docs/.*\.sgml$
1.25 +^docs/.*\.stamp$
1.26 +^docs/reference/html/
1.27 +^docs/reference/xml/
1.28 +^docs/reference/tmpl/
1.29 +^docs/reference/version.xml
1.30 +^docs/reference/libxexpr-*.txt
1.31 +^docs/reference/libxexpr.*
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/COPYING Wed Oct 10 22:58:21 2012 +0100
2.3 @@ -0,0 +1,515 @@
2.4 +
2.5 + GNU LESSER GENERAL PUBLIC LICENSE
2.6 + Version 2.1, February 1999
2.7 +
2.8 + Copyright (C) 1991, 1999 Free Software Foundation, Inc.
2.9 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2.10 + Everyone is permitted to copy and distribute verbatim copies
2.11 + of this license document, but changing it is not allowed.
2.12 +
2.13 +[This is the first released version of the Lesser GPL. It also counts
2.14 + as the successor of the GNU Library Public License, version 2, hence
2.15 + the version number 2.1.]
2.16 +
2.17 + Preamble
2.18 +
2.19 + The licenses for most software are designed to take away your
2.20 +freedom to share and change it. By contrast, the GNU General Public
2.21 +Licenses are intended to guarantee your freedom to share and change
2.22 +free software--to make sure the software is free for all its users.
2.23 +
2.24 + This license, the Lesser General Public License, applies to some
2.25 +specially designated software packages--typically libraries--of the
2.26 +Free Software Foundation and other authors who decide to use it. You
2.27 +can use it too, but we suggest you first think carefully about whether
2.28 +this license or the ordinary General Public License is the better
2.29 +strategy to use in any particular case, based on the explanations
2.30 +below.
2.31 +
2.32 + When we speak of free software, we are referring to freedom of use,
2.33 +not price. Our General Public Licenses are designed to make sure that
2.34 +you have the freedom to distribute copies of free software (and charge
2.35 +for this service if you wish); that you receive source code or can get
2.36 +it if you want it; that you can change the software and use pieces of
2.37 +it in new free programs; and that you are informed that you can do
2.38 +these things.
2.39 +
2.40 + To protect your rights, we need to make restrictions that forbid
2.41 +distributors to deny you these rights or to ask you to surrender these
2.42 +rights. These restrictions translate to certain responsibilities for
2.43 +you if you distribute copies of the library or if you modify it.
2.44 +
2.45 + For example, if you distribute copies of the library, whether gratis
2.46 +or for a fee, you must give the recipients all the rights that we gave
2.47 +you. You must make sure that they, too, receive or can get the source
2.48 +code. If you link other code with the library, you must provide
2.49 +complete object files to the recipients, so that they can relink them
2.50 +with the library after making changes to the library and recompiling
2.51 +it. And you must show them these terms so they know their rights.
2.52 +
2.53 + We protect your rights with a two-step method: (1) we copyright the
2.54 +library, and (2) we offer you this license, which gives you legal
2.55 +permission to copy, distribute and/or modify the library.
2.56 +
2.57 + To protect each distributor, we want to make it very clear that
2.58 +there is no warranty for the free library. Also, if the library is
2.59 +modified by someone else and passed on, the recipients should know
2.60 +that what they have is not the original version, so that the original
2.61 +author's reputation will not be affected by problems that might be
2.62 +introduced by others.
2.63 +^L
2.64 + Finally, software patents pose a constant threat to the existence of
2.65 +any free program. We wish to make sure that a company cannot
2.66 +effectively restrict the users of a free program by obtaining a
2.67 +restrictive license from a patent holder. Therefore, we insist that
2.68 +any patent license obtained for a version of the library must be
2.69 +consistent with the full freedom of use specified in this license.
2.70 +
2.71 + Most GNU software, including some libraries, is covered by the
2.72 +ordinary GNU General Public License. This license, the GNU Lesser
2.73 +General Public License, applies to certain designated libraries, and
2.74 +is quite different from the ordinary General Public License. We use
2.75 +this license for certain libraries in order to permit linking those
2.76 +libraries into non-free programs.
2.77 +
2.78 + When a program is linked with a library, whether statically or using
2.79 +a shared library, the combination of the two is legally speaking a
2.80 +combined work, a derivative of the original library. The ordinary
2.81 +General Public License therefore permits such linking only if the
2.82 +entire combination fits its criteria of freedom. The Lesser General
2.83 +Public License permits more lax criteria for linking other code with
2.84 +the library.
2.85 +
2.86 + We call this license the "Lesser" General Public License because it
2.87 +does Less to protect the user's freedom than the ordinary General
2.88 +Public License. It also provides other free software developers Less
2.89 +of an advantage over competing non-free programs. These disadvantages
2.90 +are the reason we use the ordinary General Public License for many
2.91 +libraries. However, the Lesser license provides advantages in certain
2.92 +special circumstances.
2.93 +
2.94 + For example, on rare occasions, there may be a special need to
2.95 +encourage the widest possible use of a certain library, so that it
2.96 +becomes
2.97 +a de-facto standard. To achieve this, non-free programs must be
2.98 +allowed to use the library. A more frequent case is that a free
2.99 +library does the same job as widely used non-free libraries. In this
2.100 +case, there is little to gain by limiting the free library to free
2.101 +software only, so we use the Lesser General Public License.
2.102 +
2.103 + In other cases, permission to use a particular library in non-free
2.104 +programs enables a greater number of people to use a large body of
2.105 +free software. For example, permission to use the GNU C Library in
2.106 +non-free programs enables many more people to use the whole GNU
2.107 +operating system, as well as its variant, the GNU/Linux operating
2.108 +system.
2.109 +
2.110 + Although the Lesser General Public License is Less protective of the
2.111 +users' freedom, it does ensure that the user of a program that is
2.112 +linked with the Library has the freedom and the wherewithal to run
2.113 +that program using a modified version of the Library.
2.114 +
2.115 + The precise terms and conditions for copying, distribution and
2.116 +modification follow. Pay close attention to the difference between a
2.117 +"work based on the library" and a "work that uses the library". The
2.118 +former contains code derived from the library, whereas the latter must
2.119 +be combined with the library in order to run.
2.120 +^L
2.121 + GNU LESSER GENERAL PUBLIC LICENSE
2.122 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
2.123 +
2.124 + 0. This License Agreement applies to any software library or other
2.125 +program which contains a notice placed by the copyright holder or
2.126 +other authorized party saying it may be distributed under the terms of
2.127 +this Lesser General Public License (also called "this License").
2.128 +Each licensee is addressed as "you".
2.129 +
2.130 + A "library" means a collection of software functions and/or data
2.131 +prepared so as to be conveniently linked with application programs
2.132 +(which use some of those functions and data) to form executables.
2.133 +
2.134 + The "Library", below, refers to any such software library or work
2.135 +which has been distributed under these terms. A "work based on the
2.136 +Library" means either the Library or any derivative work under
2.137 +copyright law: that is to say, a work containing the Library or a
2.138 +portion of it, either verbatim or with modifications and/or translated
2.139 +straightforwardly into another language. (Hereinafter, translation is
2.140 +included without limitation in the term "modification".)
2.141 +
2.142 + "Source code" for a work means the preferred form of the work for
2.143 +making modifications to it. For a library, complete source code means
2.144 +all the source code for all modules it contains, plus any associated
2.145 +interface definition files, plus the scripts used to control
2.146 +compilation
2.147 +and installation of the library.
2.148 +
2.149 + Activities other than copying, distribution and modification are not
2.150 +covered by this License; they are outside its scope. The act of
2.151 +running a program using the Library is not restricted, and output from
2.152 +such a program is covered only if its contents constitute a work based
2.153 +on the Library (independent of the use of the Library in a tool for
2.154 +writing it). Whether that is true depends on what the Library does
2.155 +and what the program that uses the Library does.
2.156 +
2.157 + 1. You may copy and distribute verbatim copies of the Library's
2.158 +complete source code as you receive it, in any medium, provided that
2.159 +you conspicuously and appropriately publish on each copy an
2.160 +appropriate copyright notice and disclaimer of warranty; keep intact
2.161 +all the notices that refer to this License and to the absence of any
2.162 +warranty; and distribute a copy of this License along with the
2.163 +Library.
2.164 +
2.165 + You may charge a fee for the physical act of transferring a copy,
2.166 +and you may at your option offer warranty protection in exchange for a
2.167 +fee.
2.168 +
2.169 + 2. You may modify your copy or copies of the Library or any portion
2.170 +of it, thus forming a work based on the Library, and copy and
2.171 +distribute such modifications or work under the terms of Section 1
2.172 +above, provided that you also meet all of these conditions:
2.173 +
2.174 + a) The modified work must itself be a software library.
2.175 +
2.176 + b) You must cause the files modified to carry prominent notices
2.177 + stating that you changed the files and the date of any change.
2.178 +
2.179 + c) You must cause the whole of the work to be licensed at no
2.180 + charge to all third parties under the terms of this License.
2.181 +
2.182 + d) If a facility in the modified Library refers to a function or a
2.183 + table of data to be supplied by an application program that uses
2.184 + the facility, other than as an argument passed when the facility
2.185 + is invoked, then you must make a good faith effort to ensure that,
2.186 + in the event an application does not supply such function or
2.187 + table, the facility still operates, and performs whatever part of
2.188 + its purpose remains meaningful.
2.189 +
2.190 + (For example, a function in a library to compute square roots has
2.191 + a purpose that is entirely well-defined independent of the
2.192 + application. Therefore, Subsection 2d requires that any
2.193 + application-supplied function or table used by this function must
2.194 + be optional: if the application does not supply it, the square
2.195 + root function must still compute square roots.)
2.196 +
2.197 +These requirements apply to the modified work as a whole. If
2.198 +identifiable sections of that work are not derived from the Library,
2.199 +and can be reasonably considered independent and separate works in
2.200 +themselves, then this License, and its terms, do not apply to those
2.201 +sections when you distribute them as separate works. But when you
2.202 +distribute the same sections as part of a whole which is a work based
2.203 +on the Library, the distribution of the whole must be on the terms of
2.204 +this License, whose permissions for other licensees extend to the
2.205 +entire whole, and thus to each and every part regardless of who wrote
2.206 +it.
2.207 +
2.208 +Thus, it is not the intent of this section to claim rights or contest
2.209 +your rights to work written entirely by you; rather, the intent is to
2.210 +exercise the right to control the distribution of derivative or
2.211 +collective works based on the Library.
2.212 +
2.213 +In addition, mere aggregation of another work not based on the Library
2.214 +with the Library (or with a work based on the Library) on a volume of
2.215 +a storage or distribution medium does not bring the other work under
2.216 +the scope of this License.
2.217 +
2.218 + 3. You may opt to apply the terms of the ordinary GNU General Public
2.219 +License instead of this License to a given copy of the Library. To do
2.220 +this, you must alter all the notices that refer to this License, so
2.221 +that they refer to the ordinary GNU General Public License, version 2,
2.222 +instead of to this License. (If a newer version than version 2 of the
2.223 +ordinary GNU General Public License has appeared, then you can specify
2.224 +that version instead if you wish.) Do not make any other change in
2.225 +these notices.
2.226 +^L
2.227 + Once this change is made in a given copy, it is irreversible for
2.228 +that copy, so the ordinary GNU General Public License applies to all
2.229 +subsequent copies and derivative works made from that copy.
2.230 +
2.231 + This option is useful when you wish to copy part of the code of
2.232 +the Library into a program that is not a library.
2.233 +
2.234 + 4. You may copy and distribute the Library (or a portion or
2.235 +derivative of it, under Section 2) in object code or executable form
2.236 +under the terms of Sections 1 and 2 above provided that you accompany
2.237 +it with the complete corresponding machine-readable source code, which
2.238 +must be distributed under the terms of Sections 1 and 2 above on a
2.239 +medium customarily used for software interchange.
2.240 +
2.241 + If distribution of object code is made by offering access to copy
2.242 +from a designated place, then offering equivalent access to copy the
2.243 +source code from the same place satisfies the requirement to
2.244 +distribute the source code, even though third parties are not
2.245 +compelled to copy the source along with the object code.
2.246 +
2.247 + 5. A program that contains no derivative of any portion of the
2.248 +Library, but is designed to work with the Library by being compiled or
2.249 +linked with it, is called a "work that uses the Library". Such a
2.250 +work, in isolation, is not a derivative work of the Library, and
2.251 +therefore falls outside the scope of this License.
2.252 +
2.253 + However, linking a "work that uses the Library" with the Library
2.254 +creates an executable that is a derivative of the Library (because it
2.255 +contains portions of the Library), rather than a "work that uses the
2.256 +library". The executable is therefore covered by this License.
2.257 +Section 6 states terms for distribution of such executables.
2.258 +
2.259 + When a "work that uses the Library" uses material from a header file
2.260 +that is part of the Library, the object code for the work may be a
2.261 +derivative work of the Library even though the source code is not.
2.262 +Whether this is true is especially significant if the work can be
2.263 +linked without the Library, or if the work is itself a library. The
2.264 +threshold for this to be true is not precisely defined by law.
2.265 +
2.266 + If such an object file uses only numerical parameters, data
2.267 +structure layouts and accessors, and small macros and small inline
2.268 +functions (ten lines or less in length), then the use of the object
2.269 +file is unrestricted, regardless of whether it is legally a derivative
2.270 +work. (Executables containing this object code plus portions of the
2.271 +Library will still fall under Section 6.)
2.272 +
2.273 + Otherwise, if the work is a derivative of the Library, you may
2.274 +distribute the object code for the work under the terms of Section 6.
2.275 +Any executables containing that work also fall under Section 6,
2.276 +whether or not they are linked directly with the Library itself.
2.277 +^L
2.278 + 6. As an exception to the Sections above, you may also combine or
2.279 +link a "work that uses the Library" with the Library to produce a
2.280 +work containing portions of the Library, and distribute that work
2.281 +under terms of your choice, provided that the terms permit
2.282 +modification of the work for the customer's own use and reverse
2.283 +engineering for debugging such modifications.
2.284 +
2.285 + You must give prominent notice with each copy of the work that the
2.286 +Library is used in it and that the Library and its use are covered by
2.287 +this License. You must supply a copy of this License. If the work
2.288 +during execution displays copyright notices, you must include the
2.289 +copyright notice for the Library among them, as well as a reference
2.290 +directing the user to the copy of this License. Also, you must do one
2.291 +of these things:
2.292 +
2.293 + a) Accompany the work with the complete corresponding
2.294 + machine-readable source code for the Library including whatever
2.295 + changes were used in the work (which must be distributed under
2.296 + Sections 1 and 2 above); and, if the work is an executable linked
2.297 + with the Library, with the complete machine-readable "work that
2.298 + uses the Library", as object code and/or source code, so that the
2.299 + user can modify the Library and then relink to produce a modified
2.300 + executable containing the modified Library. (It is understood
2.301 + that the user who changes the contents of definitions files in the
2.302 + Library will not necessarily be able to recompile the application
2.303 + to use the modified definitions.)
2.304 +
2.305 + b) Use a suitable shared library mechanism for linking with the
2.306 + Library. A suitable mechanism is one that (1) uses at run time a
2.307 + copy of the library already present on the user's computer system,
2.308 + rather than copying library functions into the executable, and (2)
2.309 + will operate properly with a modified version of the library, if
2.310 + the user installs one, as long as the modified version is
2.311 + interface-compatible with the version that the work was made with.
2.312 +
2.313 + c) Accompany the work with a written offer, valid for at
2.314 + least three years, to give the same user the materials
2.315 + specified in Subsection 6a, above, for a charge no more
2.316 + than the cost of performing this distribution.
2.317 +
2.318 + d) If distribution of the work is made by offering access to copy
2.319 + from a designated place, offer equivalent access to copy the above
2.320 + specified materials from the same place.
2.321 +
2.322 + e) Verify that the user has already received a copy of these
2.323 + materials or that you have already sent this user a copy.
2.324 +
2.325 + For an executable, the required form of the "work that uses the
2.326 +Library" must include any data and utility programs needed for
2.327 +reproducing the executable from it. However, as a special exception,
2.328 +the materials to be distributed need not include anything that is
2.329 +normally distributed (in either source or binary form) with the major
2.330 +components (compiler, kernel, and so on) of the operating system on
2.331 +which the executable runs, unless that component itself accompanies
2.332 +the executable.
2.333 +
2.334 + It may happen that this requirement contradicts the license
2.335 +restrictions of other proprietary libraries that do not normally
2.336 +accompany the operating system. Such a contradiction means you cannot
2.337 +use both them and the Library together in an executable that you
2.338 +distribute.
2.339 +^L
2.340 + 7. You may place library facilities that are a work based on the
2.341 +Library side-by-side in a single library together with other library
2.342 +facilities not covered by this License, and distribute such a combined
2.343 +library, provided that the separate distribution of the work based on
2.344 +the Library and of the other library facilities is otherwise
2.345 +permitted, and provided that you do these two things:
2.346 +
2.347 + a) Accompany the combined library with a copy of the same work
2.348 + based on the Library, uncombined with any other library
2.349 + facilities. This must be distributed under the terms of the
2.350 + Sections above.
2.351 +
2.352 + b) Give prominent notice with the combined library of the fact
2.353 + that part of it is a work based on the Library, and explaining
2.354 + where to find the accompanying uncombined form of the same work.
2.355 +
2.356 + 8. You may not copy, modify, sublicense, link with, or distribute
2.357 +the Library except as expressly provided under this License. Any
2.358 +attempt otherwise to copy, modify, sublicense, link with, or
2.359 +distribute the Library is void, and will automatically terminate your
2.360 +rights under this License. However, parties who have received copies,
2.361 +or rights, from you under this License will not have their licenses
2.362 +terminated so long as such parties remain in full compliance.
2.363 +
2.364 + 9. You are not required to accept this License, since you have not
2.365 +signed it. However, nothing else grants you permission to modify or
2.366 +distribute the Library or its derivative works. These actions are
2.367 +prohibited by law if you do not accept this License. Therefore, by
2.368 +modifying or distributing the Library (or any work based on the
2.369 +Library), you indicate your acceptance of this License to do so, and
2.370 +all its terms and conditions for copying, distributing or modifying
2.371 +the Library or works based on it.
2.372 +
2.373 + 10. Each time you redistribute the Library (or any work based on the
2.374 +Library), the recipient automatically receives a license from the
2.375 +original licensor to copy, distribute, link with or modify the Library
2.376 +subject to these terms and conditions. You may not impose any further
2.377 +restrictions on the recipients' exercise of the rights granted herein.
2.378 +You are not responsible for enforcing compliance by third parties with
2.379 +this License.
2.380 +^L
2.381 + 11. If, as a consequence of a court judgment or allegation of patent
2.382 +infringement or for any other reason (not limited to patent issues),
2.383 +conditions are imposed on you (whether by court order, agreement or
2.384 +otherwise) that contradict the conditions of this License, they do not
2.385 +excuse you from the conditions of this License. If you cannot
2.386 +distribute so as to satisfy simultaneously your obligations under this
2.387 +License and any other pertinent obligations, then as a consequence you
2.388 +may not distribute the Library at all. For example, if a patent
2.389 +license would not permit royalty-free redistribution of the Library by
2.390 +all those who receive copies directly or indirectly through you, then
2.391 +the only way you could satisfy both it and this License would be to
2.392 +refrain entirely from distribution of the Library.
2.393 +
2.394 +If any portion of this section is held invalid or unenforceable under
2.395 +any particular circumstance, the balance of the section is intended to
2.396 +apply, and the section as a whole is intended to apply in other
2.397 +circumstances.
2.398 +
2.399 +It is not the purpose of this section to induce you to infringe any
2.400 +patents or other property right claims or to contest validity of any
2.401 +such claims; this section has the sole purpose of protecting the
2.402 +integrity of the free software distribution system which is
2.403 +implemented by public license practices. Many people have made
2.404 +generous contributions to the wide range of software distributed
2.405 +through that system in reliance on consistent application of that
2.406 +system; it is up to the author/donor to decide if he or she is willing
2.407 +to distribute software through any other system and a licensee cannot
2.408 +impose that choice.
2.409 +
2.410 +This section is intended to make thoroughly clear what is believed to
2.411 +be a consequence of the rest of this License.
2.412 +
2.413 + 12. If the distribution and/or use of the Library is restricted in
2.414 +certain countries either by patents or by copyrighted interfaces, the
2.415 +original copyright holder who places the Library under this License
2.416 +may add an explicit geographical distribution limitation excluding those
2.417 +countries, so that distribution is permitted only in or among
2.418 +countries not thus excluded. In such case, this License incorporates
2.419 +the limitation as if written in the body of this License.
2.420 +
2.421 + 13. The Free Software Foundation may publish revised and/or new
2.422 +versions of the Lesser General Public License from time to time.
2.423 +Such new versions will be similar in spirit to the present version,
2.424 +but may differ in detail to address new problems or concerns.
2.425 +
2.426 +Each version is given a distinguishing version number. If the Library
2.427 +specifies a version number of this License which applies to it and
2.428 +"any later version", you have the option of following the terms and
2.429 +conditions either of that version or of any later version published by
2.430 +the Free Software Foundation. If the Library does not specify a
2.431 +license version number, you may choose any version ever published by
2.432 +the Free Software Foundation.
2.433 +^L
2.434 + 14. If you wish to incorporate parts of the Library into other free
2.435 +programs whose distribution conditions are incompatible with these,
2.436 +write to the author to ask for permission. For software which is
2.437 +copyrighted by the Free Software Foundation, write to the Free
2.438 +Software Foundation; we sometimes make exceptions for this. Our
2.439 +decision will be guided by the two goals of preserving the free status
2.440 +of all derivatives of our free software and of promoting the sharing
2.441 +and reuse of software generally.
2.442 +
2.443 + NO WARRANTY
2.444 +
2.445 + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
2.446 +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
2.447 +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
2.448 +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
2.449 +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
2.450 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2.451 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
2.452 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
2.453 +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
2.454 +
2.455 + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
2.456 +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
2.457 +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
2.458 +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
2.459 +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
2.460 +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
2.461 +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
2.462 +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
2.463 +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
2.464 +DAMAGES.
2.465 +
2.466 + END OF TERMS AND CONDITIONS
2.467 +^L
2.468 + How to Apply These Terms to Your New Libraries
2.469 +
2.470 + If you develop a new library, and you want it to be of the greatest
2.471 +possible use to the public, we recommend making it free software that
2.472 +everyone can redistribute and change. You can do so by permitting
2.473 +redistribution under these terms (or, alternatively, under the terms
2.474 +of the ordinary General Public License).
2.475 +
2.476 + To apply these terms, attach the following notices to the library.
2.477 +It is safest to attach them to the start of each source file to most
2.478 +effectively convey the exclusion of warranty; and each file should
2.479 +have at least the "copyright" line and a pointer to where the full
2.480 +notice is found.
2.481 +
2.482 +
2.483 + <one line to give the library's name and a brief idea of what it
2.484 +does.>
2.485 + Copyright (C) <year> <name of author>
2.486 +
2.487 + This library is free software; you can redistribute it and/or
2.488 + modify it under the terms of the GNU Lesser General Public
2.489 + License as published by the Free Software Foundation; either
2.490 + version 2 of the License, or (at your option) any later version.
2.491 +
2.492 + This library is distributed in the hope that it will be useful,
2.493 + but WITHOUT ANY WARRANTY; without even the implied warranty of
2.494 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2.495 + Lesser General Public License for more details.
2.496 +
2.497 + You should have received a copy of the GNU Lesser General Public
2.498 + License along with this library; if not, write to the Free Software
2.499 + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2.500 +
2.501 +Also add information on how to contact you by electronic and paper
2.502 +mail.
2.503 +
2.504 +You should also get your employer (if you work as a programmer) or
2.505 +your
2.506 +school, if any, to sign a "copyright disclaimer" for the library, if
2.507 +necessary. Here is a sample; alter the names:
2.508 +
2.509 + Yoyodyne, Inc., hereby disclaims all copyright interest in the
2.510 + library `Frob' (a library for tweaking knobs) written by James
2.511 +Random Hacker.
2.512 +
2.513 + <signature of Ty Coon>, 1 April 1990
2.514 + Ty Coon, President of Vice
2.515 +
2.516 +That's all there is to it!
2.517 +
2.518 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/Makefile.am Wed Oct 10 22:58:21 2012 +0100
3.3 @@ -0,0 +1,5 @@
3.4 +ACLOCAL_AMFLAGS=-I m4
3.5 +
3.6 +SUBDIRS=libxexpr src test docs/reference
3.7 +
3.8 +DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/bootstrap.sh Wed Oct 10 22:58:21 2012 +0100
4.3 @@ -0,0 +1,9 @@
4.4 +#!/bin/sh
4.5 +set -e
4.6 +mkdir -p config
4.7 +gtkdocize
4.8 +autoheader
4.9 +aclocal
4.10 +libtoolize
4.11 +automake --foreign --add-missing
4.12 +autoconf
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/configure.ac Wed Oct 10 22:58:21 2012 +0100
5.3 @@ -0,0 +1,80 @@
5.4 +# -*- Autoconf -*-
5.5 +# Process this file with autoconf to produce a configure script.
5.6 +
5.7 +AC_INIT([libxexpr],[1.0],[ali@juiblex.co.uk])
5.8 +AC_PREREQ(2.59)
5.9 +AC_CONFIG_MACRO_DIR([m4])
5.10 +AC_CONFIG_AUX_DIR([config])
5.11 +AC_CONFIG_SRCDIR([libxexpr/xexpr.h])
5.12 +AC_CONFIG_HEADER([config.h])
5.13 +AC_CONFIG_FILES([Makefile
5.14 +libxexpr/Makefile
5.15 +libxexpr/libxexpr.pc
5.16 +src/Makefile
5.17 +test/Makefile
5.18 +test/spec/Makefile
5.19 +test/idb/Makefile
5.20 +test/libxexpr/Makefile
5.21 +docs/reference/Makefile
5.22 +docs/reference/version.xml
5.23 +])
5.24 +AM_INIT_AUTOMAKE(no-define)
5.25 +AC_CANONICAL_HOST
5.26 +AC_SUBST(HOST_OS,$host_os)
5.27 +AC_SUBST(HOST_CPU,$host_cpu)
5.28 +
5.29 +# libtool versioning for libxexpr. For a release one of the following
5.30 +# must apply:
5.31 +#
5.32 +# - If interfaces have been changed or added, but binary compatibility has
5.33 +# been preserved, increment CURRENT and AGE and set REVISION to 0.
5.34 +# - If binary compatibility has been broken (eg removed or changed interfaces),
5.35 +# increment CURRENT and set AGE and REVISION to 0.
5.36 +# - If the interface is the same as the previous version, increment REVISION.
5.37 +#
5.38 +lt_current=0
5.39 +lt_revision=0
5.40 +lt_age=0
5.41 +LIBXEXPR_LT_VERSION_INFO="$lt_current:$lt_revision:$lt_age"
5.42 +AC_SUBST(LIBXEXPR_LT_VERSION_INFO)
5.43 +
5.44 +##################################################
5.45 +# Checks for programs.
5.46 +##################################################
5.47 +AC_PROG_CC
5.48 +AC_LIBTOOL_WIN32_DLL
5.49 +AC_PROG_LIBTOOL
5.50 +PKG_PROG_PKG_CONFIG
5.51 +GTK_DOC_CHECK([1.11],[--flavour no-tmpl])
5.52 +
5.53 +##################################################
5.54 +# Checks for header files.
5.55 +##################################################
5.56 +AC_HEADER_STDC
5.57 +
5.58 +##################################################
5.59 +# Checks for typedefs, structures, and compiler characteristics.
5.60 +##################################################
5.61 +
5.62 +##################################################
5.63 +# Checks for libraries.
5.64 +##################################################
5.65 +PKG_CHECK_MODULES(GLIB,[glib-2.0])
5.66 +PKG_CHECK_MODULES(LIBXML,[libxml-2.0])
5.67 +LIBXEXPR_CFLAGS="$LIBXML_CFLAGS $GLIB_CFLAGS"
5.68 +LIBXEXPR_LIBS="$LIBXML_LIBS $GLIB_LIBS"
5.69 +AC_SUBST(LIBXEXPR_CFLAGS)
5.70 +AC_SUBST(LIBXEXPR_LIBS)
5.71 +
5.72 +##################################################
5.73 +# Checks for library functions.
5.74 +##################################################
5.75 +
5.76 +##################################################
5.77 +# Checks for processor independent files.
5.78 +##################################################
5.79 +
5.80 +##################################################
5.81 +# Generate the various configured files
5.82 +##################################################
5.83 +AC_OUTPUT
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/docs/reference/Makefile.am Wed Oct 10 22:58:21 2012 +0100
6.3 @@ -0,0 +1,95 @@
6.4 +## Process this file with automake to produce Makefile.in
6.5 +
6.6 +# We require automake 1.6 at least.
6.7 +AUTOMAKE_OPTIONS=1.6
6.8 +
6.9 +# This is a blank Makefile.am for using gtk-doc.
6.10 +# Copy this to your project's API docs directory and modify the variables to
6.11 +# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
6.12 +# of using the various options.
6.13 +
6.14 +# The name of the module, e.g. 'glib'.
6.15 +DOC_MODULE=libxexpr
6.16 +
6.17 +# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
6.18 +#DOC_MODULE_VERSION=2
6.19 +
6.20 +
6.21 +# The top-level SGML file. You can change this if you want to.
6.22 +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
6.23 +
6.24 +# The directory containing the source code. Relative to $(srcdir).
6.25 +# gtk-doc will search all .c & .h files beneath here for inline comments
6.26 +# documenting the functions and macros.
6.27 +# e.g. DOC_SOURCE_DIR=../../../gtk
6.28 +DOC_SOURCE_DIR=../../libxexpr
6.29 +
6.30 +# Extra options to pass to gtkdoc-scangobj. Not normally needed.
6.31 +SCANGOBJ_OPTIONS=
6.32 +
6.33 +# Extra options to supply to gtkdoc-scan.
6.34 +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
6.35 +SCAN_OPTIONS=--rebuild-types --rebuild-sections
6.36 +
6.37 +# Extra options to supply to gtkdoc-mkdb.
6.38 +# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
6.39 +MKDB_OPTIONS=--sgml-mode --output-format=xml --name-space=xexpr
6.40 +
6.41 +# Extra options to supply to gtkdoc-mktmpl
6.42 +# e.g. MKTMPL_OPTIONS=--only-section-tmpl
6.43 +MKTMPL_OPTIONS=
6.44 +
6.45 +# Extra options to supply to gtkdoc-mkhtml
6.46 +MKHTML_OPTIONS=
6.47 +
6.48 +# Extra options to supply to gtkdoc-fixref. Not normally needed.
6.49 +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
6.50 +FIXXREF_OPTIONS=
6.51 +
6.52 +# Used for dependencies. The docs will be rebuilt if any of these change.
6.53 +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
6.54 +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
6.55 +HFILE_GLOB=$(top_srcdir)/libxexpr/*.h
6.56 +CFILE_GLOB=$(top_srcdir)/libxexpr/*.c
6.57 +
6.58 +# Header files to ignore when scanning.
6.59 +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
6.60 +IGNORE_HFILES=xexpr.h xexprprivate.h
6.61 +
6.62 +# Images to copy into HTML directory.
6.63 +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
6.64 +HTML_IMAGES=
6.65 +
6.66 +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
6.67 +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
6.68 +content_files=version.xml implementation_defined_behaviour.xml \
6.69 + language_extensions.xml xexpr.xml
6.70 +
6.71 +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
6.72 +# These files must be listed here *and* in content_files
6.73 +# e.g. expand_content_files=running.sgml
6.74 +expand_content_files=
6.75 +
6.76 +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
6.77 +# Only needed if you are using gtkdoc-scangobj to dynamically query widget
6.78 +# signals and properties.
6.79 +# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
6.80 +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
6.81 +GTKDOC_CFLAGS=
6.82 +GTKDOC_LIBS=
6.83 +
6.84 +# This includes the standard gtk-doc make rules, copied by gtkdocize.
6.85 +include $(top_srcdir)/gtk-doc.make
6.86 +
6.87 +# Other files to distribute
6.88 +# e.g. EXTRA_DIST += version.xml.in
6.89 +EXTRA_DIST+=version.xml.in
6.90 +
6.91 +# Files not to distribute
6.92 +# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
6.93 +# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
6.94 +DISTCLEANFILES=$(DOC_MODULE).types $(DOC_MODULE)-sections.txt
6.95 +
6.96 +# Comment this out if you want your docs-status tested during 'make check'
6.97 +TESTS_ENVIRONMENT=cd $(srcdir) &&
6.98 +TESTS=$(GTKDOC_CHECK)
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/docs/reference/implementation_defined_behaviour.xml Wed Oct 10 22:58:21 2012 +0100
7.3 @@ -0,0 +1,415 @@
7.4 +<?xml version="1.0"?>
7.5 +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
7.6 + "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
7.7 +[
7.8 +]>
7.9 +<chapter id="implementation-defined-behaviour">
7.10 + <title>Implementation Defined Behaviour</title>
7.11 +
7.12 + <para>
7.13 + The specification of the XEXPR language is laid out in a W3C note of
7.14 + <ulink url="http://www.w3.org/TR/2000/NOTE-xexpr-20001121">21 November
7.15 + 2000</ulink>. However, the specification leaves quite a bit of
7.16 + information to be deduced from the examples and leaves other parts of
7.17 + the language loosly specified. This chapter documents the way that
7.18 + libxexpr implements the language and gives the rationale for each
7.19 + decision taken.
7.20 + </para>
7.21 +
7.22 + <sect1 id="idb-numbers">
7.23 + <title>Numbers</title>
7.24 +
7.25 + <para>
7.26 + Numbers are defined in pseudo-BNF as:
7.27 + <programlisting>
7.28 +number : whitespace sign simple-number whitespace
7.29 + ;
7.30 +
7.31 +whitespace : [ \t\n]*
7.32 + ;
7.33 +
7.34 +sign : [+-]?
7.35 + ;
7.36 +
7.37 +simple-number : 0x[0-9A-Fa-f]+
7.38 + | [0-9]+
7.39 + | [0-9]+\.[0-9]+
7.40 + | [0-9]+\.[0-9]+[eE][+-][0-9]+
7.41 + ;<!--
7.42 + --></programlisting>
7.43 + that is: they have an optional leading sign and may be surrounded with
7.44 + whitespace.
7.45 + </para>
7.46 +
7.47 + <simplesect id="idb-numbers-rationale">
7.48 + <title>Rationale</title>
7.49 +
7.50 + <para>
7.51 + While negative numbers can be created using <subtract> without
7.52 + the need for any signs, this seems overly cumbersome.
7.53 + </para>
7.54 +
7.55 + <para>
7.56 + The examples in the specification make it clear that where two numbers
7.57 + are seperated by a space, this should be parsed as just two numbers
7.58 + and not two numbers plus an interveening string which a strict reading
7.59 + of the specification would imply.
7.60 + </para>
7.61 + </simplesect>
7.62 + </sect1>
7.63 +
7.64 + <sect1 id="idb-bindings">
7.65 + <title>Bindings</title>
7.66 +
7.67 + <para>
7.68 + Bindings are parsed as integers, floats or strings in that order (ie.,
7.69 + the first type that matches will be used). Thus the following pairs
7.70 + of expressions are equivalent:
7.71 + <programlisting>
7.72 +<func x="+01 "/>
7.73 +
7.74 +<func>
7.75 + <define name="x"><integer>1</integer></define>
7.76 +</func>
7.77 +
7.78 +<func x=" 14.0e-1"/>
7.79 +
7.80 +<func>
7.81 + <define name="x"><float>1.4</float></define>
7.82 +</func>
7.83 +
7.84 +<func x="Hello "/>
7.85 +
7.86 +<func>
7.87 + <define name="x"><string>Hello </string></define>
7.88 +</func><!--
7.89 + --></programlisting>
7.90 + </para>
7.91 + <simplesect id="idb-bindings-rationale">
7.92 + <title>Rationale</title>
7.93 +
7.94 + <para>
7.95 + This seems to satisfy the doctrine of least-surpise.
7.96 + </para>
7.97 + </simplesect>
7.98 + </sect1>
7.99 +
7.100 + <sect1 id="idb-pcdata">
7.101 + <title>Parsing of PCDATA</title>
7.102 +
7.103 + <para>
7.104 + When numbers and strings are mixed in PCDATA, any whitespace surrounding
7.105 + the numbers is taken to be part of the numbers rather than the strings.
7.106 + Thus the following two expressions are equivalent:
7.107 + <programlisting>
7.108 +<foo>This is the 0xdeadbeef constant.</foo>
7.109 +
7.110 +<foo>
7.111 + <string>This is the</string>
7.112 + <integer>0xdeadbeef</integer>
7.113 + <string>constant.</string>
7.114 +</foo><!--
7.115 + --></programlisting>
7.116 + </para>
7.117 +
7.118 + <simplesect id="idb-pcdata-rationale">
7.119 + <title>Rationale</title>
7.120 +
7.121 + <para>
7.122 + This seems more consistent with spaces between numbers not being
7.123 + parsed as strings than the alternative.
7.124 + </para>
7.125 + </simplesect>
7.126 + </sect1>
7.127 +
7.128 + <sect1 id="idb-define">
7.129 + <title>The <define> Function</title>
7.130 +
7.131 + <para>
7.132 + The <define> function creates a new function in the environment in
7.133 + which it is invoked. This is different than the <set> function
7.134 + which will modify the definition of an existing function if such exists.
7.135 + Only if no such function is defined in any of the active environments will
7.136 + <set> create a new function (and then in the outermost, or global,
7.137 + environment).
7.138 + </para>
7.139 +
7.140 + <simplesect id="idb-define-rationale">
7.141 + <title>Rationale</title>
7.142 +
7.143 + <para>
7.144 + We know from the examples in the specification (eg., in
7.145 + <ulink url="http://www.w3.org/TR/xexpr/#id-0045">section 45</ulink>)
7.146 + that <subtract> changes the definition of its first argument
7.147 + in at least the grandfather environment. It makes sense that <set>
7.148 + should do the same. When we come to <define>, however, we
7.149 + know from <ulink url="http://www.w3.org/TR/xexpr/#id-0003">section
7.150 + 3</ulink> that it is equivalent to an attribute on the parent element
7.151 + and so it makes sense that it should create a variable in the parent
7.152 + environment.
7.153 + </para>
7.154 + </simplesect>
7.155 + </sect1>
7.156 +
7.157 + <sect1 id="idb-get">
7.158 + <title>The <get> Function</title>
7.159 +
7.160 + <para>
7.161 + The following two expressions are equivalent:
7.162 + <programlisting>
7.163 +<get name="x"/>
7.164 +<get>x</get><!--
7.165 + --></programlisting>
7.166 + The expression <x/> has the same effect except in the case of
7.167 + <add> and <subtract> where these two expressions are
7.168 + different:
7.169 + <programlisting>
7.170 +<add><x/>1</add>
7.171 +<add><get>x</get>1</add><!--
7.172 + --></programlisting>
7.173 + The first changes the definition of <x>, the second does not.
7.174 + </para>
7.175 +
7.176 + <para>
7.177 + Note that IDs are allowed to start with the dot (.) and hyphen (-)
7.178 + characters which are not valid as the first character in XML tags.
7.179 + Thus get must be used in the following:
7.180 + <programlisting>
7.181 +<expr>
7.182 + <define name=".net">4.5.50709</define>
7.183 + <print><get>.net</get></print>
7.184 +</expr><!--
7.185 + --></programlisting>
7.186 + </para>
7.187 +
7.188 + <para>
7.189 + Since <get> returns a function definition (just like
7.190 + <define>), it is possible to define functions of this type that
7.191 + take arguments and even invoke them in a somewhat circuitous manner:
7.192 + <programlisting>
7.193 +<expr>
7.194 + <define name=".product" args="a b c d">
7.195 + <add>
7.196 + <multiply>
7.197 + <a/>
7.198 + <b/>
7.199 + </multiply>
7.200 + <multiply>
7.201 + <c/>
7.202 + <d/>
7.203 + </multiply>
7.204 + </add>
7.205 + </define>
7.206 +
7.207 + <expr>
7.208 + <define name="closure"/>
7.209 + <set name="closure">
7.210 + <get>.product</get>
7.211 + </set>
7.212 + <closure>1 2 3 4</closure>
7.213 + </expr>
7.214 +</expr><!--
7.215 + --></programlisting>
7.216 + </para>
7.217 +
7.218 + <simplesect id="idb-get-rationale">
7.219 + <title>Rationale</title>
7.220 +
7.221 + <para>
7.222 + <ulink url="http://www.w3.org/TR/xexpr/#id-0014">Section 14</ulink>
7.223 + tells us that <get>x</get> and <x/> have the same
7.224 + effect in most cases (and thus presumably not all cases) and it
7.225 + would seem surprising if <get> were not to insulate a
7.226 + function in this manner.
7.227 + </para>
7.228 + </simplesect>
7.229 + </sect1>
7.230 +
7.231 + <sect1 id="idb-arithmetic">
7.232 + <title>Arithmetic Operators</title>
7.233 +
7.234 + <para>
7.235 + The empty arithmetic operators (<add/>, <subtract/>,
7.236 + <multiply/> and <divide/>) all evaluate to <nil/>.
7.237 + </para>
7.238 +
7.239 + <para>
7.240 + The <add> and <subtract> operators change their first
7.241 + argument in some circumstances as in this example from the specification:
7.242 + <programlisting>
7.243 +<while>
7.244 + <gt><x/> 0</gt>
7.245 + <expr>
7.246 + <print newline="true"><x/><print>
7.247 + <subtract><x/> 1</subtract>
7.248 + </expr>
7.249 +</while><!--
7.250 + --></programlisting>
7.251 + </para>
7.252 +
7.253 + <para>
7.254 + In general, the first agument will be modified if it is a function
7.255 + invocation that has no bindings and no arguments. Thus the following
7.256 + will print 9:
7.257 + <programlisting>
7.258 +<define name="x"><multiply>2 3</multiply></define>
7.259 +<add><x/>3</add>
7.260 +<print><x/></print><!--
7.261 + --></programlisting>
7.262 + whereas this will print 6:
7.263 + <programlisting>
7.264 +<define name="x"><multiply>2 3</multiply></define>
7.265 +<add><x unused=""/>3</add>
7.266 +<print><x/></print><!--
7.267 + --></programlisting>
7.268 + </para>
7.269 +
7.270 + <para>
7.271 + Where arguments are modified, this occurs as the arguments are being
7.272 + evaluated. Thus this expression:
7.273 + <programlisting>
7.274 +<add><x/><x/><x/></add><!--
7.275 + --></programlisting>
7.276 + will multiply <x> by 4 rather than by 3.
7.277 + </para>
7.278 +
7.279 + <simplesect id="idb-arithmetic-rationale">
7.280 + <title>Rationale</title>
7.281 +
7.282 + <para>
7.283 + The examples in the specification imply that <add> and
7.284 + <subtract> modify their first argument when it is a
7.285 + variable. The iterative example in
7.286 + <ulink url="http://www.w3.org/TR/xexpr/#id-0008">section 8</ulink>
7.287 + wouldn't work if <multiply> worked the same way (and the
7.288 + definition of <2pi> in <ulink
7.289 + url="http://www.w3.org/TR/xexpr/#id-0007">section 7</ulink> would
7.290 + not be expected to modify the definition of <pi> each time
7.291 + it is called). Note that this example is erroneous: IDs can't contain
7.292 + numbers.
7.293 + </para>
7.294 +
7.295 + <para>
7.296 + It seems undesirable to modify functions that take arguments.
7.297 + Making the decision based on the invocation rather than the
7.298 + function definition makes expressions much easier to read.
7.299 + </para>
7.300 + </simplesect>
7.301 + </sect1>
7.302 +
7.303 + <sect1 id="idb-comparison">
7.304 + <title>Comparison Functions</title>
7.305 +
7.306 + <para>
7.307 + The empty comparison functions (<eq/>, <neq/>, <leq/>,
7.308 + <geq/>, <lt/> and <gt/>) and comparison functions with
7.309 + exactly one argument all evaluate to <true/>.
7.310 + </para>
7.311 +
7.312 + <para>
7.313 + The ordered comparison functions (<leq>, <geq>, <lt>
7.314 + and <gt>) act as if the equivalent mathematical operator was
7.315 + inserted between their arguments. Thus:
7.316 + <programlisting>
7.317 +<lt>
7.318 + 1 2 3
7.319 +</lt><!--
7.320 + --></programlisting>
7.321 + is equivalent to the mathematical expression:
7.322 + <screen>1 < 2 < 3</screen>
7.323 + and:
7.324 + <programlisting>
7.325 +<leq>
7.326 + 1 2 3
7.327 +</leq><!--
7.328 + --></programlisting>
7.329 + is equivalent to the mathematical expression:
7.330 + <screen>1 ≤ 2 ≤ 3</screen>
7.331 + </para>
7.332 +
7.333 + <para>
7.334 + When comparing objects of different types:
7.335 + <itemizedlist>
7.336 + <listitem>
7.337 + Numbers will be implicitly cast between <float> and
7.338 + <integer> where that involves no loss of precision
7.339 + </listitem>
7.340 + <listitem>
7.341 + Strings will be compared byte-by-byte as UTF8 encoded strings
7.342 + </listitem>
7.343 + <listitem>
7.344 + Functions will always be completely evaluated
7.345 + </listitem>
7.346 + <listitem>
7.347 + Invocations of the constant functions are ordered as <false/>
7.348 + < <nil/> < <true/>
7.349 + </listitem>
7.350 + </itemizedlist>
7.351 + </para>
7.352 +
7.353 + <simplesect id="idb-comparison-rationale">
7.354 + <title>Rationale</title>
7.355 +
7.356 + <para>
7.357 + The empty comparison functions equaluate to <true> by analogy
7.358 + with the comparison functions.
7.359 + </para>
7.360 +
7.361 + <para>
7.362 + The ordering of the comparison functions is confused in the
7.363 + specification with the examples for <lt> and <gt> agreeing
7.364 + with libxexpr's behaviour and the examples for <leq> and
7.365 + <geq> doing the opposite. The choice was arbitary.
7.366 + </para>
7.367 + </simplesect>
7.368 + </sect1>
7.369 +
7.370 + <sect1 id="idb-redefining-builtins">
7.371 + <title>Redefining Builtin Functions</title>
7.372 +
7.373 + <para>
7.374 + Attempting to redefine a builtin function results in an error.
7.375 + </para>
7.376 +
7.377 + <simplesect id="idb-redefining-builtins-rationale">
7.378 + <title>Rationale</title>
7.379 +
7.380 + <para>
7.381 + While this could be implemented, there is no mention of it in the
7.382 + specification and it would complicate the implementation with no
7.383 + obvious benefit.
7.384 + </para>
7.385 + </simplesect>
7.386 + </sect1>
7.387 +
7.388 + <sect1 id="idb-namespaces">
7.389 + <title>Namespaces</title>
7.390 +
7.391 + <para>
7.392 + libxexpr considers an element's namespace to be part of its name
7.393 + and thus elements in a namespace other than the XEXPR namespace as
7.394 + are always distinct from functions defined by XEXPR. In addition,
7.395 + functions defined using <define> are defined in the
7.396 + XEXPR namespace.
7.397 + </para>
7.398 +
7.399 + <para>
7.400 + libxexpr provides hooks for extending the XEXPR language by allowing
7.401 + handlers to be installed for other namespaces.
7.402 + </para>
7.403 +
7.404 + <para>
7.405 + Elements which are in no namespace are treated as if they were in the
7.406 + XEXPR namespace.
7.407 + </para>
7.408 +
7.409 + <simplesect id="idb-namespaces-rationale">
7.410 + <title>Rationale</title>
7.411 +
7.412 + <para>
7.413 + Being able to extend the XEXPR language is vital for it to be useful
7.414 + and namespaces are the obvious way to do this.
7.415 + </para>
7.416 + </simplesect>
7.417 + </sect1>
7.418 +</chapter>
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/docs/reference/language_extensions.xml Wed Oct 10 22:58:21 2012 +0100
8.3 @@ -0,0 +1,277 @@
8.4 +<?xml version="1.0"?>
8.5 +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
8.6 + "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
8.7 +[
8.8 +]>
8.9 +<chapter id="language-extensions">
8.10 + <title>Language Extensions</title>
8.11 +
8.12 + <para>
8.13 + These language extensions are provided in the following namespace URI:
8.14 + <screen>
8.15 +http://www.juiblex.co.uk/ns/libxexpr
8.16 + </screen>
8.17 + People using this namespace are encouraged to use the libxexpr namespace
8.18 + prefix.
8.19 + </para>
8.20 +
8.21 + <sect1 id="libxexpr-pi">
8.22 + <title>Function <pi></title>
8.23 +
8.24 + <simplesect>
8.25 + <title>Synopsis</title>
8.26 + <para>
8.27 + <pi> returns the value of π.
8.28 + </para>
8.29 + </simplesect>
8.30 +
8.31 + <simplesect>
8.32 + <title>Arguments</title>
8.33 + <para>
8.34 + <pi> takes no arguments.
8.35 + </para>
8.36 + </simplesect>
8.37 +
8.38 + <simplesect>
8.39 + <title>Return Values</title>
8.40 + <para>
8.41 + <pi> returns the value of π.
8.42 + </para>
8.43 + </simplesect>
8.44 +
8.45 + <example>
8.46 + <programlisting>
8.47 +<libxexpr:pi/> ≅ <float>3.14</float><!--
8.48 + --></programlisting>
8.49 + </example>
8.50 + </sect1>
8.51 +
8.52 + <sect1 id="libxexpr-sin">
8.53 + <title>Function <sin></title>
8.54 +
8.55 + <simplesect>
8.56 + <title>Synopsis</title>
8.57 + <para>
8.58 + <sin> computes the sine function.
8.59 + </para>
8.60 + </simplesect>
8.61 +
8.62 + <simplesect>
8.63 + <title>Arguments</title>
8.64 + <para>
8.65 + <sin> takes one argument: x. If no argument is given, an error
8.66 + occurs.
8.67 + </para>
8.68 + </simplesect>
8.69 +
8.70 + <simplesect>
8.71 + <title>Return Values</title>
8.72 + <para>
8.73 + <sin> returns the sine of its argument, given in radians.
8.74 + If the argument does not evaluate to a finite number,
8.75 + <sin> returns an indeterminate result.
8.76 + </para>
8.77 + </simplesect>
8.78 +
8.79 + <example>
8.80 + <programlisting>
8.81 +<libxexpr:sin>
8.82 + <divide>
8.83 + <libxexpr:pi/>
8.84 + 2
8.85 + </divide>
8.86 +</libxexpr:sin> --> <float>1</float><!--
8.87 + --></programlisting>
8.88 + </example>
8.89 + </sect1>
8.90 +
8.91 + <sect1 id="libxexpr-atan">
8.92 + <title>Function <atan></title>
8.93 +
8.94 + <simplesect>
8.95 + <title>Synopsis</title>
8.96 + <para>
8.97 + <atan> computes the arc tangent function.
8.98 + </para>
8.99 + </simplesect>
8.100 +
8.101 + <simplesect>
8.102 + <title>Arguments</title>
8.103 + <para>
8.104 + <atan> takes two arguments: x and y. The y argument defaults to
8.105 + 1. If the x argument is missing, an error occurs.
8.106 + </para>
8.107 + </simplesect>
8.108 +
8.109 + <simplesect>
8.110 + <title>Return Values</title>
8.111 + <para>
8.112 + <atan> returns the principal value of the arc tangent of its
8.113 + argument(s) in radians. If either argument is indeterminate,
8.114 + the result is also indeterminate.
8.115 + </para>
8.116 +
8.117 + <para>
8.118 + If two arguments are given, <atan> returns the arc tangent of
8.119 + y/x, using the signs of the two arguments to determine the quadrant
8.120 + of the result which will be in the range [-π, π]. If both arguments
8.121 + are 0, the result will also be 0.
8.122 + </para>
8.123 +
8.124 + <para>
8.125 + If only one argument is given, <atan> returns the arc tangent of
8.126 + its argument. The result will be in the range [-π/2, π/2].
8.127 + </para>
8.128 + </simplesect>
8.129 +
8.130 + <example>
8.131 + <programlisting>
8.132 +<libxexpr:atan>1 0</libxexpr:atan> --> <float>0</float><!--
8.133 + --></programlisting>
8.134 + </example>
8.135 + </sect1>
8.136 +
8.137 + <sect1 id="libxexpr-exp">
8.138 + <title>Function <exp></title>
8.139 +
8.140 + <simplesect>
8.141 + <title>Synopsis</title>
8.142 + <para>
8.143 + <exp> computes the base-e exponential function.
8.144 + </para>
8.145 + </simplesect>
8.146 +
8.147 + <simplesect>
8.148 + <title>Arguments</title>
8.149 + <para>
8.150 + <exp> takes zero or one argument: x.
8.151 + </para>
8.152 + </simplesect>
8.153 +
8.154 + <simplesect>
8.155 + <title>Return Values</title>
8.156 + <para>
8.157 + <exp> returns the value of e (the base of natural logarithms)
8.158 + raised to the power of its argument (or just e if no argument is
8.159 + supplied). If the argument does not evaluate to a finite number,
8.160 + <exp> returns an indeterminate result.
8.161 + </para>
8.162 + </simplesect>
8.163 +
8.164 + <example>
8.165 + <programlisting>
8.166 +<libxexpr:exp>2</libxexpr:exp> ≅ <float>7.389</float><!--
8.167 + --></programlisting>
8.168 + </example>
8.169 + </sect1>
8.170 +
8.171 + <sect1 id="libxexpr-log">
8.172 + <title>Function <log></title>
8.173 +
8.174 + <simplesect>
8.175 + <title>Synopsis</title>
8.176 + <para>
8.177 + <log> computes the natural logarithmic function.
8.178 + </para>
8.179 + </simplesect>
8.180 +
8.181 + <simplesect>
8.182 + <title>Arguments</title>
8.183 + <para>
8.184 + <log> takes one argument: x. If no argument is given, an error
8.185 + occurs.
8.186 + </para>
8.187 + </simplesect>
8.188 +
8.189 + <simplesect>
8.190 + <title>Return Values</title>
8.191 + <para>
8.192 + <log> returns the natural logarithm of its argument.
8.193 + If the argument does not evaluate to a positive finite number,
8.194 + <log> returns an indeterminate result.
8.195 + </para>
8.196 + </simplesect>
8.197 +
8.198 + <example>
8.199 + <programlisting>
8.200 +<libxexpr:log>
8.201 + <libxexpr:exp>2</libxexpr:exp>
8.202 +</libxexpr:log> --> <float>2</float><!--
8.203 + --></programlisting>
8.204 + </example>
8.205 + </sect1>
8.206 +
8.207 + <sect1 id="libxexpr-pow">
8.208 + <title>Function <pow></title>
8.209 +
8.210 + <simplesect>
8.211 + <title>Synopsis</title>
8.212 + <para>
8.213 + <pow> computes the value of its first argument raised to the
8.214 + power of its second argument.
8.215 + </para>
8.216 + </simplesect>
8.217 +
8.218 + <simplesect>
8.219 + <title>Arguments</title>
8.220 + <para>
8.221 + <pow> takes two arguments: x and y. If fewer arguments are
8.222 + given, an error occurs.
8.223 + </para>
8.224 + </simplesect>
8.225 +
8.226 + <simplesect>
8.227 + <title>Return Values</title>
8.228 + <para>
8.229 + <pow> returns the value of x (its first argument) raised to the
8.230 + power of y (its second argument).
8.231 + </para>
8.232 +
8.233 + <para>
8.234 + If x is a finite value less than 0, and y is a finite non-integer,
8.235 + <pow> returns an indeterminate result.
8.236 + </para>
8.237 +
8.238 + <para>
8.239 + If the result overflows, <pow> returns an indeterminate result.
8.240 + </para>
8.241 +
8.242 + <para>
8.243 + If result underflows, and is not representable, 0 is returned.
8.244 + </para>
8.245 +
8.246 + <para>
8.247 + Except as specified below, if either argument is indeterminate,
8.248 + the result is also indeterminate.
8.249 + </para>
8.250 +
8.251 + <para>
8.252 + If x is 1, the result is 1 (even if y is indeterminate).
8.253 + </para>
8.254 +
8.255 + <para>
8.256 + If y is 0, the result is 1 (even if x is indeterminate).
8.257 + </para>
8.258 +
8.259 + <para>
8.260 + If x is 0, and y is an odd integer greater than 0, the result is 0.
8.261 + </para>
8.262 +
8.263 + <para>
8.264 + If x is 0, and y greater than 0 and not an odd integer, the result
8.265 + is 0.
8.266 + </para>
8.267 +
8.268 + <para>
8.269 + If x is 0, and y is less than 0,
8.270 + <pow> returns an indeterminate result.
8.271 + </para>
8.272 + </simplesect>
8.273 +
8.274 + <example>
8.275 + <programlisting>
8.276 + <libxexpr:pow>10 2</libxexpr:pow> --> <float>100</float><!--
8.277 + --></programlisting>
8.278 + </example>
8.279 + </sect1>
8.280 +</chapter>
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/docs/reference/libxexpr-docs.xml Wed Oct 10 22:58:21 2012 +0100
9.3 @@ -0,0 +1,41 @@
9.4 +<?xml version="1.0"?>
9.5 +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
9.6 + "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
9.7 +[
9.8 + <!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
9.9 + <!ENTITY version SYSTEM "version.xml">
9.10 +]>
9.11 +<book id="index">
9.12 + <bookinfo>
9.13 + <title>libxexpr Reference Manual</title>
9.14 + <releaseinfo>
9.15 + for libxexpr &version;
9.16 + The latest version of this documentation can be found on-line at
9.17 + <ulink role="online-location" url="http://www.juiblex.co.uk/libxexpr/docs/reference/index.html">http://www.juiblex.co.uk/libxexpr/docs/reference/</ulink>.
9.18 + </releaseinfo>
9.19 + </bookinfo>
9.20 +
9.21 + <chapter>
9.22 + <title>Tools</title>
9.23 + <xi:include href="xexpr.xml"/>
9.24 + </chapter>
9.25 +
9.26 + <chapter>
9.27 + <title>API Reference</title>
9.28 + <xi:include href="xml/xexprtypes.xml"/>
9.29 + <xi:include href="xml/xexpreval.xml"/>
9.30 + <xi:include href="xml/xexprparse.xml"/>
9.31 + <xi:include href="xml/xexprdump.xml"/>
9.32 + </chapter>
9.33 +
9.34 + <xi:include href="implementation_defined_behaviour.xml"/>
9.35 +
9.36 + <xi:include href="language_extensions.xml"/>
9.37 +
9.38 + <index id="api-index-full">
9.39 + <title>API Index</title>
9.40 + <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
9.41 + </index>
9.42 +
9.43 + <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
9.44 +</book>
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/docs/reference/version.xml.in Wed Oct 10 22:58:21 2012 +0100
10.3 @@ -0,0 +1,1 @@
10.4 +@VERSION@
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/docs/reference/xexpr.xml Wed Oct 10 22:58:21 2012 +0100
11.3 @@ -0,0 +1,97 @@
11.4 +<refentry id="xexpr">
11.5 +
11.6 +<refmeta>
11.7 +<refentrytitle>xexpr</refentrytitle>
11.8 +<manvolnum>1</manvolnum>
11.9 +<refmiscinfo class="manual">User Commands</refmiscinfo>
11.10 +</refmeta>
11.11 +
11.12 +<refnamediv>
11.13 +<refname>xexpr</refname>
11.14 +<refpurpose>XEXPR Interpreter</refpurpose>
11.15 +</refnamediv>
11.16 +
11.17 +<refsynopsisdiv>
11.18 +<cmdsynopsis>
11.19 +<command>xexpr</command>
11.20 +<arg choice="opt" rep="repeat">OPTION</arg>
11.21 +<arg>script</arg>
11.22 +</cmdsynopsis>
11.23 +</refsynopsisdiv>
11.24 +
11.25 +<refsect1><title>Description</title>
11.26 +<para><command>xexpr</command> is an XEXPR interpreter. It loads and executes
11.27 +XEXPR programs.
11.28 +</para>
11.29 +</refsect1>
11.30 +
11.31 +<refsect1><title>Options</title>
11.32 +<variablelist>
11.33 +
11.34 +<varlistentry>
11.35 +<term><option>-h</option>, <option>--help</option></term>
11.36 +<listitem><para>
11.37 +print help and exit
11.38 +</para></listitem>
11.39 +</varlistentry>
11.40 +
11.41 +<varlistentry>
11.42 +<term><option>-d</option>, <option>--dump-tree</option></term>
11.43 +<listitem><para>
11.44 +Instead of executing the XEXPR program, dump the parsed tree after loading
11.45 +</para></listitem>
11.46 +</varlistentry>
11.47 +
11.48 +<varlistentry>
11.49 +<term><option>-D</option>, <option>--dump-result</option></term>
11.50 +<listitem><para>
11.51 +After executing the XEXPR program, dump the result
11.52 +</para></listitem>
11.53 +</varlistentry>
11.54 +
11.55 +<varlistentry>
11.56 +<term><option>-t</option>, <option>--test-result</option></term>
11.57 +<listitem><para>
11.58 +After executing the XEXPR program, test the result and exit 0 if it evaluates
11.59 +to <true/> and non-zero if it evaluates to <false/>
11.60 +</para></listitem>
11.61 +</varlistentry>
11.62 +
11.63 +<varlistentry>
11.64 +<term><option>-T=<replaceable>id</replaceable></option>, <option>--trace <replaceable>id</replaceable></option></term>
11.65 +<listitem><para>
11.66 +Adds <replaceable>id</replaceable> to the set of symbols to trace.
11.67 +
11.68 +When variables with the name of a traced symbol are created or changed,
11.69 +<command>xexpr</command> will output a suitable tracing message and a stack
11.70 +dump
11.71 +</para></listitem>
11.72 +</varlistentry>
11.73 +
11.74 +<varlistentry>
11.75 +<term><option>--xinclude</option></term>
11.76 +<listitem><para>
11.77 +Do XInclude processing
11.78 +</para></listitem>
11.79 +</varlistentry>
11.80 +
11.81 +<varlistentry>
11.82 +<term><option>--param <replaceable>name</replaceable>,<replaceable>number</replaceable></option></term>
11.83 +<listitem><para>
11.84 +Set a global XEXPR variable of the given <replaceable>name</replaceable> with a
11.85 +numeric value of <replaceable>number</replaceable>. A float or integer type
11.86 +will be selected automatically.
11.87 +</para></listitem>
11.88 +</varlistentry>
11.89 +
11.90 +<varlistentry>
11.91 +<term><option>--stringparam <replaceable>name</replaceable>,<replaceable>value</replaceable></option></term>
11.92 +<listitem><para>
11.93 +Set a global XEXPR variable of the given <replaceable>name</replaceable> with a
11.94 +string value of <replaceable>value</replaceable>.
11.95 +</para></listitem>
11.96 +</varlistentry>
11.97 +
11.98 +</variablelist>
11.99 +</refsect1>
11.100 +</refentry>
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/libxexpr/Makefile.am Wed Oct 10 22:58:21 2012 +0100
12.3 @@ -0,0 +1,14 @@
12.4 +AM_CFLAGS=-g $(LIBXEXPR_CFLAGS)
12.5 +LIBS=$(LIBXEXPR_LIBS)
12.6 +INCLUDES=-I$(top_srcdir)
12.7 +AM_LDFLAGS=-no-undefined -version-info $(LIBXEXPR_LT_VERSION_INFO)
12.8 +
12.9 +pkginclude_HEADERS=xexprdump.h xexpreval.h xexprparse.h xexprtypes.h \
12.10 + xexpr.h
12.11 +
12.12 +lib_LTLIBRARIES=libxexpr.la
12.13 +libxexpr_la_SOURCES=xexprdump.c xexpreval.c xexprparse.c xexprtypes.c \
12.14 + extension.c xexprprivate.h $(pkginclude_HEADERS)
12.15 +
12.16 +pkgconfigdir=$(libdir)/pkgconfig
12.17 +pkgconfig_DATA=libxexpr.pc
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/libxexpr/extension.c Wed Oct 10 22:58:21 2012 +0100
13.3 @@ -0,0 +1,209 @@
13.4 +#include <stdlib.h>
13.5 +#include <string.h>
13.6 +#include <math.h>
13.7 +#include <xexpr.h>
13.8 +#include "xexprprivate.h"
13.9 +
13.10 +static XexprConstant *xexpr_do_pi(Xexpr *xexpr,GSList *bindings,GSList *args,
13.11 + GError **err)
13.12 +{
13.13 + return xexpr_new_number(M_PI);
13.14 +}
13.15 +
13.16 +static XexprConstant *xexpr_do_sin(Xexpr *xexpr,GSList *bindings,GSList *args,
13.17 + GError **err)
13.18 +{
13.19 + XexprConstant *x;
13.20 + x=xexpr_bindings_get(bindings,"x");
13.21 + if (!x)
13.22 + {
13.23 + if (args)
13.24 + {
13.25 + x=args->data;
13.26 + args=args->next;
13.27 + }
13.28 + else
13.29 + {
13.30 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
13.31 + "Missing \"x\" argument to \"libxexpr:sin\"");
13.32 + return NULL;
13.33 + }
13.34 + }
13.35 + if (!xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
13.36 + return xexpr_new_number(0.0/0.0);
13.37 + if (!isfinite(x->u.number))
13.38 + return xexpr_new_number(0.0/0.0);
13.39 + else
13.40 + return xexpr_new_number(sin(x->u.number));
13.41 +}
13.42 +
13.43 +static XexprConstant *xexpr_do_atan(Xexpr *xexpr,GSList *bindings,GSList *args,
13.44 + GError **err)
13.45 +{
13.46 + XexprConstant *x,*y;
13.47 + x=xexpr_bindings_get(bindings,"x");
13.48 + if (!x)
13.49 + {
13.50 + if (args)
13.51 + {
13.52 + x=args->data;
13.53 + args=args->next;
13.54 + }
13.55 + else
13.56 + {
13.57 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
13.58 + "Missing \"x\" argument to \"libxexpr:atan\"");
13.59 + return NULL;
13.60 + }
13.61 + }
13.62 + if (!xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
13.63 + return xexpr_new_number(0.0/0.0);
13.64 + y=xexpr_bindings_get(bindings,"y");
13.65 + if (!y && args)
13.66 + {
13.67 + y=args->data;
13.68 + args=args->next;
13.69 + }
13.70 + if (y && !xexpr_constant_cast(y,XEXPR_TYPE_NUMBER))
13.71 + return xexpr_new_number(0.0/0.0);
13.72 + if (!isfinite(x->u.number) || y && !isfinite(y->u.number))
13.73 + return xexpr_new_number(0.0/0.0);
13.74 + else if (y)
13.75 + return xexpr_new_number(atan2(y->u.number,x->u.number));
13.76 + else
13.77 + return xexpr_new_number(atan(x->u.number));
13.78 +}
13.79 +
13.80 +static XexprConstant *xexpr_do_exp(Xexpr *xexpr,GSList *bindings,GSList *args,
13.81 + GError **err)
13.82 +{
13.83 + XexprConstant *x;
13.84 + x=xexpr_bindings_get(bindings,"x");
13.85 + if (!x && args)
13.86 + {
13.87 + x=args->data;
13.88 + args=args->next;
13.89 + }
13.90 + if (x && !xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
13.91 + return xexpr_new_number(0.0/0.0);
13.92 + if (x && !isfinite(x->u.number))
13.93 + return xexpr_new_number(0.0/0.0);
13.94 + else
13.95 + return xexpr_new_number(x?exp(x->u.number):exp(1.0));
13.96 +}
13.97 +
13.98 +static XexprConstant *xexpr_do_log(Xexpr *xexpr,GSList *bindings,GSList *args,
13.99 + GError **err)
13.100 +{
13.101 + XexprConstant *x;
13.102 + x=xexpr_bindings_get(bindings,"x");
13.103 + if (!x)
13.104 + {
13.105 + if (args)
13.106 + {
13.107 + x=args->data;
13.108 + args=args->next;
13.109 + }
13.110 + else
13.111 + {
13.112 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
13.113 + "Missing \"x\" argument to \"libxexpr:log\"");
13.114 + return NULL;
13.115 + }
13.116 + }
13.117 + if (!xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
13.118 + return xexpr_new_number(0.0/0.0);
13.119 + if (!isfinite(x->u.number))
13.120 + return xexpr_new_number(0.0/0.0);
13.121 + else
13.122 + return xexpr_new_number(log(x->u.number));
13.123 +}
13.124 +
13.125 +static XexprConstant *xexpr_do_pow(Xexpr *xexpr,GSList *bindings,GSList *args,
13.126 + GError **err)
13.127 +{
13.128 + XexprConstant *x,*y;
13.129 + x=xexpr_bindings_get(bindings,"x");
13.130 + if (!x)
13.131 + {
13.132 + if (args)
13.133 + {
13.134 + x=args->data;
13.135 + args=args->next;
13.136 + }
13.137 + else
13.138 + {
13.139 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
13.140 + "Missing \"x\" argument to \"libxexpr:atan\"");
13.141 + return NULL;
13.142 + }
13.143 + }
13.144 + if (!xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
13.145 + return xexpr_new_number(0.0/0.0);
13.146 + y=xexpr_bindings_get(bindings,"y");
13.147 + if (!y)
13.148 + {
13.149 + if (args)
13.150 + {
13.151 + y=args->data;
13.152 + args=args->next;
13.153 + }
13.154 + else
13.155 + {
13.156 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
13.157 + "Missing \"y\" argument to \"libxexpr:pow\"");
13.158 + return NULL;
13.159 + }
13.160 + }
13.161 + if (!xexpr_constant_cast(y,XEXPR_TYPE_NUMBER))
13.162 + return xexpr_new_number(0.0/0.0);
13.163 + if (x->u.number==1 || y->u.number==0)
13.164 + return xexpr_new_number(1.0);
13.165 + else if (!isfinite(x->u.number) || !isfinite(y->u.number))
13.166 + return xexpr_new_number(0.0/0.0);
13.167 + else
13.168 + return xexpr_new_number(pow(x->u.number,y->u.number));
13.169 +}
13.170 +
13.171 +static struct libxexpr_function {
13.172 + char *id;
13.173 + XexprConstant *(*func)(Xexpr *xexpr,GSList *bindings,GSList *args,
13.174 + GError **err);
13.175 +} libxexpr_functions[]={
13.176 + { "pi", xexpr_do_pi },
13.177 + { "sin", xexpr_do_sin },
13.178 + { "atan", xexpr_do_atan },
13.179 + { "exp", xexpr_do_exp },
13.180 + { "log", xexpr_do_log },
13.181 + { "pow", xexpr_do_pow },
13.182 +};
13.183 +
13.184 +XexprConstant *_xexpr_libxexpr_function_evaluate(Xexpr *xexpr,const char *ns,
13.185 + const char *id,GSList *bindings,GSList *args,GError **err)
13.186 +{
13.187 + int func;
13.188 + XexprConstant *value,*result;
13.189 + GSList *evaluated_args=NULL;
13.190 + for(func=0;func<G_N_ELEMENTS(libxexpr_functions);func++)
13.191 + if (!strcmp(libxexpr_functions[func].id,id))
13.192 + break;
13.193 + if (func==G_N_ELEMENTS(libxexpr_functions))
13.194 + {
13.195 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
13.196 + "Undefined function: \"libxexpr:%s\"",id);
13.197 + return NULL;
13.198 + }
13.199 + while(args)
13.200 + {
13.201 + value=xexpr_constant_evaluate(xexpr,args->data,err);
13.202 + if (!value)
13.203 + return NULL;
13.204 + evaluated_args=g_slist_prepend(evaluated_args,value);
13.205 + args=args->next;
13.206 + }
13.207 + evaluated_args=g_slist_reverse(evaluated_args);
13.208 + result=libxexpr_functions[func].func(xexpr,bindings,evaluated_args,err);
13.209 + g_slist_foreach(evaluated_args,(GFunc)xexpr_constant_free,NULL);
13.210 + g_slist_free(evaluated_args);
13.211 + return result;
13.212 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/libxexpr/libxexpr.pc.in Wed Oct 10 22:58:21 2012 +0100
14.3 @@ -0,0 +1,11 @@
14.4 +prefix=@prefix@
14.5 +exec_prefix=@exec_prefix@
14.6 +libdir=@libdir@
14.7 +includedir=@includedir@
14.8 +
14.9 +Name: libxexpr
14.10 +Description: An implementation of XEXPR - http://www.w3.org/TR/xexpr
14.11 +Version: @VERSION@
14.12 +Requires: libxml-2.0 glib-2.0
14.13 +Libs: -L${libdir} -lxexpr
14.14 +Cflags: -I${includedir}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/libxexpr/xexpr.h Wed Oct 10 22:58:21 2012 +0100
15.3 @@ -0,0 +1,11 @@
15.4 +#ifndef __XEXPER_H__
15.5 +#define __XEXPER_H__
15.6 +
15.7 +#define XEXPR_NS "http://www.ebt.com/xexpr"
15.8 +#define LIBXEXPR_NS "http://www.juiblex.co.uk/ns/libxexpr"
15.9 +
15.10 +#include <libxexpr/xexprparse.h>
15.11 +#include <libxexpr/xexpreval.h>
15.12 +#include <libxexpr/xexprdump.h>
15.13 +
15.14 +#endif /* __XEXPER_H__ */
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/libxexpr/xexprdump.c Wed Oct 10 22:58:21 2012 +0100
16.3 @@ -0,0 +1,299 @@
16.4 +#include <stdlib.h>
16.5 +#include <string.h>
16.6 +#include <math.h>
16.7 +#include <xexpr.h>
16.8 +
16.9 +/**
16.10 + * SECTION:xexprdump
16.11 + * @short_description: Functions to dump XEXPR objects
16.12 + * @stability: Stable
16.13 + * @include: libxexpr/xexpr.h
16.14 + *
16.15 + * A set of functions to dump
16.16 + * <ulink url="http://www.w3.org/TR/2000/NOTE-xexpr-20001121">XEXPR</ulink>
16.17 + * objects.
16.18 + */
16.19 +
16.20 +static void xexpr_attribute_dump_string(XexprConstant *constant,GString *str)
16.21 +{
16.22 + const char *s;
16.23 + gunichar c;
16.24 + switch(constant->type)
16.25 + {
16.26 + default:
16.27 + return xexpr_constant_dump_string(constant,str);
16.28 + break;
16.29 + case XEXPR_TYPE_STRING:
16.30 + if (strchr(constant->u.string,'"'))
16.31 + {
16.32 + if (strchr(constant->u.string,'\''))
16.33 + {
16.34 + g_string_append_c(str,'"');
16.35 + for(s=constant->u.string;s;s=g_utf8_next_char(s))
16.36 + {
16.37 + c=g_utf8_get_char(s);
16.38 + if (c=='"')
16.39 + g_string_append_c(str,'\\');
16.40 + g_string_append_unichar(str,c);
16.41 + }
16.42 + g_string_append_c(str,'"');
16.43 + }
16.44 + else
16.45 + {
16.46 + g_string_append_c(str,'\'');
16.47 + g_string_append(str,constant->u.string);
16.48 + g_string_append_c(str,'\'');
16.49 + }
16.50 + }
16.51 + else
16.52 + {
16.53 + g_string_append_c(str,'"');
16.54 + g_string_append(str,constant->u.string);
16.55 + g_string_append_c(str,'"');
16.56 + }
16.57 + break;
16.58 + case XEXPR_TYPE_INTEGER:
16.59 + g_string_append_printf(str,"\"%lld\"",constant->u.integer);
16.60 + break;
16.61 + case XEXPR_TYPE_NUMBER:
16.62 + g_string_append_printf(str,"\"%lg\"",constant->u.number);
16.63 + break;
16.64 + }
16.65 +}
16.66 +
16.67 +/**
16.68 + * xexpr_constant_dump_string:
16.69 + * @constant: an #XexprConstant to dump
16.70 + * @str: the string to dump to
16.71 + *
16.72 + * Dumps @constant to the given @str in XML format. For invocation, string
16.73 + * and numeric types, XEXPR itself is used as the dump format (with explicit
16.74 + * type tags). Function definitions cannot be expressed in XEXPR (which
16.75 + * requires that functions be given a name), so we get as close as we can
16.76 + * and use a <define> element without the required name attribute.
16.77 + */
16.78 +void xexpr_constant_dump_string(XexprConstant *constant,GString *str)
16.79 +{
16.80 + int i;
16.81 + gchar *s;
16.82 + XexprBinding *binding;
16.83 + GSList *lnk;
16.84 + GQuark prefix;
16.85 + switch(constant->type)
16.86 + {
16.87 + case XEXPR_TYPE_FUNCTION:
16.88 + g_string_append(str,"<define");
16.89 + if (constant->u.function->args)
16.90 + {
16.91 + g_string_append(str," args=\"");
16.92 + for(lnk=constant->u.function->args;lnk;lnk=lnk->next)
16.93 + {
16.94 + g_string_append(str,lnk->data);
16.95 + if (lnk->next)
16.96 + g_string_append_c(str,' ');
16.97 + }
16.98 + g_string_append_c(str,'"');
16.99 + }
16.100 + g_string_append_c(str,'>');
16.101 + for(lnk=constant->u.function->constants;lnk;lnk=lnk->next)
16.102 + xexpr_constant_dump_string(lnk->data,str);
16.103 + g_string_append(str,"</define>");
16.104 + break;
16.105 + case XEXPR_TYPE_INVOCATION:
16.106 + g_string_append_c(str,'<');
16.107 + if (!constant->u.invocation->ns)
16.108 + prefix=0;
16.109 + else if (!strcmp(constant->u.invocation->ns,LIBXEXPR_NS))
16.110 + prefix=g_quark_from_static_string("libxexpr");
16.111 + else
16.112 + {
16.113 + for(i=0;;i++)
16.114 + {
16.115 + s=g_strdup_printf("x%d",i);
16.116 + if (!g_quark_try_string(s))
16.117 + {
16.118 + prefix=g_quark_from_string(s);
16.119 + g_free(s);
16.120 + break;
16.121 + }
16.122 + g_free(s);
16.123 + }
16.124 + }
16.125 + if (prefix)
16.126 + {
16.127 + g_string_append(str,g_quark_to_string(prefix));
16.128 + g_string_append_c(str,':');
16.129 + }
16.130 + g_string_append(str,constant->u.invocation->function);
16.131 + if (prefix && prefix!=g_quark_from_static_string("libxexpr"))
16.132 + {
16.133 + g_string_append(str," xmlns:");
16.134 + g_string_append(str,g_quark_to_string(prefix));
16.135 + g_string_append(str,"=\"");
16.136 + g_string_append(str,constant->u.invocation->ns);
16.137 + g_string_append_c(str,'"');
16.138 + }
16.139 + for(lnk=constant->u.invocation->bindings;lnk;lnk=lnk->next)
16.140 + {
16.141 + binding=lnk->data;
16.142 + g_string_append_c(str,' ');
16.143 + g_string_append(str,binding->id);
16.144 + g_string_append_c(str,'=');
16.145 + xexpr_attribute_dump_string(binding->value,str);
16.146 + }
16.147 + if (constant->u.invocation->constants)
16.148 + {
16.149 + g_string_append_c(str,'>');
16.150 + xexpr_constants_dump_string(constant->u.invocation->constants,
16.151 + str);
16.152 + g_string_append(str,"</");
16.153 + if (prefix)
16.154 + {
16.155 + g_string_append(str,g_quark_to_string(prefix));
16.156 + g_string_append_c(str,':');
16.157 + }
16.158 + g_string_append(str,constant->u.invocation->function);
16.159 + g_string_append_c(str,'>');
16.160 + }
16.161 + else
16.162 + g_string_append(str,"/>");
16.163 + break;
16.164 + case XEXPR_TYPE_STRING:
16.165 + g_string_append(str,"<string>");
16.166 + g_string_append(str,constant->u.string);
16.167 + g_string_append(str,"</string>");
16.168 + break;
16.169 + case XEXPR_TYPE_INTEGER:
16.170 + g_string_append_printf(str,"<integer>%lld</integer>",
16.171 + constant->u.integer);
16.172 + break;
16.173 + case XEXPR_TYPE_NUMBER:
16.174 + g_string_append_printf(str,"<float>%lg</float>",constant->u.number);
16.175 + break;
16.176 + }
16.177 +}
16.178 +
16.179 +/**
16.180 + * xexpr_constants_dump_string:
16.181 + * @constants: (transfer none) (element-type XexprConstant): a list of
16.182 + * #XexprConstant constants to dump
16.183 + * @str: the string to dump to
16.184 + *
16.185 + * Dumps @constants to the given @str in XML format one after the other,
16.186 + * thus forming an XML fragment.
16.187 + *
16.188 + * See xexpr_constant_dump_string() for details of the XML format used.
16.189 + */
16.190 +void xexpr_constants_dump_string(GSList *constants,GString *str)
16.191 +{
16.192 + XexprConstant *constant;
16.193 + GSList *lnk;
16.194 + for(lnk=constants;lnk;lnk=lnk->next)
16.195 + {
16.196 + constant=lnk->data;
16.197 + xexpr_constant_dump_string(constant,str);
16.198 + }
16.199 +}
16.200 +
16.201 +/**
16.202 + * xexpr_dump_string:
16.203 + * @xexpr: an #Xexpr to dump
16.204 + * @str: the string to dump to
16.205 + *
16.206 + * Dumps @xexpr to the given @str in XML format. If @xexpr contains multiple
16.207 + * constants, this will result in an XML fragment.
16.208 + *
16.209 + * See xexpr_constant_dump_string() for details of the XML format used.
16.210 + */
16.211 +void xexpr_dump_string(Xexpr *xexpr,GString *str)
16.212 +{
16.213 + xexpr_constants_dump_string(xexpr->constants,str);
16.214 +}
16.215 +
16.216 +/**
16.217 + * xexpr_constant_dump:
16.218 + * @constant: an #XexprConstant to dump
16.219 + * @fp: the <type>FILE</type> to dump to
16.220 + *
16.221 + * Dumps @constant to the given @fp in XML format.
16.222 + *
16.223 + * See xexpr_constant_dump_string() for details of the XML format used.
16.224 + */
16.225 +void xexpr_constant_dump(XexprConstant *constant,FILE *fp)
16.226 +{
16.227 + GString *str=g_string_new(NULL);
16.228 + xexpr_constant_dump_string(constant,str);
16.229 + fputs(str->str,fp);
16.230 + g_string_free(str,TRUE);
16.231 +}
16.232 +
16.233 +/**
16.234 + * xexpr_constants_dump:
16.235 + * @constants: (transfer none) (element-type XexprConstant): a list of
16.236 + * #XexprConstant constants to dump
16.237 + * @fp: the <type>FILE</type> to dump to
16.238 + *
16.239 + * Dumps @constants to the given @fp in XML format one after the other,
16.240 + * thus forming an XML fragment.
16.241 + *
16.242 + * See xexpr_constant_dump_string() for details of the XML format used.
16.243 + */
16.244 +void xexpr_constants_dump(GSList *constants,FILE *fp)
16.245 +{
16.246 + GString *str=g_string_new(NULL);
16.247 + xexpr_constants_dump_string(constants,str);
16.248 + fputs(str->str,fp);
16.249 + g_string_free(str,TRUE);
16.250 +}
16.251 +
16.252 +/**
16.253 + * xexpr_dump:
16.254 + * @xexpr: an #Xexpr to dump
16.255 + * @fp: the <type>FILE</type> to dump to
16.256 + *
16.257 + * Dumps @xexpr to the given @fp in XML format. If @xexpr contains multiple
16.258 + * constants, this will result in an XML fragment.
16.259 + *
16.260 + * See xexpr_constant_dump_string() for details of the XML format used.
16.261 + */
16.262 +void xexpr_dump(Xexpr *xexpr,FILE *fp)
16.263 +{
16.264 + xexpr_constants_dump(xexpr->constants,fp);
16.265 +}
16.266 +
16.267 +/**
16.268 + * xexpr_stack_dump:
16.269 + * @xexpr: an #Xexpr whose stack you wish to dump
16.270 + * @fp: the <type>FILE</type> to dump to
16.271 + *
16.272 + * Dumps the current stack of @xexpr to the given @fp in human readable format.
16.273 + * The environments of the various invoked functions will be given in order
16.274 + * starting with the innermost (\#0). For each environment, the variables
16.275 + * defined there will be given along with their current values. Global
16.276 + * variables are contained in the outermost environment.
16.277 + */
16.278 +void xexpr_stack_dump(Xexpr *xexpr,FILE *fp)
16.279 +{
16.280 + int i;
16.281 + GSList *lnk;
16.282 + XexprBinding *binding;
16.283 + XexprEnvironment *environment=xexpr_get_environment(xexpr);
16.284 + for(i=0;environment;environment=environment->outer,i++)
16.285 + {
16.286 + fprintf(fp,"#%-2d ",i);
16.287 + if (environment->function)
16.288 + fprintf(fp,"%s",environment->function);
16.289 + else
16.290 + fprintf(fp,"%p",environment);
16.291 + fprintf(fp," (");
16.292 + for(lnk=environment->bindings;lnk;lnk=lnk->next)
16.293 + {
16.294 + binding=lnk->data;
16.295 + fprintf(fp,"%s = ",binding->id);
16.296 + xexpr_constant_dump(binding->value,fp);
16.297 + if (lnk->next)
16.298 + fprintf(fp,", ");
16.299 + }
16.300 + fprintf(fp,")\n");
16.301 + }
16.302 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/libxexpr/xexprdump.h Wed Oct 10 22:58:21 2012 +0100
17.3 @@ -0,0 +1,19 @@
17.4 +#ifndef __XEXPER_DUMP_H__
17.5 +#define __XEXPER_DUMP_H__
17.6 +
17.7 +#include <stdio.h>
17.8 +#include "xexprtypes.h"
17.9 +
17.10 +G_BEGIN_DECLS
17.11 +
17.12 +void xexpr_constant_dump_string(XexprConstant *constant,GString *str);
17.13 +void xexpr_constants_dump_string(GSList *constants,GString *str);
17.14 +void xexpr_dump_string(Xexpr *xexpr,GString *str);
17.15 +void xexpr_constant_dump(XexprConstant *constant,FILE *fp);
17.16 +void xexpr_constants_dump(GSList *constants,FILE *fp);
17.17 +void xexpr_dump(Xexpr *xexpr,FILE *fp);
17.18 +void xexpr_stack_dump(Xexpr *xexpr,FILE *fp);
17.19 +
17.20 +G_END_DECLS
17.21 +
17.22 +#endif /* __XEXPER_DUMP_H__ */
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/libxexpr/xexpreval.c Wed Oct 10 22:58:21 2012 +0100
18.3 @@ -0,0 +1,1621 @@
18.4 +#include <stdlib.h>
18.5 +#include <string.h>
18.6 +#include <math.h>
18.7 +#include <xexpr.h>
18.8 +#include "xexprprivate.h"
18.9 +
18.10 +/**
18.11 + * SECTION:xexpreval
18.12 + * @short_description: An evaluator for the XEXPR language
18.13 + * @stability: Stable
18.14 + * @include: libxexpr/xexpr.h
18.15 + *
18.16 + * An evaluator for the
18.17 + * <ulink url="http://www.w3.org/TR/2000/NOTE-xexpr-20001121">XEXPR</ulink>
18.18 + * language.
18.19 + */
18.20 +
18.21 +GSList *xexpr_extensions=NULL;
18.22 +
18.23 +static XexprExtension libxexpr_extension={
18.24 + LIBXEXPR_NS,_xexpr_libxexpr_function_evaluate
18.25 +};
18.26 +
18.27 +static XexprConstant *xexpr_do_string(Xexpr *xexpr,GSList *bindings,
18.28 + GSList *args,GError **err);
18.29 +static gboolean xexpr_defineable_id(const char *id,GError **err);
18.30 +
18.31 +/**
18.32 + * xexpr_eval_error_quark:
18.33 + *
18.34 + * Registers an error quark for the libxexpr evaluator if necessary.
18.35 + *
18.36 + * Return value: The error quark used for libxexpr evaluator errors.
18.37 + */
18.38 +GQuark xexpr_eval_error_quark(void)
18.39 +{
18.40 + static GQuark quark;
18.41 + if (!quark)
18.42 + quark=g_quark_from_static_string("xexpr_eval_error");
18.43 + return quark;
18.44 +}
18.45 +
18.46 +/**
18.47 + * xexpr_register_extension:
18.48 + * @extension: (transfer none): an #XexprExtension
18.49 + *
18.50 + * Registers an extension to handle the evaluation of functions and retrieval
18.51 + * of variables in a new namespace.
18.52 + *
18.53 + * Return value: %TRUE if the extension was successfully registered
18.54 + */
18.55 +gboolean xexpr_register_extension(XexprExtension *extension)
18.56 +{
18.57 + GSList *lnk;
18.58 + XexprExtension *ext;
18.59 + static GStaticMutex mutex=G_STATIC_MUTEX_INIT;
18.60 + g_static_mutex_lock(&mutex);
18.61 + if (!xexpr_extensions)
18.62 + xexpr_extensions=g_slist_prepend(xexpr_extensions,&libxexpr_extension);
18.63 + if (!extension || !extension->ns || !*extension->ns ||
18.64 + !strcmp(extension->ns,XEXPR_NS))
18.65 + {
18.66 + g_static_mutex_unlock(&mutex);
18.67 + return FALSE;
18.68 + }
18.69 + for(lnk=xexpr_extensions;lnk;lnk=lnk->next)
18.70 + {
18.71 + ext=lnk->data;
18.72 + if (!strcmp(ext->ns,extension->ns))
18.73 + {
18.74 + g_static_mutex_unlock(&mutex);
18.75 + return FALSE;
18.76 + }
18.77 + }
18.78 + extension=g_memdup(extension,sizeof(*extension));
18.79 + extension->ns=g_strdup(extension->ns);
18.80 + xexpr_extensions=g_slist_prepend(xexpr_extensions,extension);
18.81 + g_static_mutex_unlock(&mutex);
18.82 + return TRUE;
18.83 +}
18.84 +
18.85 +/*
18.86 + * Returned constant should be freed iff evaluate is TRUE
18.87 + */
18.88 +static XexprConstant *xexpr_get_argument(Xexpr *xexpr,GSList *bindings,
18.89 + GSList **args,const char *func,const char *id,gboolean evaluate,GError **err)
18.90 +{
18.91 + XexprConstant *arg;
18.92 + arg=xexpr_bindings_get(bindings,id);
18.93 + if (!arg)
18.94 + {
18.95 + if (*args)
18.96 + {
18.97 + arg=(*args)->data;
18.98 + *args=(*args)->next;
18.99 + }
18.100 + else
18.101 + {
18.102 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.103 + "Missing \"%s\" argument to \"%s\"",id,func);
18.104 + return NULL;
18.105 + }
18.106 + }
18.107 + if (arg && evaluate)
18.108 + arg=xexpr_constant_evaluate(xexpr,arg,err);
18.109 + return arg;
18.110 +}
18.111 +
18.112 +static XexprConstant *xexpr_do_define(Xexpr *xexpr,GSList *bindings,
18.113 + GSList *args,GError **err)
18.114 +{
18.115 + int i;
18.116 + gchar **vector=NULL;
18.117 + GSList *parameters=NULL;
18.118 + XexprConstant *name,*params,*value,*arg;
18.119 + XexprEnvironment *frame;
18.120 + name=xexpr_get_argument(xexpr,bindings,&args,"define","name",TRUE,err);
18.121 + if (!name)
18.122 + return NULL;
18.123 + if (name->type!=XEXPR_TYPE_STRING)
18.124 + {
18.125 + args=g_slist_prepend(NULL,name);
18.126 + arg=xexpr_do_string(xexpr,NULL,args,NULL);
18.127 + g_slist_free(args);
18.128 + if (arg)
18.129 + {
18.130 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.131 + "Attempt to define a function with a non-string name \"%s\"",
18.132 + arg->u.string);
18.133 + xexpr_constant_free(arg);
18.134 + }
18.135 + else
18.136 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.137 + "Attempt to define a function with a non-string name");
18.138 + xexpr_constant_free(name);
18.139 + return NULL;
18.140 + }
18.141 + else if (!_xexpr_validate_id(name->u.string,err) ||
18.142 + !xexpr_defineable_id(name->u.string,err))
18.143 + {
18.144 + xexpr_constant_free(name);
18.145 + return NULL;
18.146 + }
18.147 + params=xexpr_bindings_get(bindings,"args");
18.148 + if (params)
18.149 + {
18.150 + params=xexpr_constant_evaluate(xexpr,params,err);
18.151 + if (params->type!=XEXPR_TYPE_STRING)
18.152 + {
18.153 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.154 + "Attempt to define a function with non-string argument names");
18.155 + xexpr_constant_free(params);
18.156 + xexpr_constant_free(name);
18.157 + return NULL;
18.158 + }
18.159 + vector=g_strsplit_set(params->u.string," \t\n\r",-1);
18.160 + for(i=0;vector[i];i++)
18.161 + {
18.162 + if (vector[i][0]>='0' && vector[i][0]<='9' ||
18.163 + (vector[i][0]=='+' || vector[i][0]=='-') &&
18.164 + vector[i][1]>='0' && vector[i][1]<='9')
18.165 + {
18.166 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.167 + "Attempt to define a function with non-string argument names");
18.168 + xexpr_constant_free(params);
18.169 + xexpr_constant_free(name);
18.170 + g_strfreev(vector);
18.171 + g_slist_free(parameters);
18.172 + return NULL;
18.173 + }
18.174 + parameters=g_slist_prepend(parameters,vector[i]);
18.175 + }
18.176 + parameters=g_slist_reverse(parameters);
18.177 + }
18.178 + value=xexpr_new_function(parameters,args);
18.179 + g_slist_free(parameters);
18.180 + if (vector)
18.181 + g_strfreev(vector);
18.182 + frame=xexpr->environment;
18.183 + xexpr->environment=frame->outer;
18.184 + xexpr_var_new(xexpr,name->u.string,value);
18.185 + xexpr->environment=frame;
18.186 + xexpr_constant_free(name);
18.187 + return value;
18.188 +}
18.189 +
18.190 +static XexprConstant *xexpr_do_print(Xexpr *xexpr,GSList *bindings,GSList *args,
18.191 + GError **err)
18.192 +{
18.193 + gboolean newline=FALSE;
18.194 + GSList *lnk;
18.195 + XexprConstant *arg;
18.196 + arg=xexpr_bindings_get(bindings,"newline");
18.197 + if (arg && arg->type==XEXPR_TYPE_STRING && !strcmp(arg->u.string,"true"))
18.198 + newline=TRUE;
18.199 + for(lnk=args;lnk;lnk=lnk->next)
18.200 + {
18.201 + arg=lnk->data;
18.202 + switch(arg->type)
18.203 + {
18.204 + case XEXPR_TYPE_FUNCTION:
18.205 + /*
18.206 + * http://www.w3.org/TR/xexpr/#id-0003 implies that
18.207 + * function objects are ignored in <print>.
18.208 + */
18.209 + break;
18.210 + case XEXPR_TYPE_INVOCATION:
18.211 + printf("<%s/>",arg->u.invocation->function);
18.212 + break;
18.213 + case XEXPR_TYPE_STRING:
18.214 + fputs(arg->u.string,stdout);
18.215 + break;
18.216 + case XEXPR_TYPE_INTEGER:
18.217 + printf("%lld",arg->u.integer);
18.218 + break;
18.219 + case XEXPR_TYPE_NUMBER:
18.220 + printf("%lg",arg->u.number);
18.221 + break;
18.222 + }
18.223 + }
18.224 + if (newline)
18.225 + putchar('\n');
18.226 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.227 +}
18.228 +
18.229 +static XexprConstant *xexpr_do_println(Xexpr *xexpr,GSList *bindings,
18.230 + GSList *args,GError **err)
18.231 +{
18.232 + putchar('\n');
18.233 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.234 +}
18.235 +
18.236 +static XexprConstant *xexpr_do_get(Xexpr *xexpr,GSList *bindings,
18.237 + GSList *args,GError **err)
18.238 +{
18.239 + XexprConstant *name,*value;
18.240 + name=xexpr_get_argument(xexpr,bindings,&args,"get","name",FALSE,err);
18.241 + if (!name)
18.242 + return NULL;
18.243 + if (name->type==XEXPR_TYPE_STRING)
18.244 + value=xexpr_var_get(xexpr,name->u.string);
18.245 + else
18.246 + value=NULL;
18.247 + if (value)
18.248 + value=xexpr_constant_dup(value);
18.249 + else
18.250 + value=xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.251 + return value;
18.252 +}
18.253 +
18.254 +static XexprConstant *xexpr_do_set(Xexpr *xexpr,GSList *bindings,
18.255 + GSList *args,GError **err)
18.256 +{
18.257 + XexprConstant *name,*value;
18.258 + name=xexpr_get_argument(xexpr,bindings,&args,"set","name",FALSE,err);
18.259 + if (!name)
18.260 + return NULL;
18.261 + if (name->type!=XEXPR_TYPE_STRING)
18.262 + {
18.263 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.264 + "Attempt to bind a value a non-string name");
18.265 + xexpr_constant_free(name);
18.266 + return NULL;
18.267 + }
18.268 + else if (!_xexpr_validate_id(name->u.string,err) ||
18.269 + !xexpr_defineable_id(name->u.string,err))
18.270 + {
18.271 + xexpr_constant_free(name);
18.272 + return NULL;
18.273 + }
18.274 + value=xexpr_get_argument(xexpr,bindings,&args,"set","value",FALSE,err);
18.275 + if (!value)
18.276 + return NULL;
18.277 + xexpr_var_set(xexpr,name->u.string,value);
18.278 + return xexpr_constant_dup(value);
18.279 +}
18.280 +
18.281 +static XexprConstant *xexpr_do_expr(Xexpr *xexpr,GSList *bindings,GSList *args,
18.282 + GError **err)
18.283 +{
18.284 + if (!args)
18.285 + return xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.286 + while(args->next)
18.287 + args=args->next;
18.288 + return xexpr_constant_dup(args->data);
18.289 +}
18.290 +
18.291 +static XexprConstant *xexpr_do_return(Xexpr *xexpr,GSList *bindings,
18.292 + GSList *args,GError **err)
18.293 +{
18.294 + XexprConstant *retval;
18.295 + if (!args)
18.296 + retval=xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.297 + while(args->next)
18.298 + args=args->next;
18.299 + retval=xexpr_constant_dup(args->data);
18.300 + return xexpr_new_invocation_take_ownership(NULL,g_strdup("return"),NULL,
18.301 + g_slist_prepend(NULL,retval));
18.302 +}
18.303 +
18.304 +static XexprConstant *xexpr_do_string(Xexpr *xexpr,GSList *bindings,
18.305 + GSList *args,GError **err)
18.306 +{
18.307 + XexprConstant *arg;
18.308 + GString *str=g_string_new(NULL);
18.309 + while(args)
18.310 + {
18.311 + arg=args->data;
18.312 + switch(arg->type)
18.313 + {
18.314 + case XEXPR_TYPE_FUNCTION:
18.315 + g_warn_if_reached();
18.316 + break;
18.317 + case XEXPR_TYPE_INVOCATION:
18.318 + g_string_append_printf(str,"<%s/>",arg->u.invocation->function);
18.319 + break;
18.320 + case XEXPR_TYPE_STRING:
18.321 + g_string_append(str,arg->u.string);
18.322 + break;
18.323 + case XEXPR_TYPE_INTEGER:
18.324 + g_string_append_printf(str,"%lld",arg->u.integer);
18.325 + break;
18.326 + case XEXPR_TYPE_NUMBER:
18.327 + g_string_append_printf(str,"%lg",arg->u.number);
18.328 + break;
18.329 + }
18.330 + args=args->next;
18.331 + }
18.332 + return xexpr_new_string_take_ownership(g_string_free(str,FALSE));
18.333 +}
18.334 +
18.335 +static XexprConstant *xexpr_do_integer(Xexpr *xexpr,GSList *bindings,
18.336 + GSList *args,GError **err)
18.337 +{
18.338 + XexprConstant *arg;
18.339 + double d;
18.340 + long long int value=0;
18.341 + while(args)
18.342 + {
18.343 + arg=args->data;
18.344 + switch(arg->type)
18.345 + {
18.346 + case XEXPR_TYPE_FUNCTION:
18.347 + g_warn_if_reached();
18.348 + break;
18.349 + case XEXPR_TYPE_INVOCATION:
18.350 + g_warn_if_reached();
18.351 + break;
18.352 + case XEXPR_TYPE_STRING:
18.353 + value=g_ascii_strtoll(arg->u.string,NULL,0);
18.354 + if (value==LLONG_MIN || value==LLONG_MAX)
18.355 + {
18.356 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.357 + "Integer overflow on %s",arg->u.string);
18.358 + return NULL;
18.359 + }
18.360 + break;
18.361 + case XEXPR_TYPE_INTEGER:
18.362 + value=arg->u.integer;
18.363 + break;
18.364 + case XEXPR_TYPE_NUMBER:
18.365 + if (!isfinite(arg->u.number))
18.366 + {
18.367 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.368 + "%lg is not finite",arg->u.number);
18.369 + return NULL;
18.370 + }
18.371 + d=nearbyint(arg->u.number);
18.372 + if (d<=LLONG_MIN || d>=LLONG_MAX)
18.373 + {
18.374 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.375 + "Integer overflow on %lg",arg->u.number);
18.376 + return NULL;
18.377 + }
18.378 + value=(long long int)d;
18.379 + break;
18.380 + }
18.381 + args=args->next;
18.382 + }
18.383 + return xexpr_new_integer(value);
18.384 +}
18.385 +
18.386 +static XexprConstant *xexpr_do_float(Xexpr *xexpr,GSList *bindings,
18.387 + GSList *args,GError **err)
18.388 +{
18.389 + XexprConstant *arg;
18.390 + double value=0.0/0.0;
18.391 + while(args)
18.392 + {
18.393 + arg=args->data;
18.394 + switch(arg->type)
18.395 + {
18.396 + case XEXPR_TYPE_FUNCTION:
18.397 + g_warn_if_reached();
18.398 + break;
18.399 + case XEXPR_TYPE_INVOCATION:
18.400 + g_warn_if_reached();
18.401 + break;
18.402 + case XEXPR_TYPE_STRING:
18.403 + value=g_ascii_strtod(arg->u.string,NULL);
18.404 + if (value==HUGE_VAL || value==-HUGE_VAL)
18.405 + {
18.406 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.407 + "Numeric overflow on %s",arg->u.string);
18.408 + return NULL;
18.409 + }
18.410 + break;
18.411 + case XEXPR_TYPE_INTEGER:
18.412 + if (arg->u.integer<-DBL_MAX || arg->u.integer>DBL_MAX)
18.413 + {
18.414 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.415 + "Numeric overflow on %lld",arg->u.integer);
18.416 + return NULL;
18.417 + }
18.418 + value=(double)arg->u.integer;
18.419 + break;
18.420 + case XEXPR_TYPE_NUMBER:
18.421 + value=arg->u.number;
18.422 + break;
18.423 + }
18.424 + args=args->next;
18.425 + }
18.426 + return xexpr_new_number(value);
18.427 +}
18.428 +
18.429 +static XexprConstant *xexpr_do_true(Xexpr *xexpr,GSList *bindings,GSList *args,
18.430 + GError **err)
18.431 +{
18.432 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.433 +}
18.434 +
18.435 +static XexprConstant *xexpr_do_false(Xexpr *xexpr,GSList *bindings,GSList *args,
18.436 + GError **err)
18.437 +{
18.438 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.439 +}
18.440 +
18.441 +static XexprConstant *xexpr_do_nil(Xexpr *xexpr,GSList *bindings,GSList *args,
18.442 + GError **err)
18.443 +{
18.444 + return xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.445 +}
18.446 +
18.447 +typedef struct xexpr_accumulator {
18.448 + gboolean first;
18.449 + Xexpr *xexpr;
18.450 + GSList *args;
18.451 + const char *result_binding;
18.452 + XexprConstant *arg,*result;
18.453 +} XexprAccumulator;
18.454 +
18.455 +static gboolean xexpr_accumulator_init(XexprAccumulator *accumulator,
18.456 + Xexpr *xexpr,GSList *args,gboolean bind_result,GError **err)
18.457 +{
18.458 + XexprConstant *arg;
18.459 + accumulator->xexpr=xexpr;
18.460 + accumulator->args=args;
18.461 + accumulator->arg=NULL;
18.462 + accumulator->first=TRUE;
18.463 + if (!accumulator->args)
18.464 + {
18.465 + accumulator->result_binding=NULL;
18.466 + accumulator->result=xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.467 + return TRUE;
18.468 + }
18.469 + arg=accumulator->args->data;
18.470 + /*
18.471 + * If arg invokes a function with no bindings and no arguments
18.472 + * then the result is accumulated in the function itself.
18.473 + * This allows constructs such as:
18.474 + * <subtract><x/>1</subtract>
18.475 + * as a shorthand for:
18.476 + * <set name="x"><subtract><get><x/></get>1</subtract></set>
18.477 + * This is implied by http://www.w3.org/TR/xexpr/#id-0045
18.478 + *
18.479 + * Note that since the value accumulates:
18.480 + * <add x="1"><x/><x/><x/></add>
18.481 + * results in 4 rather than 3.
18.482 + */
18.483 + if (bind_result && arg->type==XEXPR_TYPE_INVOCATION &&
18.484 + !arg->u.invocation->bindings && !arg->u.invocation->constants)
18.485 + accumulator->result_binding=arg->u.invocation->function;
18.486 + else
18.487 + accumulator->result_binding=NULL;
18.488 + accumulator->result=xexpr_constant_evaluate(xexpr,arg,err);
18.489 + while(accumulator->result && accumulator->result->type==XEXPR_TYPE_FUNCTION)
18.490 + {
18.491 + arg=xexpr_constant_evaluate(xexpr,accumulator->result,err);
18.492 + xexpr_constant_free(accumulator->result);
18.493 + accumulator->result=arg;
18.494 + }
18.495 + return !!accumulator->result;
18.496 +}
18.497 +
18.498 +static gboolean xexpr_accumulator_next(XexprAccumulator *accumulator)
18.499 +{
18.500 + if (accumulator->result_binding && !accumulator->first)
18.501 + {
18.502 + xexpr_var_set(accumulator->xexpr,accumulator->result_binding,
18.503 + accumulator->result);
18.504 + if (xexpr_is_tracing(accumulator->xexpr,accumulator->result_binding))
18.505 + {
18.506 + printf("\nChanged variable %s\n",accumulator->result_binding);
18.507 + xexpr_stack_dump(accumulator->xexpr,stdout);
18.508 + }
18.509 + }
18.510 + accumulator->args=accumulator->args->next;
18.511 + accumulator->first=FALSE;
18.512 + return !!accumulator->args;
18.513 +}
18.514 +
18.515 +static XexprConstant *xexpr_accumulator_get(XexprAccumulator *accumulator,
18.516 + GError **err)
18.517 +{
18.518 + if (accumulator->arg)
18.519 + xexpr_constant_free(accumulator->arg);
18.520 + accumulator->arg=xexpr_constant_evaluate(accumulator->xexpr,
18.521 + accumulator->args->data,err);
18.522 + return accumulator->arg;
18.523 +}
18.524 +
18.525 +static XexprConstant *xexpr_accumulator_finish(XexprAccumulator *accumulator)
18.526 +{
18.527 + if (accumulator->arg)
18.528 + xexpr_constant_free(accumulator->arg);
18.529 + return accumulator->result;
18.530 +}
18.531 +
18.532 +static void xexpr_accumulator_abort(XexprAccumulator *accumulator)
18.533 +{
18.534 + xexpr_constant_free(xexpr_accumulator_finish(accumulator));
18.535 +}
18.536 +
18.537 +static XexprConstant *xexpr_do_add(Xexpr *xexpr,GSList *bindings,GSList *args,
18.538 + GError **err)
18.539 +{
18.540 + XexprConstant *arg;
18.541 + gchar *str;
18.542 + XexprAccumulator accumulator;
18.543 + if (!xexpr_accumulator_init(&accumulator,xexpr,args,TRUE,err))
18.544 + return NULL;
18.545 + while(xexpr_accumulator_next(&accumulator))
18.546 + {
18.547 + arg=xexpr_accumulator_get(&accumulator,err);
18.548 + if (!arg)
18.549 + {
18.550 + xexpr_accumulator_abort(&accumulator);
18.551 + return NULL;
18.552 + }
18.553 + switch(accumulator.result->type)
18.554 + {
18.555 + case XEXPR_TYPE_INVOCATION:
18.556 + case XEXPR_TYPE_FUNCTION:
18.557 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.558 + "Attempt to perform arithmetic op on a function");
18.559 + xexpr_accumulator_abort(&accumulator);
18.560 + return NULL;
18.561 + break;
18.562 + case XEXPR_TYPE_STRING:
18.563 + switch(arg->type)
18.564 + {
18.565 + case XEXPR_TYPE_FUNCTION:
18.566 + case XEXPR_TYPE_INVOCATION:
18.567 + g_set_error(err,XEXPR_EVAL_ERROR,
18.568 + XEXPR_EVAL_ERROR_FAILED,
18.569 + "Attempt to perform arithmetic op on a function");
18.570 + xexpr_accumulator_abort(&accumulator);
18.571 + return NULL;
18.572 + case XEXPR_TYPE_STRING:
18.573 + str=g_strconcat(accumulator.result->u.string,
18.574 + arg->u.string,NULL);
18.575 + g_free(accumulator.result->u.string);
18.576 + accumulator.result->u.string=str;
18.577 + break;
18.578 + case XEXPR_TYPE_INTEGER:
18.579 + str=g_strdup_printf("%s%lld",
18.580 + accumulator.result->u.string,arg->u.integer);
18.581 + g_free(accumulator.result->u.string);
18.582 + accumulator.result->u.string=str;
18.583 + break;
18.584 + case XEXPR_TYPE_NUMBER:
18.585 + str=g_strdup_printf("%s%lg",
18.586 + accumulator.result->u.string,arg->u.number);
18.587 + g_free(accumulator.result->u.string);
18.588 + accumulator.result->u.string=str;
18.589 + break;
18.590 + }
18.591 + break;
18.592 + case XEXPR_TYPE_INTEGER:
18.593 + if (arg->type==XEXPR_TYPE_INTEGER)
18.594 + {
18.595 + accumulator.result->u.integer+=arg->u.integer;
18.596 + break;
18.597 + }
18.598 + else if (arg->type==XEXPR_TYPE_NUMBER)
18.599 + {
18.600 + accumulator.result->type=XEXPR_TYPE_NUMBER;
18.601 + accumulator.result->u.number=accumulator.result->u.integer;
18.602 + }
18.603 + /* Fall through */
18.604 + case XEXPR_TYPE_NUMBER:
18.605 + if (arg->type==XEXPR_TYPE_INTEGER)
18.606 + accumulator.result->u.number+=arg->u.integer;
18.607 + else if (arg->type==XEXPR_TYPE_NUMBER)
18.608 + accumulator.result->u.number+=arg->u.number;
18.609 + else
18.610 + {
18.611 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.612 + "Attempt to add non-numeric to numeric quantity");
18.613 + xexpr_accumulator_abort(&accumulator);
18.614 + return NULL;
18.615 + }
18.616 + break;
18.617 + }
18.618 + }
18.619 + return xexpr_accumulator_finish(&accumulator);
18.620 +}
18.621 +
18.622 +static XexprConstant *xexpr_do_subtract(Xexpr *xexpr,GSList *bindings,
18.623 + GSList *args,GError **err)
18.624 +{
18.625 + XexprConstant *arg;
18.626 + XexprAccumulator accumulator;
18.627 + if (!xexpr_accumulator_init(&accumulator,xexpr,args,TRUE,err))
18.628 + return NULL;
18.629 + while(xexpr_accumulator_next(&accumulator))
18.630 + {
18.631 + arg=xexpr_accumulator_get(&accumulator,err);
18.632 + if (!arg)
18.633 + {
18.634 + xexpr_accumulator_abort(&accumulator);
18.635 + return NULL;
18.636 + }
18.637 + if (arg->type!=XEXPR_TYPE_INTEGER && arg->type!=XEXPR_TYPE_NUMBER)
18.638 + {
18.639 +invalid_args:
18.640 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.641 + "Attempt to perform subtraction on a non-numeric quantity");
18.642 + xexpr_accumulator_abort(&accumulator);
18.643 + return NULL;
18.644 + }
18.645 + switch(accumulator.result->type)
18.646 + {
18.647 + case XEXPR_TYPE_INTEGER:
18.648 + if (arg->type==XEXPR_TYPE_INTEGER)
18.649 + {
18.650 + accumulator.result->u.integer-=arg->u.integer;
18.651 + break;
18.652 + }
18.653 + else
18.654 + {
18.655 + accumulator.result->type=XEXPR_TYPE_NUMBER;
18.656 + accumulator.result->u.number=accumulator.result->u.integer;
18.657 + }
18.658 + /* Fall through */
18.659 + case XEXPR_TYPE_NUMBER:
18.660 + if (accumulator.arg->type==XEXPR_TYPE_INTEGER)
18.661 + accumulator.result->u.number-=arg->u.integer;
18.662 + else
18.663 + accumulator.result->u.number-=arg->u.number;
18.664 + break;
18.665 + default:
18.666 + goto invalid_args;
18.667 + }
18.668 + }
18.669 + return xexpr_accumulator_finish(&accumulator);
18.670 +}
18.671 +
18.672 +static XexprConstant *xexpr_do_multiply(Xexpr *xexpr,GSList *bindings,
18.673 + GSList *args,GError **err)
18.674 +{
18.675 + XexprConstant *arg;
18.676 + XexprAccumulator accumulator;
18.677 + if (!xexpr_accumulator_init(&accumulator,xexpr,args,FALSE,err))
18.678 + return NULL;
18.679 + while(xexpr_accumulator_next(&accumulator))
18.680 + {
18.681 + arg=xexpr_accumulator_get(&accumulator,err);
18.682 + if (!arg)
18.683 + {
18.684 + xexpr_accumulator_abort(&accumulator);
18.685 + return NULL;
18.686 + }
18.687 + if (arg->type!=XEXPR_TYPE_INTEGER && arg->type!=XEXPR_TYPE_NUMBER)
18.688 + {
18.689 + GString *str=g_string_new(NULL);
18.690 +invalid_args:
18.691 + xexpr_constant_dump_string(arg,str);
18.692 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.693 + "Attempt to perform multiply on a non-numeric quantity: %s",
18.694 + str->str);
18.695 + g_string_free(str,TRUE);
18.696 + xexpr_accumulator_abort(&accumulator);
18.697 + return NULL;
18.698 + }
18.699 + switch(accumulator.result->type)
18.700 + {
18.701 + case XEXPR_TYPE_INTEGER:
18.702 + if (arg->type==XEXPR_TYPE_INTEGER)
18.703 + {
18.704 + accumulator.result->u.integer*=arg->u.integer;
18.705 + break;
18.706 + }
18.707 + else
18.708 + {
18.709 + accumulator.result->type=XEXPR_TYPE_NUMBER;
18.710 + accumulator.result->u.number=accumulator.result->u.integer;
18.711 + }
18.712 + /* Fall through */
18.713 + case XEXPR_TYPE_NUMBER:
18.714 + if (arg->type==XEXPR_TYPE_INTEGER)
18.715 + accumulator.result->u.number*=arg->u.integer;
18.716 + else
18.717 + accumulator.result->u.number*=arg->u.number;
18.718 + break;
18.719 + default:
18.720 + goto invalid_args;
18.721 + }
18.722 + }
18.723 + return xexpr_accumulator_finish(&accumulator);
18.724 +}
18.725 +
18.726 +static XexprConstant *xexpr_do_divide(Xexpr *xexpr,GSList *bindings,
18.727 + GSList *args,GError **err)
18.728 +{
18.729 + XexprConstant *arg;
18.730 + long long int r;
18.731 + XexprAccumulator accumulator;
18.732 + if (!xexpr_accumulator_init(&accumulator,xexpr,args,FALSE,err))
18.733 + return NULL;
18.734 + while(xexpr_accumulator_next(&accumulator))
18.735 + {
18.736 + arg=xexpr_accumulator_get(&accumulator,err);
18.737 + if (!arg)
18.738 + {
18.739 + xexpr_accumulator_abort(&accumulator);
18.740 + return NULL;
18.741 + }
18.742 + if (arg->type!=XEXPR_TYPE_INTEGER && arg->type!=XEXPR_TYPE_NUMBER)
18.743 + {
18.744 +invalid_args:
18.745 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.746 + "Attempt to perform divide on a non-numeric quantity");
18.747 + xexpr_accumulator_abort(&accumulator);
18.748 + return NULL;
18.749 + }
18.750 + switch(accumulator.result->type)
18.751 + {
18.752 + case XEXPR_TYPE_INTEGER:
18.753 + if (arg->type==XEXPR_TYPE_INTEGER)
18.754 + {
18.755 + r=accumulator.result->u.integer/arg->u.integer;
18.756 + if (r*arg->u.integer==accumulator.result->u.integer)
18.757 + {
18.758 + accumulator.result->u.integer=r;
18.759 + break;
18.760 + }
18.761 + }
18.762 + accumulator.result->type=XEXPR_TYPE_NUMBER;
18.763 + accumulator.result->u.number=accumulator.result->u.integer;
18.764 + /* Fall through */
18.765 + case XEXPR_TYPE_NUMBER:
18.766 + if (arg->type==XEXPR_TYPE_INTEGER)
18.767 + accumulator.result->u.number/=arg->u.integer;
18.768 + else
18.769 + accumulator.result->u.number/=arg->u.number;
18.770 + break;
18.771 + default:
18.772 + goto invalid_args;
18.773 + }
18.774 + }
18.775 + return xexpr_accumulator_finish(&accumulator);
18.776 +}
18.777 +
18.778 +/**
18.779 + * xexpr_constant_cast:
18.780 + * @constant: an #XexprConstant to cast
18.781 + * @to: type to cast @constant to
18.782 + *
18.783 + * Attempt to perform an implicit cast of @constant to the given type @to.
18.784 + * Implicit casting can only be performed between the two numeric types
18.785 + * and then only where the quantity can be represented without loss of
18.786 + * precision.
18.787 + *
18.788 + * Return value: %TRUE if @constant is now of type @to.
18.789 + */
18.790 +gboolean xexpr_constant_cast(XexprConstant *constant,XexprType to)
18.791 +{
18.792 + double dummy;
18.793 + if (constant->type==to)
18.794 + return TRUE;
18.795 + if (constant->type==XEXPR_TYPE_NUMBER && to==XEXPR_TYPE_INTEGER &&
18.796 + constant->u.number>=LLONG_MIN && constant->u.number<=LLONG_MAX &&
18.797 + !modf(constant->u.number,&dummy))
18.798 + {
18.799 + constant->type=XEXPR_TYPE_INTEGER;
18.800 + constant->u.integer=constant->u.number;
18.801 + return TRUE;
18.802 + }
18.803 + else if (constant->type==XEXPR_TYPE_INTEGER && to==XEXPR_TYPE_NUMBER &&
18.804 + constant->u.integer+1.0!=(double)constant->u.integer &&
18.805 + constant->u.integer-1.0!=(double)constant->u.integer)
18.806 + {
18.807 + constant->type=XEXPR_TYPE_NUMBER;
18.808 + constant->u.number=constant->u.integer;
18.809 + return TRUE;
18.810 + }
18.811 + else
18.812 + return FALSE;
18.813 +}
18.814 +
18.815 +static gboolean xexpr_constant_boolean(Xexpr *xexpr,XexprConstant *constant,
18.816 + GError **err)
18.817 +{
18.818 + gboolean retval;
18.819 + XexprConstant *result;
18.820 + switch (constant->type)
18.821 + {
18.822 + case XEXPR_TYPE_NUMBER:
18.823 + return !(constant->u.number==0);
18.824 + case XEXPR_TYPE_INTEGER:
18.825 + return !!constant->u.integer;
18.826 + case XEXPR_TYPE_STRING:
18.827 + return !!*constant->u.string;
18.828 + case XEXPR_TYPE_INVOCATION:
18.829 + return strcmp(constant->u.invocation->function,"false") &&
18.830 + strcmp(constant->u.invocation->function,"nil");
18.831 + case XEXPR_TYPE_FUNCTION:
18.832 + /*
18.833 + * See http://www.w3.org/TR/xexpr/#id-0038
18.834 + */
18.835 + result=xexpr_constant_evaluate(xexpr,constant,err);
18.836 + if (!result)
18.837 + return FALSE;
18.838 + retval=xexpr_constant_boolean(xexpr,result,err);
18.839 + xexpr_constant_free(result);
18.840 + return retval;
18.841 + }
18.842 + return FALSE;
18.843 +}
18.844 +
18.845 +/*
18.846 + * Returns: 0 if equal, <0 if value1 < value2, >0 if value1 > value2,
18.847 + * NaN if value1 is not comparible with value2.
18.848 + */
18.849 +static double xexpr_constant_compare(Xexpr *xexpr,XexprConstant *v1,
18.850 + XexprConstant *v2)
18.851 +{
18.852 + double retval=0.0/0.0;
18.853 + XexprConstant *value1,*value2;
18.854 + value1=xexpr_constant_evaluate(xexpr,v1,NULL);
18.855 + if (!value1)
18.856 + value1=xexpr_constant_dup(v1);
18.857 + while(value1->type==XEXPR_TYPE_FUNCTION)
18.858 + {
18.859 + v1=xexpr_constant_evaluate(xexpr,value1,NULL);
18.860 + if (v1)
18.861 + {
18.862 + xexpr_constant_free(value1);
18.863 + value1=v1;
18.864 + }
18.865 + else
18.866 + break;
18.867 + }
18.868 + value2=xexpr_constant_evaluate(xexpr,v2,NULL);
18.869 + if (!value2)
18.870 + value2=xexpr_constant_dup(v2);
18.871 + while(value2->type==XEXPR_TYPE_FUNCTION)
18.872 + {
18.873 + v2=xexpr_constant_evaluate(xexpr,value2,NULL);
18.874 + if (v2)
18.875 + {
18.876 + xexpr_constant_free(value2);
18.877 + value2=v2;
18.878 + }
18.879 + else
18.880 + break;
18.881 + }
18.882 + if (value1->type!=value2->type)
18.883 + {
18.884 + if (!xexpr_constant_cast(value1,value2->type) &&
18.885 + !xexpr_constant_cast(value2,value1->type))
18.886 + {
18.887 + xexpr_constant_free(value1);
18.888 + xexpr_constant_free(value2);
18.889 + return 0.0/0.0;
18.890 + }
18.891 + }
18.892 + switch(value1->type)
18.893 + {
18.894 + case XEXPR_TYPE_FUNCTION:
18.895 + g_warn_if_reached();
18.896 + break;
18.897 + case XEXPR_TYPE_INVOCATION:
18.898 + g_warn_if_fail(value1->u.invocation->bindings==NULL);
18.899 + g_warn_if_fail(value2->u.invocation->bindings==NULL);
18.900 + g_warn_if_fail(value1->u.invocation->constants==NULL);
18.901 + g_warn_if_fail(value2->u.invocation->constants==NULL);
18.902 + retval=strcmp(value1->u.invocation->function,
18.903 + value2->u.invocation->function);
18.904 + break;
18.905 + case XEXPR_TYPE_STRING:
18.906 + retval=strcmp(value1->u.string,value2->u.string);
18.907 + break;
18.908 + case XEXPR_TYPE_INTEGER:
18.909 + retval=value1->u.integer-value2->u.integer;
18.910 + break;
18.911 + case XEXPR_TYPE_NUMBER:
18.912 + retval=value1->u.number-value2->u.number;
18.913 + break;
18.914 + }
18.915 + xexpr_constant_free(value1);
18.916 + xexpr_constant_free(value2);
18.917 + return retval;
18.918 +}
18.919 +
18.920 +static XexprConstant *xexpr_do_eq(Xexpr *xexpr,GSList *bindings,GSList *args,
18.921 + GError **err)
18.922 +{
18.923 + XexprConstant *arg,*standard=NULL;
18.924 + while(args)
18.925 + {
18.926 + arg=args->data;
18.927 + if (!standard)
18.928 + standard=arg;
18.929 + else if (xexpr_constant_compare(xexpr,standard,arg))
18.930 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.931 + args=args->next;
18.932 + }
18.933 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.934 +}
18.935 +
18.936 +static XexprConstant *xexpr_do_neq(Xexpr *xexpr,GSList *bindings,GSList *args,
18.937 + GError **err)
18.938 +{
18.939 + XexprConstant *arg;
18.940 + GSList *lnk;
18.941 + while(args)
18.942 + {
18.943 + arg=args->data;
18.944 + for(lnk=args->next;lnk;lnk=lnk->next)
18.945 + if (!xexpr_constant_compare(xexpr,arg,lnk->data))
18.946 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.947 + args=args->next;
18.948 + }
18.949 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.950 +}
18.951 +
18.952 +static XexprConstant *xexpr_do_leq(Xexpr *xexpr,GSList *bindings,GSList *args,
18.953 + GError **err)
18.954 +{
18.955 + XexprConstant *arg,*standard=NULL;
18.956 + while(args)
18.957 + {
18.958 + arg=args->data;
18.959 + if (standard && !(xexpr_constant_compare(xexpr,standard,arg)<=0))
18.960 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.961 + standard=arg;
18.962 + args=args->next;
18.963 + }
18.964 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.965 +}
18.966 +
18.967 +static XexprConstant *xexpr_do_geq(Xexpr *xexpr,GSList *bindings,GSList *args,
18.968 + GError **err)
18.969 +{
18.970 + XexprConstant *arg,*standard=NULL;
18.971 + while(args)
18.972 + {
18.973 + arg=args->data;
18.974 + if (standard && !(xexpr_constant_compare(xexpr,standard,arg)>=0))
18.975 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.976 + standard=arg;
18.977 + args=args->next;
18.978 + }
18.979 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.980 +}
18.981 +
18.982 +static XexprConstant *xexpr_do_lt(Xexpr *xexpr,GSList *bindings,GSList *args,
18.983 + GError **err)
18.984 +{
18.985 + XexprConstant *arg,*standard=NULL;
18.986 + while(args)
18.987 + {
18.988 + arg=args->data;
18.989 + if (standard && !(xexpr_constant_compare(xexpr,standard,arg)<0))
18.990 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.991 + standard=arg;
18.992 + args=args->next;
18.993 + }
18.994 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.995 +}
18.996 +
18.997 +static XexprConstant *xexpr_do_gt(Xexpr *xexpr,GSList *bindings,GSList *args,
18.998 + GError **err)
18.999 +{
18.1000 + XexprConstant *arg,*standard=NULL;
18.1001 + while(args)
18.1002 + {
18.1003 + arg=args->data;
18.1004 + if (standard && !(xexpr_constant_compare(xexpr,standard,arg)>0))
18.1005 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.1006 + standard=arg;
18.1007 + args=args->next;
18.1008 + }
18.1009 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.1010 +}
18.1011 +
18.1012 +static XexprConstant *xexpr_do_and(Xexpr *xexpr,GSList *bindings,GSList *args,
18.1013 + GError **err)
18.1014 +{
18.1015 + GError *tmp_err=NULL;
18.1016 + XexprConstant *arg;
18.1017 + XexprAccumulator accumulator;
18.1018 + if (!args)
18.1019 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.1020 + if (!xexpr_accumulator_init(&accumulator,xexpr,args,FALSE,err))
18.1021 + return NULL;
18.1022 + if (!xexpr_constant_boolean(xexpr,accumulator.result,&tmp_err))
18.1023 + {
18.1024 + xexpr_accumulator_abort(&accumulator);
18.1025 + if (tmp_err)
18.1026 + {
18.1027 + g_propagate_error(err,tmp_err);
18.1028 + return NULL;
18.1029 + }
18.1030 + else
18.1031 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.1032 + }
18.1033 + while(xexpr_accumulator_next(&accumulator))
18.1034 + {
18.1035 + arg=xexpr_accumulator_get(&accumulator,err);
18.1036 + if (!arg)
18.1037 + {
18.1038 + xexpr_accumulator_abort(&accumulator);
18.1039 + return NULL;
18.1040 + }
18.1041 + if (!xexpr_constant_boolean(xexpr,arg,&tmp_err))
18.1042 + {
18.1043 + xexpr_accumulator_abort(&accumulator);
18.1044 + if (tmp_err)
18.1045 + {
18.1046 + g_propagate_error(err,tmp_err);
18.1047 + return NULL;
18.1048 + }
18.1049 + else
18.1050 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.1051 + }
18.1052 + }
18.1053 + xexpr_accumulator_abort(&accumulator);
18.1054 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.1055 +}
18.1056 +
18.1057 +static XexprConstant *xexpr_do_or(Xexpr *xexpr,GSList *bindings,GSList *args,
18.1058 + GError **err)
18.1059 +{
18.1060 + GError *tmp_err=NULL;
18.1061 + XexprConstant *arg;
18.1062 + XexprAccumulator accumulator;
18.1063 + if (!args)
18.1064 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.1065 + if (!xexpr_accumulator_init(&accumulator,xexpr,args,FALSE,err))
18.1066 + return NULL;
18.1067 + if (xexpr_constant_boolean(xexpr,accumulator.result,&tmp_err))
18.1068 + {
18.1069 + xexpr_accumulator_abort(&accumulator);
18.1070 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.1071 + }
18.1072 + else if (tmp_err)
18.1073 + {
18.1074 + xexpr_accumulator_abort(&accumulator);
18.1075 + g_propagate_error(err,tmp_err);
18.1076 + return NULL;
18.1077 + }
18.1078 + while(xexpr_accumulator_next(&accumulator))
18.1079 + {
18.1080 + arg=xexpr_accumulator_get(&accumulator,err);
18.1081 + if (!arg)
18.1082 + {
18.1083 + xexpr_accumulator_abort(&accumulator);
18.1084 + return NULL;
18.1085 + }
18.1086 + if (xexpr_constant_boolean(xexpr,arg,&tmp_err))
18.1087 + {
18.1088 + xexpr_accumulator_abort(&accumulator);
18.1089 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.1090 + }
18.1091 + else if (tmp_err)
18.1092 + {
18.1093 + xexpr_accumulator_abort(&accumulator);
18.1094 + g_propagate_error(err,tmp_err);
18.1095 + return NULL;
18.1096 + }
18.1097 + }
18.1098 + xexpr_accumulator_abort(&accumulator);
18.1099 + return xexpr_new_invocation(NULL,"false",NULL,NULL);
18.1100 +}
18.1101 +
18.1102 +/*
18.1103 + * <not> is a misnomer, http://www.w3.org/TR/xexpr/#id-0040
18.1104 + * makes it clear that, except in the trivial case of no arguments,
18.1105 + * <not> is simply the negation of <and>.
18.1106 + */
18.1107 +static XexprConstant *xexpr_do_not(Xexpr *xexpr,GSList *bindings,GSList *args,
18.1108 + GError **err)
18.1109 +{
18.1110 + gboolean test;
18.1111 + XexprConstant *result;
18.1112 + if (!args)
18.1113 + return xexpr_new_invocation(NULL,"true",NULL,NULL);
18.1114 + result=xexpr_do_and(xexpr,bindings,args,err);
18.1115 + if (!result)
18.1116 + return NULL;
18.1117 + test=xexpr_constant_boolean(xexpr,result,NULL);
18.1118 + xexpr_constant_free(result);
18.1119 + return xexpr_new_invocation(NULL,test?"false":"true",NULL,NULL);
18.1120 +}
18.1121 +
18.1122 +static XexprConstant *xexpr_do_if(Xexpr *xexpr,GSList *bindings,GSList *args,
18.1123 + GError **err)
18.1124 +{
18.1125 + GError *tmp_err=NULL;
18.1126 + gboolean test;
18.1127 + XexprConstant *arg;
18.1128 + if (g_slist_length(args)<2)
18.1129 + {
18.1130 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1131 + "<if> requires at least 2 arguments to be passed");
18.1132 + return NULL;
18.1133 + }
18.1134 + arg=xexpr_constant_evaluate(xexpr,args->data,err);
18.1135 + if (!arg)
18.1136 + return NULL;
18.1137 + test=xexpr_constant_boolean(xexpr,arg,&tmp_err);
18.1138 + if (tmp_err)
18.1139 + {
18.1140 + g_propagate_error(err,tmp_err);
18.1141 + return NULL;
18.1142 + }
18.1143 + xexpr_constant_free(arg);
18.1144 + if (test)
18.1145 + return xexpr_constant_evaluate(xexpr,args->next->data,err);
18.1146 + else if (args->next->next)
18.1147 + return xexpr_constant_evaluate(xexpr,args->next->next->data,err);
18.1148 + else
18.1149 + return xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.1150 +}
18.1151 +
18.1152 +static XexprConstant *xexpr_do_switch(Xexpr *xexpr,GSList *bindings,
18.1153 + GSList *args,GError **err)
18.1154 +{
18.1155 + GError *tmp_err=NULL;
18.1156 + gboolean test;
18.1157 + XexprConstant *case_arg,*arg;
18.1158 + GSList *lnk;
18.1159 + while(args)
18.1160 + {
18.1161 + case_arg=args->data;
18.1162 + if (case_arg->type!=XEXPR_TYPE_INVOCATION ||
18.1163 + strcmp(case_arg->u.invocation->function,"case"))
18.1164 + {
18.1165 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1166 + "<switch> requires a list of <case> expressions");
18.1167 + return NULL;
18.1168 + }
18.1169 + lnk=case_arg->u.invocation->constants;
18.1170 + if (!lnk)
18.1171 + {
18.1172 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1173 + "<case> requires a test expression");
18.1174 + return NULL;
18.1175 + }
18.1176 + arg=xexpr_constant_evaluate(xexpr,lnk->data,err);
18.1177 + if (!arg)
18.1178 + return NULL;
18.1179 + test=xexpr_constant_boolean(xexpr,arg,&tmp_err);
18.1180 + if (tmp_err)
18.1181 + {
18.1182 + g_propagate_error(err,tmp_err);
18.1183 + return NULL;
18.1184 + }
18.1185 + xexpr_constant_free(arg);
18.1186 + if (test)
18.1187 + {
18.1188 + arg=NULL;
18.1189 + while(lnk)
18.1190 + {
18.1191 + if (arg)
18.1192 + xexpr_constant_free(arg);
18.1193 + arg=xexpr_constant_evaluate(xexpr,lnk->data,err);
18.1194 + if (!arg)
18.1195 + return NULL;
18.1196 + lnk=lnk->next;
18.1197 + }
18.1198 + if (!arg)
18.1199 + arg=xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.1200 + return arg;
18.1201 + }
18.1202 + args=args->next;
18.1203 + }
18.1204 + return xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.1205 +}
18.1206 +
18.1207 +static XexprConstant *xexpr_do_while(Xexpr *xexpr,GSList *bindings,GSList *args,
18.1208 + GError **err)
18.1209 +{
18.1210 + GError *tmp_err=NULL;
18.1211 + gboolean test;
18.1212 + XexprConstant *arg,*result;
18.1213 + if (g_slist_length(args)!=2)
18.1214 + {
18.1215 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1216 + "<while> takes 2 arguments");
18.1217 + return NULL;
18.1218 + }
18.1219 + result=xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.1220 + do
18.1221 + {
18.1222 + arg=xexpr_constant_evaluate(xexpr,args->data,err);
18.1223 + if (!arg)
18.1224 + {
18.1225 + xexpr_constant_free(result);
18.1226 + return NULL;
18.1227 + }
18.1228 + test=xexpr_constant_boolean(xexpr,arg,&tmp_err);
18.1229 + if (tmp_err)
18.1230 + {
18.1231 + g_propagate_error(err,tmp_err);
18.1232 + return NULL;
18.1233 + }
18.1234 + xexpr_constant_free(arg);
18.1235 + if (test)
18.1236 + {
18.1237 + xexpr_constant_free(result);
18.1238 + result=xexpr_constant_evaluate(xexpr,args->next->data,err);
18.1239 + if (!result)
18.1240 + return NULL;
18.1241 + }
18.1242 + } while(test);
18.1243 + return result;
18.1244 +}
18.1245 +
18.1246 +static XexprConstant *xexpr_do_do(Xexpr *xexpr,GSList *bindings,GSList *args,
18.1247 + GError **err)
18.1248 +{
18.1249 + GError *tmp_err=NULL;
18.1250 + gboolean test;
18.1251 + XexprConstant *arg,*result;
18.1252 + if (g_slist_length(args)!=2)
18.1253 + {
18.1254 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1255 + "<do> takes 2 arguments");
18.1256 + return NULL;
18.1257 + }
18.1258 + result=NULL;
18.1259 + do
18.1260 + {
18.1261 + if (result)
18.1262 + xexpr_constant_free(result);
18.1263 + result=xexpr_constant_evaluate(xexpr,args->data,err);
18.1264 + if (!result)
18.1265 + return NULL;
18.1266 + arg=xexpr_constant_evaluate(xexpr,args->next->data,err);
18.1267 + if (!arg)
18.1268 + {
18.1269 + xexpr_constant_free(result);
18.1270 + return NULL;
18.1271 + }
18.1272 + test=xexpr_constant_boolean(xexpr,arg,&tmp_err);
18.1273 + if (tmp_err)
18.1274 + {
18.1275 + g_propagate_error(err,tmp_err);
18.1276 + return NULL;
18.1277 + }
18.1278 + xexpr_constant_free(arg);
18.1279 + } while(test);
18.1280 + return result;
18.1281 +}
18.1282 +
18.1283 +static struct xexpr_builtin {
18.1284 + char *id;
18.1285 + gboolean evaluate_args;
18.1286 + XexprConstant *(*func)(Xexpr *xexpr,GSList *bindings,GSList *args,
18.1287 + GError **err);
18.1288 +} xexpr_builtins[]={
18.1289 + { "define", FALSE, xexpr_do_define },
18.1290 + { "print", TRUE, xexpr_do_print },
18.1291 + { "println", TRUE, xexpr_do_println },
18.1292 + { "get", TRUE, xexpr_do_get },
18.1293 + { "set", TRUE, xexpr_do_set },
18.1294 + { "expr", TRUE, xexpr_do_expr },
18.1295 + { "xexpr", TRUE, xexpr_do_expr },
18.1296 + { "return", TRUE, xexpr_do_return },
18.1297 + { "string", TRUE, xexpr_do_string },
18.1298 + { "integer", TRUE, xexpr_do_integer },
18.1299 + { "float", TRUE, xexpr_do_float },
18.1300 + { "true", TRUE, xexpr_do_true },
18.1301 + { "false", TRUE, xexpr_do_false },
18.1302 + { "nil", TRUE, xexpr_do_nil },
18.1303 + { "add", FALSE, xexpr_do_add },
18.1304 + { "subtract", FALSE, xexpr_do_subtract },
18.1305 + { "multiply", FALSE, xexpr_do_multiply },
18.1306 + { "divide", FALSE, xexpr_do_divide },
18.1307 + { "eq", TRUE, xexpr_do_eq },
18.1308 + { "neq", TRUE, xexpr_do_neq },
18.1309 + { "leq", TRUE, xexpr_do_leq },
18.1310 + { "geq", TRUE, xexpr_do_geq },
18.1311 + { "lt", TRUE, xexpr_do_lt },
18.1312 + { "gt", TRUE, xexpr_do_gt },
18.1313 + { "and", FALSE, xexpr_do_and },
18.1314 + { "or", FALSE, xexpr_do_or },
18.1315 + { "not", FALSE, xexpr_do_not },
18.1316 + { "if", FALSE, xexpr_do_if },
18.1317 + { "switch", FALSE, xexpr_do_switch },
18.1318 + { "while", FALSE, xexpr_do_while },
18.1319 + { "do", FALSE, xexpr_do_do },
18.1320 +};
18.1321 +
18.1322 +static gboolean xexpr_defineable_id(const char *id,GError **err)
18.1323 +{
18.1324 + int i;
18.1325 + for(i=0;i<G_N_ELEMENTS(xexpr_builtins);i++)
18.1326 + if (!strcmp(xexpr_builtins[i].id,id))
18.1327 + {
18.1328 + g_set_error(err,XEXPR_PARSE_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1329 + "Can't define reserved XEXPR ID \"%s\"",id);
18.1330 + return FALSE;
18.1331 + }
18.1332 + return TRUE;
18.1333 +}
18.1334 +
18.1335 +static XexprConstant *xexpr_closure(Xexpr *xexpr,XexprConstant *constant,
18.1336 + GError **err)
18.1337 +{
18.1338 + GSList *lnk;
18.1339 + XexprConstant *result,*tmp;
18.1340 + g_return_val_if_fail(constant->type==XEXPR_TYPE_FUNCTION,NULL);
18.1341 + result=NULL;
18.1342 + for(lnk=constant->u.function->constants;lnk;lnk=lnk->next)
18.1343 + {
18.1344 + if (result)
18.1345 + xexpr_constant_free(result);
18.1346 + result=xexpr_constant_evaluate(xexpr,lnk->data,err);
18.1347 + if (!result)
18.1348 + return NULL;
18.1349 + if (result->type==XEXPR_TYPE_INVOCATION &&
18.1350 + !strcmp(result->u.invocation->function,"return"))
18.1351 + {
18.1352 + lnk=g_slist_last(result->u.invocation->constants);
18.1353 + tmp=xexpr_constant_dup(lnk->data);
18.1354 + xexpr_constant_free(result);
18.1355 + result=tmp;
18.1356 + break;
18.1357 + }
18.1358 + }
18.1359 + if (!result)
18.1360 + result=xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.1361 + return result;
18.1362 +}
18.1363 +
18.1364 +static XexprConstant *xexpr_function_evaluate(Xexpr *xexpr,const char *ns,
18.1365 + const char *id,GSList *bindings,GSList *args,GError **err)
18.1366 +{
18.1367 + int builtin;
18.1368 + gboolean evaluate_args;
18.1369 + XexprBinding *binding;
18.1370 + XexprExtension *ext;
18.1371 + XexprConstant *value,*function_def,*result;
18.1372 + const char *unbound_parameter;
18.1373 + GSList *unbound_args=args,*lnk,*actual,*unbound_parameters;
18.1374 + if (ns)
18.1375 + {
18.1376 + for(lnk=xexpr_extensions;lnk;lnk=lnk->next)
18.1377 + {
18.1378 + ext=lnk->data;
18.1379 + if (!strcmp(ext->ns,ns))
18.1380 + return ext->function_evaluate(xexpr,ns,id,bindings,args,err);
18.1381 + }
18.1382 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1383 + "Unknown namespace \"%s\"",ns);
18.1384 + return NULL;
18.1385 + }
18.1386 + for(builtin=0;builtin<G_N_ELEMENTS(xexpr_builtins);builtin++)
18.1387 + if (!strcmp(xexpr_builtins[builtin].id,id))
18.1388 + {
18.1389 + evaluate_args=xexpr_builtins[builtin].evaluate_args;
18.1390 + break;
18.1391 + }
18.1392 + if (builtin==G_N_ELEMENTS(xexpr_builtins))
18.1393 + {
18.1394 + function_def=xexpr_var_get(xexpr,id);
18.1395 + if (!function_def)
18.1396 + {
18.1397 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1398 + "Undefined function: \"%s\"",id);
18.1399 + return NULL;
18.1400 + }
18.1401 + else if (function_def->type!=XEXPR_TYPE_FUNCTION)
18.1402 + return xexpr_constant_evaluate(xexpr,function_def,err);
18.1403 + unbound_parameters=g_slist_copy(function_def->u.function->args);
18.1404 + evaluate_args=TRUE;
18.1405 + }
18.1406 + else
18.1407 + {
18.1408 + function_def=NULL;
18.1409 + unbound_parameters=NULL;
18.1410 + }
18.1411 + for(lnk=bindings;lnk;lnk=lnk->next)
18.1412 + {
18.1413 + binding=lnk->data;
18.1414 + actual=g_slist_find_custom(unbound_parameters,binding->id,
18.1415 + (GCompareFunc)strcmp);
18.1416 + if (actual)
18.1417 + unbound_parameters=g_slist_delete_link(unbound_parameters,actual);
18.1418 + xexpr_var_new(xexpr,binding->id,binding->value);
18.1419 + }
18.1420 + if (evaluate_args)
18.1421 + {
18.1422 + for(lnk=unbound_parameters;lnk;lnk=lnk->next)
18.1423 + {
18.1424 + unbound_parameter=lnk->data;
18.1425 + value=xexpr_var_get(xexpr,unbound_parameter);
18.1426 + if (value)
18.1427 + xexpr_var_new(xexpr,unbound_parameter,value);
18.1428 + else
18.1429 + {
18.1430 + value=xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.1431 + xexpr_var_new(xexpr,unbound_parameter,value);
18.1432 + xexpr_constant_free(value);
18.1433 + }
18.1434 + }
18.1435 + }
18.1436 + while(unbound_parameters)
18.1437 + {
18.1438 + unbound_parameter=unbound_parameters->data;
18.1439 + if (unbound_args)
18.1440 + {
18.1441 + if (evaluate_args)
18.1442 + {
18.1443 + value=xexpr_constant_evaluate(xexpr,unbound_args->data,err);
18.1444 + if (!value)
18.1445 + {
18.1446 + g_slist_free(unbound_parameters);
18.1447 + return NULL;
18.1448 + }
18.1449 + xexpr_var_set(xexpr,unbound_parameter,value);
18.1450 + xexpr_constant_free(value);
18.1451 + }
18.1452 + else
18.1453 + {
18.1454 + value=unbound_args->data;
18.1455 + xexpr_var_new(xexpr,unbound_parameter,value);
18.1456 + }
18.1457 + unbound_args=unbound_args->next;
18.1458 + unbound_parameters=
18.1459 + g_slist_delete_link(unbound_parameters,unbound_parameters);
18.1460 + }
18.1461 + else
18.1462 + {
18.1463 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
18.1464 + "No actual value to bind to parameter %s of function %s",
18.1465 + unbound_parameter,id);
18.1466 + g_slist_free(unbound_parameters);
18.1467 + return NULL;
18.1468 + }
18.1469 + }
18.1470 + if (evaluate_args)
18.1471 + {
18.1472 + args=NULL;
18.1473 + while(unbound_args)
18.1474 + {
18.1475 + value=xexpr_constant_evaluate(xexpr,unbound_args->data,err);
18.1476 + if (!value)
18.1477 + return NULL;
18.1478 + args=g_slist_prepend(args,value);
18.1479 + unbound_args=unbound_args->next;
18.1480 + }
18.1481 + args=g_slist_reverse(args);
18.1482 + }
18.1483 + if (function_def)
18.1484 + result=xexpr_closure(xexpr,function_def,err);
18.1485 + else
18.1486 + result=xexpr_builtins[builtin].func(xexpr,bindings,args,err);
18.1487 + if (evaluate_args)
18.1488 + {
18.1489 + g_slist_foreach(args,(GFunc)xexpr_constant_free,NULL);
18.1490 + g_slist_free(args);
18.1491 + }
18.1492 + return result;
18.1493 +}
18.1494 +
18.1495 +/**
18.1496 + * xexpr_constant_evaluate:
18.1497 + * @xexpr: an #Xexpr
18.1498 + * @constant: the #XexprConstant to evaluate
18.1499 + * @err: (allow-none): location to store error, or %NULL
18.1500 + *
18.1501 + * Evaluate an XEXPR expression. Typically, an expression will evaluate to
18.1502 + * one of the basic types: string, integer or float. However, the XEXPR
18.1503 + * language specification states that <define> returns a function
18.1504 + * object (ie., an #XexprConstant with type %XEXPR_TYPE_FUNCTION).
18.1505 + * If such a function object is passed to xexpr_constant_evaluate(), then
18.1506 + * the function definition will be evaluated. If the function takes
18.1507 + * arguments, then these will be taken as <nil>.
18.1508 + *
18.1509 + * The returned expresion should be freed with xexpr_constant_free()
18.1510 + * when no longer needed.
18.1511 + *
18.1512 + * Return value: (transfer full): The evaluated result, or %NULL on error
18.1513 + */
18.1514 +XexprConstant *xexpr_constant_evaluate(Xexpr *xexpr,XexprConstant *constant,
18.1515 + GError **err)
18.1516 +{
18.1517 + GSList *lnk;
18.1518 + XexprConstant *result,*tmp;
18.1519 + switch(constant->type)
18.1520 + {
18.1521 + case XEXPR_TYPE_FUNCTION:
18.1522 + /*
18.1523 + * It's not clear how function objects should be evaluated.
18.1524 + * We choose to invoke them with all arguments as <nil/>.
18.1525 + * Note that this means that <get>x</get> will not error
18.1526 + * out if x is defined as taking arguments whereas <x/>
18.1527 + * will. http://www.w3.org/TR/xexpr/#id-0014 states that
18.1528 + * these have the same effect in _most_ cases which implies
18.1529 + * that there are differences in some cases.
18.1530 + */
18.1531 + _xexpr_push_environment(xexpr,NULL);
18.1532 + tmp=xexpr_new_invocation(NULL,"nil",NULL,NULL);
18.1533 + for(lnk=constant->u.function->args;lnk;lnk=lnk->next)
18.1534 + xexpr_var_new(xexpr,lnk->data,tmp);
18.1535 + xexpr_constant_free(tmp);
18.1536 + result=xexpr_closure(xexpr,constant,err);
18.1537 + _xexpr_pop_environment(xexpr);
18.1538 + return result;
18.1539 + break;
18.1540 + case XEXPR_TYPE_INVOCATION:
18.1541 + _xexpr_push_environment(xexpr,constant->u.invocation->function);
18.1542 + result=xexpr_function_evaluate(xexpr,
18.1543 + constant->u.invocation->ns,
18.1544 + constant->u.invocation->function,
18.1545 + constant->u.invocation->bindings,
18.1546 + constant->u.invocation->constants,err);
18.1547 + _xexpr_pop_environment(xexpr);
18.1548 + return result;
18.1549 + break;
18.1550 + case XEXPR_TYPE_STRING:
18.1551 + return xexpr_new_string(constant->u.string,-1);
18.1552 + break;
18.1553 + case XEXPR_TYPE_INTEGER:
18.1554 + return xexpr_new_integer(constant->u.integer);
18.1555 + break;
18.1556 + case XEXPR_TYPE_NUMBER:
18.1557 + return xexpr_new_number(constant->u.number);
18.1558 + break;
18.1559 + }
18.1560 + return NULL;
18.1561 +}
18.1562 +
18.1563 +/**
18.1564 + * xexpr_evaluate:
18.1565 + * @xexpr: an #Xexpr to evaluate
18.1566 + * @err: (allow-none): location to store error, or %NULL
18.1567 + *
18.1568 + * Evaluate an XEXPR expression. Typically, an expression will evaluate to
18.1569 + * one of the basic types: string, integer or float. However, the XEXPR
18.1570 + * language specification states that <define> returns a function
18.1571 + * object (ie., an #XexprConstant with type %XEXPR_TYPE_FUNCTION).
18.1572 + * If such a function object is passed to xexpr_evaluate(), then
18.1573 + * the function definition will be evaluated. If the function takes
18.1574 + * arguments, then these will be taken as <nil>.
18.1575 + *
18.1576 + * The returned expresion should be freed with xexpr_free()
18.1577 + * when no longer needed.
18.1578 + *
18.1579 + * Return value: (transfer full): The evaluated result, or %NULL on error
18.1580 + */
18.1581 +Xexpr *xexpr_evaluate(Xexpr *xexpr,GError **err)
18.1582 +{
18.1583 + Xexpr *results;
18.1584 + XexprConstant *constant,*result;
18.1585 + GSList *lnk;
18.1586 + results=xexpr_sub(xexpr);
18.1587 + for(lnk=xexpr->constants;lnk;lnk=lnk->next)
18.1588 + {
18.1589 + constant=lnk->data;
18.1590 + result=xexpr_constant_evaluate(xexpr,constant,err);
18.1591 + if (!result)
18.1592 + {
18.1593 + xexpr_free(results);
18.1594 + return NULL;
18.1595 + }
18.1596 + else
18.1597 + results->constants=g_slist_prepend(results->constants,result);
18.1598 + }
18.1599 + results->constants=g_slist_reverse(results->constants);
18.1600 + return results;
18.1601 +}
18.1602 +
18.1603 +/**
18.1604 + * xexpr_test:
18.1605 + * @xexpr: an #Xexpr to test
18.1606 + * @err: (allow-none): location to store error, or %NULL
18.1607 + *
18.1608 + * Test an expression by looking at the last constant in the expression.
18.1609 + * Numerical constants are treated as <true> if they are non-zero,
18.1610 + * string constants are treated as <true> if they are non-empty,
18.1611 + * function invocations are treated as <true> unless they are
18.1612 + * <false> or <nil>, function definitions are recursively
18.1613 + * evaluated before they are tested.
18.1614 + *
18.1615 + * Return value: %TRUE if the expression is equivalent to <true>.
18.1616 + */
18.1617 +gboolean xexpr_test(Xexpr *xexpr,GError **err)
18.1618 +{
18.1619 + GSList *lnk;
18.1620 + XexprConstant *constant;
18.1621 + lnk=g_slist_last(xexpr->constants);
18.1622 + constant=lnk->data;
18.1623 + return xexpr_constant_boolean(xexpr,constant,err);
18.1624 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/libxexpr/xexpreval.h Wed Oct 10 22:58:21 2012 +0100
19.3 @@ -0,0 +1,37 @@
19.4 +#ifndef __XEXPER_EVAL_H__
19.5 +#define __XEXPER_EVAL_H__
19.6 +
19.7 +#include <glib.h>
19.8 +#include "xexprtypes.h"
19.9 +
19.10 +G_BEGIN_DECLS
19.11 +
19.12 +/**
19.13 + * XEXPR_EVAL_ERROR:
19.14 + *
19.15 + * Used to get the #GError quark for libxexpr evaluator errors.
19.16 + */
19.17 +#define XEXPR_EVAL_ERROR xexpr_eval_error_quark()
19.18 +
19.19 +/**
19.20 + * XexprEvalError:
19.21 + * @XEXPR_EVAL_ERROR_FAILED: Indicates a generic failure.
19.22 + *
19.23 + * Enum values for evaluator errors.
19.24 + */
19.25 +typedef enum
19.26 +{
19.27 + XEXPR_EVAL_ERROR_FAILED
19.28 +} XexprEvalError;
19.29 +
19.30 +GQuark xexpr_eval_error_quark(void);
19.31 +gboolean xexpr_register_extension(XexprExtension *extension);
19.32 +XexprConstant *xexpr_constant_evaluate(Xexpr *xexpr,XexprConstant *constant,
19.33 + GError **err);
19.34 +Xexpr *xexpr_evaluate(Xexpr *xexpr,GError **err);
19.35 +gboolean xexpr_constant_cast(XexprConstant *constant,XexprType to);
19.36 +gboolean xexpr_test(Xexpr *xexpr,GError **err);
19.37 +
19.38 +G_END_DECLS
19.39 +
19.40 +#endif /* __XEXPER_EVAL_H__ */
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/libxexpr/xexprparse.c Wed Oct 10 22:58:21 2012 +0100
20.3 @@ -0,0 +1,320 @@
20.4 +#include <stdlib.h>
20.5 +#include <string.h>
20.6 +#include <math.h>
20.7 +#include "xexprparse.h"
20.8 +
20.9 +/**
20.10 + * SECTION:xexprparse
20.11 + * @short_description: A parser for the XEXPR language
20.12 + * @stability: Stable
20.13 + * @include: libxexpr/xexpr.h
20.14 + *
20.15 + * A parser for the
20.16 + * <ulink url="http://www.w3.org/TR/2000/NOTE-xexpr-20001121">XEXPR</ulink>
20.17 + * language.
20.18 + */
20.19 +
20.20 +/**
20.21 + * xexpr_parse_error_quark:
20.22 + *
20.23 + * Registers an error quark for the libxexpr parser if necessary.
20.24 + *
20.25 + * Return value: The error quark used for libxexpr parser errors.
20.26 + */
20.27 +GQuark xexpr_parse_error_quark(void)
20.28 +{
20.29 + static GQuark quark;
20.30 + if (!quark)
20.31 + quark=g_quark_from_static_string("xexpr_parse_error");
20.32 + return quark;
20.33 +}
20.34 +
20.35 +gboolean _xexpr_validate_id(const char *id,GError **err)
20.36 +{
20.37 + int i;
20.38 + for(i=0;id[i];i++)
20.39 + if (!g_ascii_isalpha(id[i]) && id[i]!='-' && id[i]!='.')
20.40 + {
20.41 + g_set_error(err,XEXPR_PARSE_ERROR,XEXPR_PARSE_ERROR_FAILED,
20.42 + "Invalid XEXPR ID: \"%s\"",id);
20.43 + return FALSE;
20.44 + }
20.45 + return TRUE;
20.46 +}
20.47 +
20.48 +static gboolean xexpr_parse_pcdata(Xexpr *xexpr,xmlNode *node,xmlChar *pcdata,
20.49 + GError **err)
20.50 +{
20.51 + int n;
20.52 + const char *s,*t;
20.53 + xmlChar *text;
20.54 + gchar *str;
20.55 + gboolean is_integer;
20.56 + long long int integer;
20.57 + double number;
20.58 + s=(const char *)pcdata;
20.59 + if (node->type==XML_TEXT_NODE &&
20.60 + (!node->prev || node->prev->type!=XML_TEXT_NODE))
20.61 + while(g_ascii_isspace(*s))
20.62 + s++;
20.63 + while(*s)
20.64 + {
20.65 + t=strpbrk(s,"+-0123456789");
20.66 + /* All numbers start with [+-]?[0-9] (possibly with leading WS) */
20.67 + if (t && (t[0]!='+' && t[0]!='-' || t[1]!='+' && t[1]!='-'))
20.68 + {
20.69 + while(t>s && g_ascii_isspace(t[-1]))
20.70 + t--;
20.71 + if (t>s)
20.72 + xexpr->constants=g_slist_prepend(xexpr->constants,
20.73 + xexpr_new_string(s,t-s));
20.74 + s=t;
20.75 + while(g_ascii_isspace(*s))
20.76 + s++;
20.77 + if (*s=='+' || *s=='-')
20.78 + s++;
20.79 + if (s[0]=='0' && s[1]=='x' &&
20.80 + (n=strspn(s+2,"0123456789ABCDEFabcdef"))>0)
20.81 + {
20.82 + s+=2+n;
20.83 + is_integer=TRUE;
20.84 + }
20.85 + else
20.86 + {
20.87 + s+=strspn(s,"0123456789");
20.88 + if (*s=='.' && (n=strspn(s+1,"0123456789"))>0)
20.89 + {
20.90 + s+=1+n;
20.91 + if ((s[0]=='e' || s[0]=='E') && (s[1]=='+' || s[1]=='-') &&
20.92 + (n=strspn(s+2,"0123456789"))>0)
20.93 + s+=2+n;
20.94 + is_integer=FALSE;
20.95 + }
20.96 + else
20.97 + is_integer=TRUE;
20.98 + }
20.99 + while(g_ascii_isspace(*s))
20.100 + s++;
20.101 + str=g_strndup(t,s-t);
20.102 + if (is_integer)
20.103 + {
20.104 + integer=g_ascii_strtoll(str,NULL,0);
20.105 + if (integer==LLONG_MIN || integer==LLONG_MAX)
20.106 + {
20.107 + text=xmlGetNodePath(node);
20.108 + g_set_error(err,XEXPR_PARSE_ERROR,XEXPR_PARSE_ERROR_FAILED,
20.109 + "Integer overflow on %s at %s",str,(const char *)text);
20.110 + xmlFree(text);
20.111 + g_free(str);
20.112 + return FALSE;
20.113 + }
20.114 + else
20.115 + xexpr->constants=g_slist_prepend(xexpr->constants,
20.116 + xexpr_new_integer(integer));
20.117 + }
20.118 + else
20.119 + {
20.120 + number=g_ascii_strtod(str,NULL);
20.121 + if (number==HUGE_VAL || number==-HUGE_VAL)
20.122 + {
20.123 + text=xmlGetNodePath(node);
20.124 + g_set_error(err,XEXPR_PARSE_ERROR,XEXPR_PARSE_ERROR_FAILED,
20.125 + "Numeric overflow on %s at %s",str,(const char *)text);
20.126 + xmlFree(text);
20.127 + g_free(str);
20.128 + return FALSE;
20.129 + }
20.130 + else
20.131 + xexpr->constants=g_slist_prepend(xexpr->constants,
20.132 + xexpr_new_number(number));
20.133 + }
20.134 + g_free(str);
20.135 + }
20.136 + else
20.137 + {
20.138 + n=strlen(s);
20.139 + if (node->type==XML_TEXT_NODE &&
20.140 + (!node->next || node->next->type!=XML_TEXT_NODE))
20.141 + while(n && g_ascii_isspace(s[n-1]))
20.142 + n--;
20.143 + xexpr->constants=g_slist_prepend(xexpr->constants,
20.144 + xexpr_new_string(s,n));
20.145 + break;
20.146 + }
20.147 + }
20.148 + return TRUE;
20.149 +}
20.150 +
20.151 +static gboolean xexpr_parse_string(Xexpr *xexpr,xmlNode *xml,GError **err)
20.152 +{
20.153 + xmlNode *node;
20.154 + xmlChar *text;
20.155 + GString *str=g_string_new(NULL);
20.156 + for(node=xml;node;node=node->next)
20.157 + {
20.158 + if (node->type==XML_ELEMENT_NODE)
20.159 + {
20.160 + text=xmlGetNodePath(node);
20.161 + g_set_error(err,XEXPR_PARSE_ERROR,XEXPR_PARSE_ERROR_FAILED,
20.162 + "No markup can occur within <string> at %s",(const char *)text);
20.163 + xmlFree(text);
20.164 + return FALSE;
20.165 + }
20.166 + else if (node->type==XML_TEXT_NODE)
20.167 + g_string_append(str,(const char *)node->content);
20.168 + else if (node->type!=XML_COMMENT_NODE)
20.169 + {
20.170 + text=xmlGetNodePath(node);
20.171 + g_set_error(err,XEXPR_PARSE_ERROR,XEXPR_PARSE_ERROR_FAILED,
20.172 + "Unexpected node type %d at %s",node->type,(const char *)text);
20.173 + xmlFree(text);
20.174 + return FALSE;
20.175 + }
20.176 + }
20.177 + xexpr->constants=g_slist_append(xexpr->constants,
20.178 + xexpr_new_string_take_ownership(g_string_free(str,FALSE)));
20.179 + return TRUE;
20.180 +}
20.181 +
20.182 +/**
20.183 + * xexpr_parse_node:
20.184 + * @xexpr: an #Xexpr
20.185 + * @node: the #xmlNode to parse
20.186 + * @err: (allow-none): location to store error, or %NULL.
20.187 + *
20.188 + * Parse an XEXPR expression whose root is @node.
20.189 + *
20.190 + * Typical usage of this function might be:
20.191 + * |[
20.192 + * doc=xmlReadFile(filename,NULL,0);
20.193 + * if (doc && !xexpr_parse_node(xexpr,xmlDocGetRootElement(doc),&err))
20.194 + * {
20.195 + * fprintf(stderr,"%s: %s\n",filename,err->message);
20.196 + * exit(1);
20.197 + * }
20.198 + * ]|
20.199 + *
20.200 + * Return value: %TRUE if @node was successfully parsed.
20.201 + */
20.202 +gboolean xexpr_parse_node(Xexpr *xexpr,xmlNode *node,GError **err)
20.203 +{
20.204 + XexprConstant *constant;
20.205 + XexprBinding *binding;
20.206 + Xexpr *sub,*binding_xexpr;
20.207 + xmlAttr *attr;
20.208 + xmlChar *prop;
20.209 + GSList *bindings;
20.210 + char *ns;
20.211 + sub=xexpr_sub(xexpr);
20.212 + if (!strcmp((const char *)node->name,"string"))
20.213 + {
20.214 + if (!xexpr_parse_string(sub,node->children,err))
20.215 + {
20.216 + xexpr_free(sub);
20.217 + return FALSE;
20.218 + }
20.219 + }
20.220 + else if (!_xexpr_validate_id((const char *)node->name,err) ||
20.221 + !xexpr_parse_fragment(sub,node->children,err))
20.222 + {
20.223 + xexpr_free(sub);
20.224 + return FALSE;
20.225 + }
20.226 + bindings=NULL;
20.227 + for(attr=node->properties;attr;attr=attr->next)
20.228 + {
20.229 + if (!_xexpr_validate_id((const char *)attr->name,err))
20.230 + {
20.231 + g_slist_foreach(bindings,(GFunc)xexpr_binding_free,NULL);
20.232 + g_slist_free(bindings);
20.233 + xexpr_free(sub);
20.234 + return FALSE;
20.235 + }
20.236 + prop=xmlGetProp(node,attr->name);
20.237 + binding_xexpr=xexpr_sub(xexpr);
20.238 + if (!xexpr_parse_pcdata(binding_xexpr,(xmlNode *)attr,prop,err))
20.239 + {
20.240 + xmlFree(prop);
20.241 + g_slist_foreach(bindings,(GFunc)xexpr_binding_free,NULL);
20.242 + g_slist_free(bindings);
20.243 + xexpr_free(binding_xexpr);
20.244 + xexpr_free(sub);
20.245 + return FALSE;
20.246 + }
20.247 + binding=g_slice_new(XexprBinding);
20.248 + binding->id=g_strdup((const char *)attr->name);
20.249 + if (!binding_xexpr->constants || binding_xexpr->constants->next)
20.250 + binding->value=xexpr_new_string((const char *)prop,-1);
20.251 + else
20.252 + {
20.253 + binding->value=binding_xexpr->constants->data;
20.254 + g_slist_free(binding_xexpr->constants);
20.255 + binding_xexpr->constants=NULL;
20.256 + }
20.257 + xexpr_free(binding_xexpr);
20.258 + xmlFree(prop);
20.259 + bindings=g_slist_prepend(bindings,binding);
20.260 + }
20.261 + bindings=g_slist_reverse(bindings);
20.262 + if (node->ns)
20.263 + ns=g_strdup((const char *)node->ns->href);
20.264 + else
20.265 + ns=NULL;
20.266 + constant=xexpr_new_invocation_take_ownership(ns,
20.267 + g_strdup((const char *)node->name),bindings,sub->constants);
20.268 + sub->constants=NULL;
20.269 + xexpr_free(sub);
20.270 + xexpr->constants=g_slist_prepend(xexpr->constants,constant);
20.271 + return TRUE;
20.272 +}
20.273 +
20.274 +/**
20.275 + * xexpr_parse_fragment:
20.276 + * @xexpr: an #Xexpr
20.277 + * @xml: the first #xmlNode to parse
20.278 + * @err: (allow-none): location to store error, or %NULL.
20.279 + *
20.280 + * Parse an XEXPR expression consisting of @xml and its siblings.
20.281 + *
20.282 + * Typical usage of this function might be:
20.283 + * |[
20.284 + * xpathObj=xmlXPathEvalExpression(BAD_CAST "//params/setting",xpathCtx);
20.285 + * xml=xpathObj?xpathObj->nodesetval->nodeTab[0]:NULL;
20.286 + * if (xml && !xexpr_parse_fragment(xexpr,xml->children,&err))
20.287 + * {
20.288 + * fprintf(stderr,"%s: %s\n",filename,err->message);
20.289 + * exit(1);
20.290 + * }
20.291 + * ]|
20.292 + *
20.293 + * Return value: %TRUE if @xml was successfully parsed.
20.294 + */
20.295 +gboolean xexpr_parse_fragment(Xexpr *xexpr,xmlNode *xml,GError **err)
20.296 +{
20.297 + xmlNode *node;
20.298 + xmlChar *text;
20.299 + xexpr->constants=g_slist_reverse(xexpr->constants);
20.300 + for(node=xml;node;node=node->next)
20.301 + {
20.302 + if (node->type==XML_ELEMENT_NODE)
20.303 + {
20.304 + if (!xexpr_parse_node(xexpr,node,err))
20.305 + return FALSE;
20.306 + }
20.307 + else if (node->type==XML_TEXT_NODE)
20.308 + {
20.309 + if (!xexpr_parse_pcdata(xexpr,node,node->content,err))
20.310 + return FALSE;
20.311 + }
20.312 + else if (node->type!=XML_COMMENT_NODE)
20.313 + {
20.314 + text=xmlGetNodePath(node);
20.315 + g_set_error(err,XEXPR_PARSE_ERROR,XEXPR_PARSE_ERROR_FAILED,
20.316 + "Unexpected node type %d at %s",node->type,(const char *)text);
20.317 + xmlFree(text);
20.318 + return FALSE;
20.319 + }
20.320 + }
20.321 + xexpr->constants=g_slist_reverse(xexpr->constants);
20.322 + return TRUE;
20.323 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/libxexpr/xexprparse.h Wed Oct 10 22:58:21 2012 +0100
21.3 @@ -0,0 +1,34 @@
21.4 +#ifndef __XEXPER_PARSE_H__
21.5 +#define __XEXPER_PARSE_H__
21.6 +
21.7 +#include <glib.h>
21.8 +#include <libxml/tree.h>
21.9 +#include "xexprtypes.h"
21.10 +
21.11 +G_BEGIN_DECLS
21.12 +
21.13 +/**
21.14 + * XEXPR_PARSE_ERROR:
21.15 + *
21.16 + * Used to get the #GError quark for libxexpr parser errors.
21.17 + */
21.18 +#define XEXPR_PARSE_ERROR xexpr_parse_error_quark()
21.19 +
21.20 +/**
21.21 + * XexprParseError:
21.22 + * @XEXPR_PARSE_ERROR_FAILED: Indicates a generic failure.
21.23 + *
21.24 + * Enum values for parser errors.
21.25 + */
21.26 +typedef enum
21.27 +{
21.28 + XEXPR_PARSE_ERROR_FAILED
21.29 +} XexprParseError;
21.30 +
21.31 +GQuark xexpr_parse_error_quark(void);
21.32 +gboolean xexpr_parse_fragment(Xexpr *xexpr,xmlNode *xml,GError **err);
21.33 +gboolean xexpr_parse_node(Xexpr *xexpr,xmlNode *node,GError **err);
21.34 +
21.35 +G_END_DECLS
21.36 +
21.37 +#endif /* __XEXPER_PARSE_H__ */
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/libxexpr/xexprprivate.h Wed Oct 10 22:58:21 2012 +0100
22.3 @@ -0,0 +1,5 @@
22.4 +gboolean _xexpr_validate_id(const char *id,GError **err);
22.5 +void _xexpr_push_environment(Xexpr *xexpr,const char *id);
22.6 +void _xexpr_pop_environment(Xexpr *xexpr);
22.7 +XexprConstant *_xexpr_libxexpr_function_evaluate(Xexpr *xexpr,const char *ns,
22.8 + const char *id,GSList *bindings,GSList *args,GError **err);
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/libxexpr/xexprtypes.c Wed Oct 10 22:58:21 2012 +0100
23.3 @@ -0,0 +1,705 @@
23.4 +#include <stdlib.h>
23.5 +#include <string.h>
23.6 +#include <math.h>
23.7 +#include <xexpr.h>
23.8 +#include "xexprprivate.h"
23.9 +
23.10 +/**
23.11 + * SECTION:xexprtypes
23.12 + * @short_description: Types defined in libxexpr
23.13 + * @stability: Stable
23.14 + * @include: libxexpr/xexpr.h
23.15 + *
23.16 + * The various types defined in libxexpr and the functions that support them.
23.17 + */
23.18 +
23.19 +static XexprEnvironment *xexpr_environment_new(const char *function,
23.20 + XexprEnvironment *outer);
23.21 +
23.22 +/**
23.23 + * xexpr_binding_free:
23.24 + * @binding: an #XexprBinding
23.25 + *
23.26 + * Frees the memory allocated for the #XexprBinding.
23.27 + */
23.28 +void xexpr_binding_free(XexprBinding *binding)
23.29 +{
23.30 + g_free(binding->id);
23.31 + xexpr_constant_free(binding->value);
23.32 + g_slice_free(XexprBinding,binding);
23.33 +}
23.34 +
23.35 +/**
23.36 + * xexpr_environment_free:
23.37 + * @environment: an #XexprEnvironment
23.38 + *
23.39 + * Frees the memory allocated for the #XexprEnvironment.
23.40 + */
23.41 +static void xexpr_environment_free(XexprEnvironment *environment)
23.42 +{
23.43 + g_warn_if_fail(environment->refcount==1);
23.44 + if (environment->outer)
23.45 + environment->outer->refcount--;
23.46 + g_free(environment->function);
23.47 + g_slist_foreach(environment->bindings,(GFunc)xexpr_binding_free,NULL);
23.48 + g_slist_free(environment->bindings);
23.49 + g_slice_free(XexprEnvironment,environment);
23.50 +}
23.51 +
23.52 +/*
23.53 + * xexpr_invocation_free:
23.54 + * @invocation: an #XexprInvocation
23.55 + *
23.56 + * Frees the memory allocated for the #XexprInvocation.
23.57 + */
23.58 +static void xexpr_invocation_free(XexprInvocation *invocation)
23.59 +{
23.60 + g_free(invocation->function);
23.61 + g_slist_foreach(invocation->bindings,(GFunc)xexpr_binding_free,NULL);
23.62 + g_slist_free(invocation->bindings);
23.63 + g_slist_foreach(invocation->constants,(GFunc)xexpr_constant_free,NULL);
23.64 + g_slist_free(invocation->constants);
23.65 + g_slice_free(XexprInvocation,invocation);
23.66 +}
23.67 +
23.68 +/*
23.69 + * xexpr_function_free:
23.70 + * @function: an #XexprFunction
23.71 + *
23.72 + * Frees the memory allocated for the #XexprFunction.
23.73 + */
23.74 +static void xexpr_function_free(XexprFunction *function)
23.75 +{
23.76 + g_slist_foreach(function->args,(GFunc)g_free,NULL);
23.77 + g_slist_free(function->args);
23.78 + g_slist_foreach(function->constants,(GFunc)xexpr_constant_free,NULL);
23.79 + g_slist_free(function->constants);
23.80 + g_slice_free(XexprFunction,function);
23.81 +}
23.82 +
23.83 +/**
23.84 + * xexpr_constant_free:
23.85 + * @constant: an #XexprConstant
23.86 + *
23.87 + * Frees the memory allocated for the #XexprConstant.
23.88 + */
23.89 +void xexpr_constant_free(XexprConstant *constant)
23.90 +{
23.91 + switch(constant->type)
23.92 + {
23.93 + case XEXPR_TYPE_INVOCATION:
23.94 + xexpr_invocation_free(constant->u.invocation);
23.95 + break;
23.96 + case XEXPR_TYPE_FUNCTION:
23.97 + xexpr_function_free(constant->u.function);
23.98 + break;
23.99 + case XEXPR_TYPE_STRING:
23.100 + g_free(constant->u.string);
23.101 + break;
23.102 + case XEXPR_TYPE_INTEGER:
23.103 + case XEXPR_TYPE_NUMBER:
23.104 + break;
23.105 + }
23.106 + g_slice_free(XexprConstant,constant);
23.107 +}
23.108 +
23.109 +/**
23.110 + * xexpr_free:
23.111 + * @xexpr: an #Xexpr
23.112 + *
23.113 + * Frees the memory allocated for the #Xexpr.
23.114 + */
23.115 +void xexpr_free(Xexpr *xexpr)
23.116 +{
23.117 + g_slist_foreach(xexpr->tracing,(GFunc)g_free,NULL);
23.118 + g_slist_free(xexpr->tracing);
23.119 + g_slist_foreach(xexpr->constants,(GFunc)xexpr_constant_free,NULL);
23.120 + g_slist_free(xexpr->constants);
23.121 + g_slice_free(Xexpr,xexpr);
23.122 +}
23.123 +
23.124 +/**
23.125 + * xexpr_new:
23.126 + *
23.127 + * Creates a new #Xexpr.
23.128 + *
23.129 + * Returns: the new #Xexpr
23.130 + */
23.131 +Xexpr *xexpr_new(void)
23.132 +{
23.133 + xexpr_register_extension(NULL);
23.134 + return g_slice_new0(Xexpr);
23.135 +}
23.136 +
23.137 +/**
23.138 + * xexpr_sub:
23.139 + * @xexpr: an #Xexpr to copy the initial options from
23.140 + *
23.141 + * Creates a new #Xexpr, copying options from @xexpr.
23.142 + *
23.143 + * Returns: the new #Xexpr
23.144 + */
23.145 +Xexpr *xexpr_sub(Xexpr *xexpr)
23.146 +{
23.147 + GSList *lnk;
23.148 + Xexpr *sub=xexpr_new();
23.149 + sub->tracing=g_slist_copy(xexpr->tracing);
23.150 + for(lnk=sub->tracing;lnk;lnk=lnk->next)
23.151 + lnk->data=g_strdup(lnk->data);
23.152 + return sub;
23.153 +}
23.154 +
23.155 +/**
23.156 + * xexpr_is_tracing:
23.157 + * @xexpr: an #Xexpr
23.158 + * @id: the symbol to test for
23.159 + *
23.160 + * Checks if a symbol is currently being traced, returning %TRUE if it is.
23.161 + *
23.162 + * Returns: %TRUE if @id is being traced
23.163 + */
23.164 +gboolean xexpr_is_tracing(Xexpr *xexpr,const char *id)
23.165 +{
23.166 + return !!g_slist_find_custom(xexpr->tracing,id,(GCompareFunc)g_strcmp0);
23.167 +}
23.168 +
23.169 +/**
23.170 + * xexpr_start_tracing:
23.171 + * @xexpr: an #Xexpr
23.172 + * @id: the symbol to trace
23.173 + *
23.174 + * Adds @id to the set of symbols to trace.
23.175 + *
23.176 + * When variables with the name of a traced symbol are created or changed,
23.177 + * the evaluator will output a suitable tracing message and a stack dump.
23.178 + *
23.179 + * <example>
23.180 + * <title>Example Tracing Output</title>
23.181 + * <screen>
23.182 + * Created new variable x in frame \#0
23.183 + * \#0 test1Â (x = <nil/>)
23.184 + * \#1 eq ()
23.185 + * \#2 if ()
23.186 + * \#3 and ()
23.187 + * \#4 expr ()
23.188 + *
23.189 + * Set variable x
23.190 + * \#0 test1Â (x = <integer>1</integer>)
23.191 + * \#1 eq ()
23.192 + * \#2 if ()
23.193 + * \#3 and ()
23.194 + * \#4 expr ()
23.195 + * </screen>
23.196 + * </example>
23.197 + */
23.198 +void xexpr_start_tracing(Xexpr *xexpr,const char *id)
23.199 +{
23.200 + if (!xexpr_is_tracing(xexpr,id))
23.201 + xexpr->tracing=g_slist_prepend(xexpr->tracing,g_strdup(id));
23.202 +}
23.203 +
23.204 +/**
23.205 + * xexpr_get_environment:
23.206 + * @xexpr: an #Xexpr
23.207 + *
23.208 + * Gets the #XexprEnvironment of the given #Xexpr.
23.209 + *
23.210 + * Returns: (transfer none): the innermost environment
23.211 + */
23.212 +XexprEnvironment *xexpr_get_environment(Xexpr *xexpr)
23.213 +{
23.214 + if (!xexpr->environment)
23.215 + xexpr->environment=xexpr_environment_new(NULL,NULL);
23.216 + return xexpr->environment;
23.217 +}
23.218 +
23.219 +/**
23.220 + * xexpr_set_constants_take_ownership:
23.221 + * @xexpr: an #Xexpr
23.222 + * @constants: (transfer full) (element-type XexprConstant): A list of
23.223 + * constants to use, replacing any existing constants
23.224 + *
23.225 + * Sets the list of constants which make up the expression.
23.226 + */
23.227 +void xexpr_set_constants_take_ownership(Xexpr *xexpr,GSList *constants)
23.228 +{
23.229 + g_slist_foreach(xexpr->constants,(GFunc)xexpr_constant_free,NULL);
23.230 + g_slist_free(xexpr->constants);
23.231 + xexpr->constants=constants;
23.232 +}
23.233 +
23.234 +/**
23.235 + * xexpr_set_constants:
23.236 + * @xexpr: an #Xexpr
23.237 + * @constants: (transfer none) (element-type XexprConstant): A list of
23.238 + * constants to use, replacing any existing constants
23.239 + *
23.240 + * Sets the list of constants which make up the expression.
23.241 + */
23.242 +void xexpr_set_constants(Xexpr *xexpr,GSList *constants)
23.243 +{
23.244 + GSList *lnk,*copy=NULL;
23.245 + for(lnk=constants;lnk;lnk=lnk->next)
23.246 + copy=g_slist_prepend(copy,xexpr_constant_dup(lnk->data));
23.247 + copy=g_slist_reverse(copy);
23.248 + xexpr_set_constants_take_ownership(xexpr,copy);
23.249 +}
23.250 +
23.251 +void _xexpr_push_environment(Xexpr *xexpr,const char *id)
23.252 +{
23.253 + xexpr->environment=xexpr_environment_new(id,xexpr_get_environment(xexpr));
23.254 +}
23.255 +
23.256 +void _xexpr_pop_environment(Xexpr *xexpr)
23.257 +{
23.258 + XexprEnvironment *outer=xexpr->environment->outer;
23.259 + if (outer)
23.260 + {
23.261 + xexpr_environment_free(xexpr->environment);
23.262 + xexpr->environment=outer;
23.263 + }
23.264 +}
23.265 +
23.266 +/**
23.267 + * xexpr_new_invocation_take_ownership:
23.268 + * @ns: (transfer full): the namespace to which @function belongs, or %NULL
23.269 + * @function: (transfer full): the name of the function to be invoked
23.270 + * @bindings: (transfer full) (element-type XexprBinding): the pre-bound
23.271 + * arguments
23.272 + * @constants: (transfer full) (element-type XexprConstant): the other
23.273 + * arguments
23.274 + *
23.275 + * Create a new #XexprConstant that invokes @function with pre-bound arguments
23.276 + * @bindings and with @constants as further arguments. Functions with named
23.277 + * parameters will use the pre-bound arguments first if present, otherwise
23.278 + * the other arguments will be bound to the unbound parameters as needed.
23.279 + *
23.280 + * @ns should be %NULL, the empty string or %XEXPR_NS for XEXPR functions.
23.281 + *
23.282 + * Returns: (transfer full): the new #XexprConstant
23.283 + */
23.284 +XexprConstant *xexpr_new_invocation_take_ownership(char *ns,char *function,
23.285 + GSList *bindings,GSList *constants)
23.286 +{
23.287 + XexprConstant *constant;
23.288 + constant=g_slice_new(XexprConstant);
23.289 + constant->type=XEXPR_TYPE_INVOCATION;
23.290 + constant->u.invocation=g_slice_new(XexprInvocation);
23.291 + if (ns && (!*ns || !strcmp(ns,XEXPR_NS)))
23.292 + {
23.293 + g_free(ns);
23.294 + ns=NULL;
23.295 + }
23.296 + constant->u.invocation->ns=ns;
23.297 + constant->u.invocation->function=function;
23.298 + constant->u.invocation->bindings=bindings;
23.299 + constant->u.invocation->constants=constants;
23.300 + return constant;
23.301 +}
23.302 +
23.303 +/**
23.304 + * xexpr_new_invocation:
23.305 + * @ns: (transfer none): the namespace to which @function belongs, or %NULL
23.306 + * @function: (transfer none): the name of the function to be invoked
23.307 + * @bindings: (transfer none) (element-type XexprBinding): the pre-bound
23.308 + * arguments
23.309 + * @constants: (transfer none) (element-type XexprConstant): the other
23.310 + * arguments
23.311 + *
23.312 + * Create a new #XexprConstant that invokes @function with pre-bound arguments
23.313 + * @bindings and with @constants as further arguments. Functions with named
23.314 + * parameters will use the pre-bound arguments first if present, otherwise
23.315 + * the other arguments will be bound to the unbound parameters as needed.
23.316 + *
23.317 + * @ns should be %NULL, the empty string or %XEXPR_NS for XEXPR functions.
23.318 + *
23.319 + * Returns: (transfer full): the new #XexprConstant
23.320 + */
23.321 +XexprConstant *xexpr_new_invocation(const char *ns,const char *function,
23.322 + GSList *bindings,GSList *constants)
23.323 +{
23.324 + GSList *list,*lnk;
23.325 + list=g_slist_copy(constants);
23.326 + for(lnk=list;lnk;lnk=lnk->next)
23.327 + lnk->data=xexpr_constant_dup(lnk->data);
23.328 + if (ns && (!*ns || !strcmp(ns,XEXPR_NS)))
23.329 + ns=NULL;
23.330 + return xexpr_new_invocation_take_ownership(g_strdup(ns),g_strdup(function),
23.331 + xexpr_bindings_dup(bindings),list);
23.332 +}
23.333 +
23.334 +/**
23.335 + * xexpr_new_function_take_ownership:
23.336 + * @args: (transfer full) (element-type utf8): the parameter names
23.337 + * @constants: (transfer full) (element-type XexprConstant): the constants
23.338 + * which will be evaluated when the function is invoked
23.339 + *
23.340 + * Create a new #XexprConstant that defines an unnamed function. Creating a
23.341 + * function definition is the first step in defining a function. The second
23.342 + * step is to bind the definition to a name, eg., using xexpr_var_new().
23.343 + *
23.344 + * Returns: (transfer full): the new #XexprConstant
23.345 + */
23.346 +XexprConstant *xexpr_new_function_take_ownership(GSList *args,GSList *constants)
23.347 +{
23.348 + XexprConstant *constant;
23.349 + constant=g_slice_new(XexprConstant);
23.350 + constant->type=XEXPR_TYPE_FUNCTION;
23.351 + constant->u.function=g_slice_new(XexprFunction);
23.352 + constant->u.function->args=args;
23.353 + constant->u.function->constants=constants;
23.354 + return constant;
23.355 +}
23.356 +
23.357 +/**
23.358 + * xexpr_new_function:
23.359 + * @args: (transfer none) (element-type utf8): the parameter names
23.360 + * @constants: (transfer none) (element-type XexprConstant): the constants
23.361 + * which will be evaluated when the function is invoked
23.362 + *
23.363 + * Create a new #XexprConstant that defines an unnamed function. Creating a
23.364 + * function definition is the first step in defining a function. The second
23.365 + * step is to bind the definition to a name, eg., using xexpr_var_new().
23.366 + *
23.367 + * Returns: (transfer full): the new #XexprConstant
23.368 + */
23.369 +XexprConstant *xexpr_new_function(GSList *args,GSList *constants)
23.370 +{
23.371 + GSList *lnk;
23.372 + args=g_slist_copy(args);
23.373 + for(lnk=args;lnk;lnk=lnk->next)
23.374 + lnk->data=g_strdup(lnk->data);
23.375 + constants=g_slist_copy(constants);
23.376 + for(lnk=constants;lnk;lnk=lnk->next)
23.377 + lnk->data=xexpr_constant_dup(lnk->data);
23.378 + return xexpr_new_function_take_ownership(args,constants);
23.379 +}
23.380 +
23.381 +/**
23.382 + * xexpr_new_string_take_ownership:
23.383 + * @s: (transfer full): the string
23.384 + *
23.385 + * Create a new #XexprConstant that consists of the given string.
23.386 + *
23.387 + * Returns: (transfer full): the new #XexprConstant
23.388 + */
23.389 +XexprConstant *xexpr_new_string_take_ownership(char *s)
23.390 +{
23.391 + XexprConstant *constant;
23.392 + constant=g_slice_new(XexprConstant);
23.393 + constant->type=XEXPR_TYPE_STRING;
23.394 + constant->u.string=s;
23.395 + return constant;
23.396 +}
23.397 +
23.398 +/**
23.399 + * xexpr_new_string:
23.400 + * @s: (transfer none): the string
23.401 + * @len: length of @s to use, or -1 to treat @s as nul-terminated
23.402 + *
23.403 + * Create a new #XexprConstant that consists of the given string.
23.404 + *
23.405 + * Returns: (transfer full): the new #XexprConstant
23.406 + */
23.407 +XexprConstant *xexpr_new_string(const char *s,gssize len)
23.408 +{
23.409 + if (len<0)
23.410 + len=strlen(s);
23.411 + return xexpr_new_string_take_ownership(g_strndup(s,len));
23.412 +}
23.413 +
23.414 +/**
23.415 + * xexpr_new_integer:
23.416 + * @integer: the integer
23.417 + *
23.418 + * Create a new #XexprConstant that consists of the given integer.
23.419 + *
23.420 + * Returns: (transfer full): the new #XexprConstant
23.421 + */
23.422 +XexprConstant *xexpr_new_integer(long long int integer)
23.423 +{
23.424 + XexprConstant *constant;
23.425 + constant=g_slice_new(XexprConstant);
23.426 + constant->type=XEXPR_TYPE_INTEGER;
23.427 + constant->u.integer=integer;
23.428 + return constant;
23.429 +}
23.430 +
23.431 +/**
23.432 + * xexpr_new_number:
23.433 + * @number: the number
23.434 + *
23.435 + * Create a new #XexprConstant that consists of the given floating-point number.
23.436 + *
23.437 + * Returns: (transfer full): the new #XexprConstant
23.438 + */
23.439 +XexprConstant *xexpr_new_number(double number)
23.440 +{
23.441 + XexprConstant *constant;
23.442 + constant=g_slice_new(XexprConstant);
23.443 + constant->type=XEXPR_TYPE_NUMBER;
23.444 + constant->u.number=number;
23.445 + return constant;
23.446 +}
23.447 +
23.448 +static XexprEnvironment *xexpr_environment_new(const char *function,
23.449 + XexprEnvironment *outer)
23.450 +{
23.451 + XexprEnvironment *environment=g_slice_new0(XexprEnvironment);
23.452 + environment->function=g_strdup(function);
23.453 + environment->refcount=1;
23.454 + environment->outer=outer;
23.455 + if (outer)
23.456 + outer->refcount++;
23.457 + return environment;
23.458 +}
23.459 +
23.460 +/**
23.461 + * xexpr_environment_foreach:
23.462 + * @environment: an #XexprEnvironment
23.463 + * @func: the function to call with each active variable
23.464 + * @user_data: user data to pass to the function
23.465 + *
23.466 + * Calls a function for each active variable in an #XexprEnvironment.
23.467 + */
23.468 +void xexpr_environment_foreach(XexprEnvironment *environment,GTraverseFunc func,
23.469 + gpointer user_data)
23.470 +{
23.471 + GSList *lnk;
23.472 + GSList *environments=NULL;
23.473 + GTree *active;
23.474 + XexprBinding *binding;
23.475 + while(environment)
23.476 + {
23.477 + environments=g_slist_prepend(environments,environment);
23.478 + environment=environment->outer;
23.479 + }
23.480 + active=g_tree_new((GCompareFunc)strcmp);
23.481 + while(environments)
23.482 + {
23.483 + environment=environments->data;
23.484 + environments=g_slist_delete_link(environments,environments);
23.485 + for(lnk=environment->bindings;lnk;lnk=lnk->next)
23.486 + {
23.487 + binding=lnk->data;
23.488 + g_tree_insert(active,binding->id,binding->value);
23.489 + }
23.490 + }
23.491 + g_tree_foreach(active,func,user_data);
23.492 + g_tree_destroy(active);
23.493 +}
23.494 +
23.495 +/**
23.496 + * xexpr_bindings_get:
23.497 + * @bindings: (transfer none) (element-type XexprBinding): the bindings to
23.498 + * search
23.499 + * @id: the symbol to search for
23.500 + *
23.501 + * Look for a binding of symbol @id in @bindings and return the value if
23.502 + * found.
23.503 + *
23.504 + * Returns: (transfer none): the found #XexprConstant or %NULL
23.505 + */
23.506 +XexprConstant *xexpr_bindings_get(GSList *bindings,const char *id)
23.507 +{
23.508 + GSList *lnk;
23.509 + XexprBinding *binding;
23.510 + for(lnk=bindings;lnk;lnk=lnk->next)
23.511 + {
23.512 + binding=lnk->data;
23.513 + if (!strcmp(binding->id,id))
23.514 + return binding->value;
23.515 + }
23.516 + return NULL;
23.517 +}
23.518 +
23.519 +/**
23.520 + * xexpr_bindings_set:
23.521 + * @bindings: (transfer none) (element-type XexprBinding): the bindings to
23.522 + * update
23.523 + * @id: an existing symbol to set
23.524 + * @value: (transfer none): the new value
23.525 + *
23.526 + * Update an existing binding of symbol @id in @bindings with the new value
23.527 + * @value. If no existing binding is found, return %FALSE.
23.528 + *
23.529 + * Returns: %TRUE if @id was found and updated
23.530 + */
23.531 +gboolean xexpr_bindings_set(GSList *bindings,const char *id,
23.532 + XexprConstant *value)
23.533 +{
23.534 + GSList *lnk;
23.535 + XexprBinding *binding;
23.536 + for(lnk=bindings;lnk;lnk=lnk->next)
23.537 + {
23.538 + binding=lnk->data;
23.539 + if (!strcmp(binding->id,id))
23.540 + {
23.541 + xexpr_constant_free(binding->value);
23.542 + binding->value=xexpr_constant_dup(value);
23.543 + return TRUE;
23.544 + }
23.545 + }
23.546 + return FALSE;
23.547 +}
23.548 +
23.549 +/**
23.550 + * xexpr_bindings_new:
23.551 + * @bindings: (transfer full) (element-type XexprBinding): the bindings to
23.552 + * modify
23.553 + * @id: a symbol to set or create
23.554 + * @value: (transfer none): the new value
23.555 + *
23.556 + * Update an existing binding of symbol @id or create a new one in @bindings
23.557 + * with the new value @value.
23.558 + *
23.559 + * Returns: (transfer full) (element-type XexprBinding): the new bindings list
23.560 + */
23.561 +GSList *xexpr_bindings_new(GSList *bindings,const char *id,XexprConstant *value)
23.562 +{
23.563 + XexprBinding *binding;
23.564 + if (!xexpr_bindings_set(bindings,id,value))
23.565 + {
23.566 + binding=g_slice_new(XexprBinding);
23.567 + binding->id=g_strdup(id);
23.568 + binding->value=xexpr_constant_dup(value);
23.569 + bindings=g_slist_prepend(bindings,binding);
23.570 + }
23.571 + return bindings;
23.572 +}
23.573 +
23.574 +/**
23.575 + * xexpr_var_get:
23.576 + * @xexpr: an #Xexpr
23.577 + * @id: a symbol to look up
23.578 + *
23.579 + * Look for a definition of symbol @id in @xexpr and return its value. If
23.580 + * no definition exists, return %NULL.
23.581 + *
23.582 + * Returns: (transfer none): the bound value, or %NULL if not found.
23.583 + */
23.584 +XexprConstant *xexpr_var_get(Xexpr *xexpr,const char *id)
23.585 +{
23.586 + XexprConstant *value=NULL;
23.587 + XexprEnvironment *environment=xexpr_get_environment(xexpr);
23.588 + while(environment && !value)
23.589 + {
23.590 + value=xexpr_bindings_get(environment->bindings,id);
23.591 + environment=environment->outer;
23.592 + }
23.593 + return value;
23.594 +}
23.595 +
23.596 +/**
23.597 + * xexpr_var_new:
23.598 + * @xexpr: an #Xexpr
23.599 + * @id: a symbol to set or create
23.600 + * @value: (transfer none): the new value
23.601 + *
23.602 + * Update an existing binding of symbol @id in the innermost environment of
23.603 + * @xexpr or create a new one with the new value @value.
23.604 + */
23.605 +void xexpr_var_new(Xexpr *xexpr,const char *id,XexprConstant *value)
23.606 +{
23.607 + XexprEnvironment *environment=xexpr_get_environment(xexpr);
23.608 + environment->bindings=xexpr_bindings_new(environment->bindings,id,value);
23.609 + if (xexpr_is_tracing(xexpr,id))
23.610 + {
23.611 + printf("\nCreated new variable %s in frame #0\n",id);
23.612 + xexpr_stack_dump(xexpr,stdout);
23.613 + }
23.614 +}
23.615 +
23.616 +/**
23.617 + * xexpr_var_set:
23.618 + * @xexpr: an #Xexpr
23.619 + * @id: a symbol to set or create
23.620 + * @value: (transfer none): the new value
23.621 + *
23.622 + * Update the active binding of symbol @id in @xexpr if such exists or create
23.623 + * create a new one in the outermost environment with the new value @value.
23.624 + */
23.625 +void xexpr_var_set(Xexpr *xexpr,const char *id,XexprConstant *value)
23.626 +{
23.627 + XexprEnvironment *environment=xexpr_get_environment(xexpr);
23.628 + while(environment)
23.629 + {
23.630 + if (xexpr_bindings_set(environment->bindings,id,value))
23.631 + {
23.632 + if (xexpr_is_tracing(xexpr,id))
23.633 + {
23.634 + printf("\nSet variable %s\n",id);
23.635 + xexpr_stack_dump(xexpr,stdout);
23.636 + }
23.637 + return;
23.638 + }
23.639 + if (environment->outer)
23.640 + environment=environment->outer;
23.641 + else
23.642 + break;
23.643 + }
23.644 + environment->bindings=xexpr_bindings_new(environment->bindings,id,value);
23.645 + if (xexpr_is_tracing(xexpr,id))
23.646 + {
23.647 + printf("\nCreated new global variable %s\n",id);
23.648 + xexpr_stack_dump(xexpr,stdout);
23.649 + }
23.650 +}
23.651 +
23.652 +/**
23.653 + * xexpr_constant_dup:
23.654 + * @constant: an #XexprConstant to duplicate
23.655 + *
23.656 + * Duplicate @constant.
23.657 + *
23.658 + * Returns: (transfer full): the new #XexprConstant
23.659 + */
23.660 +XexprConstant *xexpr_constant_dup(XexprConstant *constant)
23.661 +{
23.662 + switch(constant->type)
23.663 + {
23.664 + case XEXPR_TYPE_INVOCATION:
23.665 + return xexpr_new_invocation(constant->u.invocation->ns,
23.666 + constant->u.invocation->function,constant->u.invocation->bindings,
23.667 + constant->u.invocation->constants);
23.668 + break;
23.669 + case XEXPR_TYPE_FUNCTION:
23.670 + return xexpr_new_function(constant->u.function->args,
23.671 + constant->u.function->constants);
23.672 + break;
23.673 + case XEXPR_TYPE_STRING:
23.674 + return xexpr_new_string(constant->u.string,-1);
23.675 + break;
23.676 + case XEXPR_TYPE_INTEGER:
23.677 + return xexpr_new_integer(constant->u.integer);
23.678 + break;
23.679 + case XEXPR_TYPE_NUMBER:
23.680 + return xexpr_new_number(constant->u.number);
23.681 + break;
23.682 + }
23.683 + return NULL;
23.684 +}
23.685 +
23.686 +/**
23.687 + * xexpr_bindings_dup:
23.688 + * @bindings: (transfer none) (element-type XexprBinding): a list of bindings
23.689 + * to duplicate
23.690 + *
23.691 + * Duplicate @bindings.
23.692 + *
23.693 + * Returns: (transfer full) (element-type XexprBinging): the new bindings list
23.694 + */
23.695 +GSList *xexpr_bindings_dup(GSList *bindings)
23.696 +{
23.697 + GSList *lnk,*list=NULL;
23.698 + XexprBinding *binding,*dup;
23.699 + for(lnk=bindings;lnk;lnk=lnk->next)
23.700 + {
23.701 + binding=lnk->data;
23.702 + dup=g_slice_new(XexprBinding);
23.703 + dup->id=g_strdup(binding->id);
23.704 + dup->value=xexpr_constant_dup(binding->value);
23.705 + list=g_slist_prepend(list,dup);
23.706 + }
23.707 + return g_slist_reverse(list);
23.708 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/libxexpr/xexprtypes.h Wed Oct 10 22:58:21 2012 +0100
24.3 @@ -0,0 +1,176 @@
24.4 +#ifndef __XEXPER_TYPES_H__
24.5 +#define __XEXPER_TYPES_H__
24.6 +
24.7 +#include <glib.h>
24.8 +#include <libxml/tree.h>
24.9 +
24.10 +G_BEGIN_DECLS
24.11 +
24.12 +/**
24.13 + * XexprInvocation:
24.14 + * @ns: the namespace to which @function belongs, or %NULL
24.15 + * @function: the function to be invoked
24.16 + * @bindings: (element-type XexprBinding): the pre-bound arguments
24.17 + * @constants: (element-type XexprConstant): the other arguments
24.18 + *
24.19 + * A structure describing the invocation of a function.
24.20 + */
24.21 +typedef struct xexpr_invocation {
24.22 + char *ns;
24.23 + char *function;
24.24 + GSList *bindings;
24.25 + GSList *constants;
24.26 +} XexprInvocation;
24.27 +
24.28 +/**
24.29 + * XexprFunction:
24.30 + * @args: (element-type utf8): the parameter names
24.31 + * @constants: (element-type XexprConstant): the constants
24.32 + * which will be evaluated when the function is invoked
24.33 + *
24.34 + * A structure describing the definition of a function.
24.35 + */
24.36 +typedef struct xexpr_function {
24.37 + GSList *args;
24.38 + GSList *constants;
24.39 +} XexprFunction;
24.40 +
24.41 +typedef struct xexpr_constant XexprConstant;
24.42 +
24.43 +/**
24.44 + * XexprBinding:
24.45 + * @id: the bound name
24.46 + * @value: the expresion bound to @id
24.47 + *
24.48 + * A structure describing the binding of a value to a name.
24.49 + */
24.50 +typedef struct xexpr_binding {
24.51 + char *id;
24.52 + XexprConstant *value;
24.53 +} XexprBinding;
24.54 +
24.55 +/**
24.56 + * XexprType:
24.57 + * @XEXPR_TYPE_INVOCATION: a function invocation
24.58 + * @XEXPR_TYPE_FUNCTION: a function definition
24.59 + * @XEXPR_TYPE_STRING: a string
24.60 + * @XEXPR_TYPE_INTEGER: an integer
24.61 + * @XEXPR_TYPE_NUMBER: a floating-point number
24.62 + *
24.63 + * Enum values for the type, to specify the type of expression.
24.64 + */
24.65 +typedef enum {
24.66 + XEXPR_TYPE_INVOCATION=1,
24.67 + XEXPR_TYPE_FUNCTION,
24.68 + XEXPR_TYPE_STRING,
24.69 + XEXPR_TYPE_INTEGER,
24.70 + XEXPR_TYPE_NUMBER
24.71 +} XexprType;
24.72 +
24.73 +/**
24.74 + * XexprConstant:
24.75 + * @type: the type of expression
24.76 + * @u: type-specific parameters
24.77 + *
24.78 + * A structure describing an XEXPR expression
24.79 + */
24.80 +struct xexpr_constant {
24.81 + XexprType type;
24.82 + union {
24.83 + XexprInvocation *invocation;
24.84 + XexprFunction *function;
24.85 + char *string;
24.86 + long long int integer;
24.87 + double number;
24.88 + } u;
24.89 +};
24.90 +
24.91 +/**
24.92 + * XexprEnvironment:
24.93 + * @function: the name of the function to which the environment belongs,
24.94 + * or %NULL if this is the outermost environment
24.95 + * @outer: the next environment in the chain from innermost to outermost,
24.96 + * or %NULL if this is the outermost environment
24.97 + * @bindings: (element-type XexprBinding): the variables set in this environment
24.98 + *
24.99 + * A structure describing an XEXPR environment
24.100 + */
24.101 +typedef struct xexpr_environment {
24.102 + /*< private >*/
24.103 + int refcount;
24.104 + /*< public >*/
24.105 + char *function;
24.106 + struct xexpr_environment *outer;
24.107 + GSList *bindings;
24.108 +} XexprEnvironment;
24.109 +
24.110 +/**
24.111 + * Xexpr:
24.112 + * @constants: (element-type XexprConstant): the constants that make up this
24.113 + * expression
24.114 + * @environment: the innermost environment
24.115 + *
24.116 + * A structure describing an XEXPR expression
24.117 + */
24.118 +typedef struct xexpr {
24.119 + /*< private >*/
24.120 + GSList *tracing;
24.121 + /*< public >*/
24.122 + GSList *constants;
24.123 + XexprEnvironment *environment;
24.124 +} Xexpr;
24.125 +
24.126 +/**
24.127 + * XexprExtension:
24.128 + * @ns: the namespace of the extension
24.129 + * @function_evaluate: evaluates functions defined in the extension
24.130 + *
24.131 + * A structure describing an XEXPR extension
24.132 + */
24.133 +typedef struct xexpr_extension {
24.134 + char *ns;
24.135 + XexprConstant *(*function_evaluate)(Xexpr *xexpr,const char *ns,
24.136 + const char *id,GSList *bindings,GSList *args,GError **err);
24.137 +} XexprExtension;
24.138 +
24.139 +XexprConstant *xexpr_new_string(const char *s,gssize len);
24.140 +XexprConstant *xexpr_new_string_take_ownership(char *s);
24.141 +XexprConstant *xexpr_new_integer(long long int integer);
24.142 +XexprConstant *xexpr_new_number(double number);
24.143 +XexprConstant *xexpr_new_invocation(const char *ns,const char *function,
24.144 + GSList *bindings,GSList *constants);
24.145 +XexprConstant *xexpr_new_invocation_take_ownership(char *ns,char *function,
24.146 + GSList *bindings,GSList *constants);
24.147 +XexprConstant *xexpr_new_function_take_ownership(GSList *args,
24.148 + GSList *constants);
24.149 +XexprConstant *xexpr_new_function(GSList *args,GSList *constants);
24.150 +XexprConstant *xexpr_constant_dup(XexprConstant *constant);
24.151 +void xexpr_constant_free(XexprConstant *constant);
24.152 +
24.153 +void xexpr_binding_free(XexprBinding *binding);
24.154 +
24.155 +XexprConstant *xexpr_bindings_get(GSList *bindings,const char *id);
24.156 +gboolean xexpr_bindings_set(GSList *bindings,const char *id,
24.157 + XexprConstant *value);
24.158 +GSList *xexpr_bindings_new(GSList *bindings,const char *id,
24.159 + XexprConstant *value);
24.160 +GSList *xexpr_bindings_dup(GSList *bindings);
24.161 +
24.162 +Xexpr *xexpr_new(void);
24.163 +Xexpr *xexpr_sub(Xexpr *xexpr);
24.164 +void xexpr_var_new(Xexpr *xexpr,const char *id,XexprConstant *value);
24.165 +void xexpr_var_set(Xexpr *xexpr,const char *id,XexprConstant *value);
24.166 +XexprConstant *xexpr_var_get(Xexpr *xexpr,const char *id);
24.167 +void xexpr_start_tracing(Xexpr *xexpr,const char *id);
24.168 +gboolean xexpr_is_tracing(Xexpr *xexpr,const char *id);
24.169 +void xexpr_free(Xexpr *xexpr);
24.170 +XexprEnvironment *xexpr_get_environment(Xexpr *xexpr);
24.171 +void xexpr_set_constants(Xexpr *xexpr,GSList *constants);
24.172 +void xexpr_set_constants_take_ownership(Xexpr *xexpr,GSList *constants);
24.173 +
24.174 +void xexpr_environment_foreach(XexprEnvironment *environment,GTraverseFunc func,
24.175 + gpointer user_data);
24.176 +
24.177 +G_END_DECLS
24.178 +
24.179 +#endif /* __XEXPER_TYPES_H__ */
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/src/Makefile.am Wed Oct 10 22:58:21 2012 +0100
25.3 @@ -0,0 +1,4 @@
25.4 +AM_CFLAGS=$(LIBXEXPR_CFLAGS) -g -I$(top_srcdir)
25.5 +LDADD=../libxexpr/libxexpr.la $(LIBXEXPR_LIBS)
25.6 +
25.7 +bin_PROGRAMS=xexpr
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/src/xexpr.c Wed Oct 10 22:58:21 2012 +0100
26.3 @@ -0,0 +1,193 @@
26.4 +#include <stdlib.h>
26.5 +#include <string.h>
26.6 +#include <math.h>
26.7 +#include <glib.h>
26.8 +#include <libxml/parser.h>
26.9 +#include <libxexpr/xexpr.h>
26.10 +
26.11 +gboolean dump_tree,dump_result,test_result,do_xinclude;
26.12 +gchar **files;
26.13 +
26.14 +gboolean trace_symbol(const gchar *option_name,const gchar *value,gpointer data,
26.15 + GError **err)
26.16 +{
26.17 + Xexpr *xexpr=data;
26.18 + xexpr_start_tracing(xexpr,value);
26.19 + return TRUE;
26.20 +}
26.21 +
26.22 +gboolean set_param(const gchar *option_name,const gchar *value,gpointer data,
26.23 + GError **err)
26.24 +{
26.25 + const char *s;
26.26 + char *endptr;
26.27 + double d,integer;
26.28 + gchar *name;
26.29 + XexprConstant *arg;
26.30 + Xexpr *xexpr=data;
26.31 + s=strchr(value,',');
26.32 + if (!s)
26.33 + {
26.34 + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
26.35 + "No comma found in --param argument \"%s\"",value);
26.36 + return FALSE;
26.37 + }
26.38 + name=g_strndup(value,s-value);
26.39 + d=strtod(s+1,&endptr);
26.40 + if (!d || *endptr)
26.41 + {
26.42 + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
26.43 + "Invalid number in --param argument: \"%s\"",s);
26.44 + return FALSE;
26.45 + }
26.46 + if (!modf(d,&integer))
26.47 + arg=xexpr_new_integer(integer);
26.48 + else
26.49 + arg=xexpr_new_number(d);
26.50 + xexpr_var_set(xexpr,name,arg);
26.51 + xexpr_constant_free(arg);
26.52 + return TRUE;
26.53 +}
26.54 +
26.55 +gboolean set_string_param(const gchar *option_name,const gchar *value,
26.56 + gpointer data,GError **err)
26.57 +{
26.58 + const char *s;
26.59 + char *endptr;
26.60 + double d,integer;
26.61 + gchar *name;
26.62 + XexprConstant *arg;
26.63 + Xexpr *xexpr=data;
26.64 + s=strchr(value,',');
26.65 + if (!s)
26.66 + {
26.67 + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
26.68 + "No comma found in --stringparam argument \"%s\"",value);
26.69 + return FALSE;
26.70 + }
26.71 + name=g_strndup(value,s-value);
26.72 + arg=xexpr_new_string(s+1,-1);
26.73 + xexpr_var_set(xexpr,name,arg);
26.74 + xexpr_constant_free(arg);
26.75 + return TRUE;
26.76 +}
26.77 +
26.78 +static GOptionEntry entries[]={
26.79 + { "dump-tree",'d',0,G_OPTION_ARG_NONE,&dump_tree,"Dump parsed file",NULL },
26.80 + { "dump-result",'D',0,G_OPTION_ARG_NONE,&dump_result,"Dump result",NULL },
26.81 + { "test-result",'t',0,G_OPTION_ARG_NONE,&test_result,"Test result",NULL },
26.82 + { "trace",'T',0,G_OPTION_ARG_CALLBACK,trace_symbol,"Trace symbol",NULL },
26.83 + { G_OPTION_REMAINING,0,0,G_OPTION_ARG_FILENAME_ARRAY,&files,NULL,
26.84 + "[<input>]" },
26.85 + { "xinclude",0,0,G_OPTION_ARG_NONE,&do_xinclude,"Do XInclude processing",
26.86 + NULL },
26.87 + { "param",0,0,G_OPTION_ARG_CALLBACK,set_param,
26.88 + "Pass a (parameter,number) pair",NULL },
26.89 + { "stringparam",0,0,G_OPTION_ARG_CALLBACK,set_string_param,
26.90 + "Pass a (parameter,string) pair",NULL },
26.91 + { NULL }
26.92 +};
26.93 +
26.94 +gboolean set_variable(gpointer key,gpointer value,gpointer data)
26.95 +{
26.96 + xexpr_var_set(data,key,value);
26.97 + return FALSE;
26.98 +}
26.99 +
26.100 +gboolean run_xexpr(Xexpr *xexpr,xmlDocPtr doc,const char *filename)
26.101 +{
26.102 + gboolean retval=TRUE;
26.103 + GError *err=NULL;
26.104 + Xexpr *sub,*result;
26.105 + sub=xexpr_sub(xexpr);
26.106 + xexpr_environment_foreach(xexpr_get_environment(xexpr),set_variable,sub);
26.107 + if (!xexpr_parse_node(sub,xmlDocGetRootElement(doc),&err))
26.108 + {
26.109 + fprintf(stderr,"%s: %s\n",filename,err->message);
26.110 + exit(1);
26.111 + }
26.112 + if (dump_tree)
26.113 + {
26.114 + xexpr_dump(sub,stdout);
26.115 + putchar('\n');
26.116 + }
26.117 + else
26.118 + {
26.119 + result=xexpr_evaluate(sub,&err);
26.120 + if (err)
26.121 + {
26.122 + fprintf(stderr,"%s: %s\n",filename,err->message);
26.123 + g_clear_error(&err);
26.124 + xexpr_free(sub);
26.125 + return FALSE;
26.126 + }
26.127 + if (dump_result)
26.128 + {
26.129 + printf("\nResult: ");
26.130 + xexpr_dump(result,stdout);
26.131 + putchar('\n');
26.132 + }
26.133 + if (test_result)
26.134 + retval=xexpr_test(result,NULL);
26.135 + xexpr_free(result);
26.136 + }
26.137 + xexpr_free(sub);
26.138 + return retval;
26.139 +}
26.140 +
26.141 +int main(int argc,char **argv)
26.142 +{
26.143 + int i;
26.144 + xmlDocPtr doc;
26.145 + int xml_options=XML_PARSE_NOENT;
26.146 + gboolean result=TRUE;
26.147 + GError *err=NULL;
26.148 + GOptionGroup *group;
26.149 + GOptionContext *context;
26.150 + Xexpr *xexpr;
26.151 + xexpr=xexpr_new();
26.152 + context=g_option_context_new("- XEXPR interpreter");
26.153 + group=g_option_group_new(NULL,NULL,NULL,xexpr,NULL);
26.154 + g_option_group_add_entries(group,entries);
26.155 + g_option_context_set_main_group(context,group);
26.156 + if (!g_option_context_parse(context,&argc,&argv,&err))
26.157 + {
26.158 + fprintf(stderr,"%s\n",err->message);
26.159 + exit(1);
26.160 + }
26.161 + if (do_xinclude)
26.162 + xml_options|=XML_PARSE_XINCLUDE|XML_PARSE_NOXINCNODE;
26.163 + if (files && files[0])
26.164 + {
26.165 + for(i=0;files[i];i++)
26.166 + {
26.167 + doc=xmlReadFile(files[i],NULL,xml_options);
26.168 + if (!doc)
26.169 + result=FALSE;
26.170 + else
26.171 + {
26.172 + if (do_xinclude && xmlXIncludeProcessFlags(doc,xml_options)<0)
26.173 + result=FALSE;
26.174 + else if (!run_xexpr(xexpr,doc,files[i]))
26.175 + result=FALSE;
26.176 + xmlFreeDoc(doc);
26.177 + }
26.178 + }
26.179 + }
26.180 + else
26.181 + {
26.182 + doc=xmlReadFd(0,NULL,NULL,xml_options);
26.183 + if (!doc)
26.184 + result=FALSE;
26.185 + else
26.186 + {
26.187 + if (do_xinclude && xmlXIncludeProcessFlags(doc,xml_options)<0)
26.188 + result=FALSE;
26.189 + else if (!run_xexpr(xexpr,doc,"stdin"))
26.190 + result=FALSE;
26.191 + xmlFreeDoc(doc);
26.192 + }
26.193 + }
26.194 + xexpr_free(xexpr);
26.195 + exit(result?0:1);
26.196 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/test/Makefile.am Wed Oct 10 22:58:21 2012 +0100
27.3 @@ -0,0 +1,1 @@
27.4 +SUBDIRS=spec idb libxexpr
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/test/idb/Makefile.am Wed Oct 10 22:58:21 2012 +0100
28.3 @@ -0,0 +1,11 @@
28.4 +TESTS_ENVIRONMENT=top_builddir="$(top_builddir)"
28.5 +check_SCRIPTS=numbers bindings pcdata define get arithmetic comparison \
28.6 + builtin namespaces
28.7 +TESTS=$(check_SCRIPTS)
28.8 +
28.9 +%: %.sh
28.10 + cp $(srcdir)/$*.sh $@
28.11 + chmod +x $@
28.12 +
28.13 +EXTRA_DIST=$(check_SCRIPTS:%=%.sh) $(check_SCRIPTS:%=%.xml)
28.14 +CLEANFILES=$(check_SCRIPTS)
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/test/idb/arithmetic.sh Wed Oct 10 22:58:21 2012 +0100
29.3 @@ -0,0 +1,11 @@
29.4 +#!/bin/sh
29.5 +$top_builddir/src/xexpr $srcdir/arithmetic.xml > arithmetic.out
29.6 +cat <<-EOF > arithmetic.ref
29.7 +9
29.8 +6
29.9 +20
29.10 +EOF
29.11 +cmp arithmetic.out arithmetic.ref
29.12 +retval=$?
29.13 +rm -f arithmetic.out arithmetic.ref
29.14 +exit $retval
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/test/idb/arithmetic.xml Wed Oct 10 22:58:21 2012 +0100
30.3 @@ -0,0 +1,15 @@
30.4 +<expr>
30.5 + <define name="x"><multiply>2 3</multiply></define>
30.6 + <add><x/>3</add>
30.7 + <print><x/></print>
30.8 + <println/>
30.9 +
30.10 + <define name="x"><multiply>2 3</multiply></define>
30.11 + <add><x unused=""/>3</add>
30.12 + <print><x/></print>
30.13 + <println/>
30.14 +
30.15 + <set name="x">5</set>
30.16 + <add><x/><x/><x/></add>
30.17 + <print newline="true"><x/></print>
30.18 +</expr>
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/test/idb/bindings.sh Wed Oct 10 22:58:21 2012 +0100
31.3 @@ -0,0 +1,2 @@
31.4 +#!/bin/sh
31.5 +$top_builddir/src/xexpr --test-result $srcdir/bindings.xml
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/test/idb/bindings.xml Wed Oct 10 22:58:21 2012 +0100
32.3 @@ -0,0 +1,47 @@
32.4 +<expr>
32.5 + <define name="func" args="x"><x/></define>
32.6 +
32.7 + <and>
32.8 + <if>
32.9 + <eq>
32.10 + <func x="+01 "/>
32.11 + <func>
32.12 + <define name="x"><integer>1</integer></define>
32.13 + </func>
32.14 + </eq>
32.15 + <print newline="true">PASS</print>
32.16 + <expr>
32.17 + <print newline="true">FAIL</print>
32.18 + <false/>
32.19 + </expr>
32.20 + </if>
32.21 +
32.22 + <if>
32.23 + <eq>
32.24 + <func x=" 14.0e-1"/>
32.25 + <func>
32.26 + <define name="x"><float>1.4</float></define>
32.27 + </func>
32.28 + </eq>
32.29 + <print newline="true">PASS</print>
32.30 + <expr>
32.31 + <print newline="true">FAIL</print>
32.32 + <false/>
32.33 + </expr>
32.34 + </if>
32.35 +
32.36 + <if>
32.37 + <eq>
32.38 + <func x="Hello "/>
32.39 + <func>
32.40 + <define name="x"><string>Hello </string></define>
32.41 + </func>
32.42 + </eq>
32.43 + <print newline="true">PASS</print>
32.44 + <expr>
32.45 + <print newline="true">FAIL</print>
32.46 + <false/>
32.47 + </expr>
32.48 + </if>
32.49 + </and>
32.50 +</expr>
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/test/idb/builtin.sh Wed Oct 10 22:58:21 2012 +0100
33.3 @@ -0,0 +1,3 @@
33.4 +#!/bin/sh
33.5 +$top_builddir/src/xexpr $srcdir/builtin.xml >& /dev/null && exit 1
33.6 +exit 0
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/test/idb/builtin.xml Wed Oct 10 22:58:21 2012 +0100
34.3 @@ -0,0 +1,4 @@
34.4 +<expr>
34.5 + <define name="println"><print newline="true"/></define>
34.6 + <println/>
34.7 +</expr>
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/test/idb/comparison.sh Wed Oct 10 22:58:21 2012 +0100
35.3 @@ -0,0 +1,2 @@
35.4 +#!/bin/sh
35.5 +$top_builddir/src/xexpr --test-result $srcdir/comparison.xml
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/test/idb/comparison.xml Wed Oct 10 22:58:21 2012 +0100
36.3 @@ -0,0 +1,224 @@
36.4 +<and>
36.5 + <if>
36.6 + <eq>
36.7 + <eq/>
36.8 + <true/>
36.9 + </eq>
36.10 + <print newline="true">PASS</print>
36.11 + <expr>
36.12 + <print newline="true">FAIL</print>
36.13 + <false/>
36.14 + </expr>
36.15 + </if>
36.16 +
36.17 + <if>
36.18 + <eq>
36.19 + <neq/>
36.20 + <true/>
36.21 + </eq>
36.22 + <print newline="true">PASS</print>
36.23 + <expr>
36.24 + <print newline="true">FAIL</print>
36.25 + <false/>
36.26 + </expr>
36.27 + </if>
36.28 +
36.29 + <if>
36.30 + <eq>
36.31 + <leq/>
36.32 + <true/>
36.33 + </eq>
36.34 + <print newline="true">PASS</print>
36.35 + <expr>
36.36 + <print newline="true">FAIL</print>
36.37 + <false/>
36.38 + </expr>
36.39 + </if>
36.40 +
36.41 + <if>
36.42 + <eq>
36.43 + <geq/>
36.44 + <true/>
36.45 + </eq>
36.46 + <print newline="true">PASS</print>
36.47 + <expr>
36.48 + <print newline="true">FAIL</print>
36.49 + <false/>
36.50 + </expr>
36.51 + </if>
36.52 +
36.53 + <if>
36.54 + <eq>
36.55 + <lt/>
36.56 + <true/>
36.57 + </eq>
36.58 + <print newline="true">PASS</print>
36.59 + <expr>
36.60 + <print newline="true">FAIL</print>
36.61 + <false/>
36.62 + </expr>
36.63 + </if>
36.64 +
36.65 + <if>
36.66 + <eq>
36.67 + <gt/>
36.68 + <true/>
36.69 + </eq>
36.70 + <print newline="true">PASS</print>
36.71 + <expr>
36.72 + <print newline="true">FAIL</print>
36.73 + <false/>
36.74 + </expr>
36.75 + </if>
36.76 +
36.77 + <if>
36.78 + <eq>
36.79 + <eq><false/></eq>
36.80 + <true/>
36.81 + </eq>
36.82 + <print newline="true">PASS</print>
36.83 + <expr>
36.84 + <print newline="true">FAIL</print>
36.85 + <false/>
36.86 + </expr>
36.87 + </if>
36.88 +
36.89 + <if>
36.90 + <eq>
36.91 + <neq><string>Hello</string></neq>
36.92 + <true/>
36.93 + </eq>
36.94 + <print newline="true">PASS</print>
36.95 + <expr>
36.96 + <print newline="true">FAIL</print>
36.97 + <false/>
36.98 + </expr>
36.99 + </if>
36.100 +
36.101 + <if>
36.102 + <eq>
36.103 + <leq><float>27.2</float></leq>
36.104 + <true/>
36.105 + </eq>
36.106 + <print newline="true">PASS</print>
36.107 + <expr>
36.108 + <print newline="true">FAIL</print>
36.109 + <false/>
36.110 + </expr>
36.111 + </if>
36.112 +
36.113 + <if>
36.114 + <eq>
36.115 + <geq><define name="x">0</define></geq>
36.116 + <true/>
36.117 + </eq>
36.118 + <print newline="true">PASS</print>
36.119 + <expr>
36.120 + <print newline="true">FAIL</print>
36.121 + <false/>
36.122 + </expr>
36.123 + </if>
36.124 +
36.125 + <if>
36.126 + <eq>
36.127 + <lt><integer>3</integer></lt>
36.128 + <true/>
36.129 + </eq>
36.130 + <print newline="true">PASS</print>
36.131 + <expr>
36.132 + <print newline="true">FAIL</print>
36.133 + <false/>
36.134 + </expr>
36.135 + </if>
36.136 +
36.137 + <if>
36.138 + <eq>
36.139 + <gt><get name="x"/></gt>
36.140 + <true/>
36.141 + </eq>
36.142 + <print newline="true">PASS</print>
36.143 + <expr>
36.144 + <print newline="true">FAIL</print>
36.145 + <false/>
36.146 + </expr>
36.147 + </if>
36.148 +
36.149 + <if>
36.150 + <eq>
36.151 + <lt>1 2 3</lt>
36.152 + <true/>
36.153 + </eq>
36.154 + <print newline="true">PASS</print>
36.155 + <expr>
36.156 + <print newline="true">FAIL</print>
36.157 + <false/>
36.158 + </expr>
36.159 + </if>
36.160 +
36.161 + <if>
36.162 + <eq>
36.163 + <leq>1 2 3</leq>
36.164 + <true/>
36.165 + </eq>
36.166 + <print newline="true">PASS</print>
36.167 + <expr>
36.168 + <print newline="true">FAIL</print>
36.169 + <false/>
36.170 + </expr>
36.171 + </if>
36.172 +
36.173 + <if>
36.174 + <eq>
36.175 + <eq><float>35</float><integer>35</integer></eq>
36.176 + <true/>
36.177 + </eq>
36.178 + <print newline="true">PASS</print>
36.179 + <expr>
36.180 + <print newline="true">FAIL</print>
36.181 + <false/>
36.182 + </expr>
36.183 + </if>
36.184 +
36.185 + <if>
36.186 + <eq>
36.187 + <gt><string>œ</string><string>æ</string></gt>
36.188 + <true/>
36.189 + </eq>
36.190 + <print newline="true">PASS</print>
36.191 + <expr>
36.192 + <print newline="true">FAIL</print>
36.193 + <false/>
36.194 + </expr>
36.195 + </if>
36.196 +
36.197 + <if>
36.198 + <eq>
36.199 + <lt>
36.200 + <define name="x"><define name="y">2</define></define>
36.201 + <define name="z">3</define>
36.202 + </lt>
36.203 + <true/>
36.204 + </eq>
36.205 + <print newline="true">PASS</print>
36.206 + <expr>
36.207 + <print newline="true">FAIL</print>
36.208 + <false/>
36.209 + </expr>
36.210 + </if>
36.211 +
36.212 + <if>
36.213 + <eq>
36.214 + <lt>
36.215 + <false/>
36.216 + <nil/>
36.217 + <true/>
36.218 + </lt>
36.219 + <true/>
36.220 + </eq>
36.221 + <print newline="true">PASS</print>
36.222 + <expr>
36.223 + <print newline="true">FAIL</print>
36.224 + <false/>
36.225 + </expr>
36.226 + </if>
36.227 +</and>
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/test/idb/define.sh Wed Oct 10 22:58:21 2012 +0100
37.3 @@ -0,0 +1,2 @@
37.4 +#!/bin/sh
37.5 +$top_builddir/src/xexpr --test-result $srcdir/define.xml
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/test/idb/define.xml Wed Oct 10 22:58:21 2012 +0100
38.3 @@ -0,0 +1,35 @@
38.4 +<expr>
38.5 + <define name="x">1</define>
38.6 +
38.7 + <and>
38.8 + <if>
38.9 + <eq>
38.10 + <expr>
38.11 + <define name="x"><integer>2</integer></define>
38.12 + <x/>
38.13 + </expr>
38.14 + <x/>
38.15 + </eq>
38.16 + <expr>
38.17 + <print newline="true">FAIL</print>
38.18 + <false/>
38.19 + </expr>
38.20 + <print newline="true">PASS</print>
38.21 + </if>
38.22 +
38.23 + <if>
38.24 + <eq>
38.25 + <expr>
38.26 + <set name="x"><integer>2</integer></set>
38.27 + <x/>
38.28 + </expr>
38.29 + <x/>
38.30 + </eq>
38.31 + <print newline="true">PASS</print>
38.32 + <expr>
38.33 + <print newline="true">FAIL</print>
38.34 + <false/>
38.35 + </expr>
38.36 + </if>
38.37 + </and>
38.38 +</expr>
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/test/idb/get.sh Wed Oct 10 22:58:21 2012 +0100
39.3 @@ -0,0 +1,2 @@
39.4 +#!/bin/sh
39.5 +$top_builddir/src/xexpr --test-result $srcdir/get.xml
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/test/idb/get.xml Wed Oct 10 22:58:21 2012 +0100
40.3 @@ -0,0 +1,80 @@
40.4 +<expr>
40.5 + <define name="x">1</define>
40.6 + <define name=".product" args="a b c d">
40.7 + <add>
40.8 + <multiply>
40.9 + <a/>
40.10 + <b/>
40.11 + </multiply>
40.12 + <multiply>
40.13 + <c/>
40.14 + <d/>
40.15 + </multiply>
40.16 + </add>
40.17 + </define>
40.18 +
40.19 + <and>
40.20 + <if>
40.21 + <eq>
40.22 + <get name="x"/>
40.23 + <get>x</get>
40.24 + </eq>
40.25 + <print newline="true">PASS</print>
40.26 + <expr>
40.27 + <print newline="true">FAIL</print>
40.28 + <false/>
40.29 + </expr>
40.30 + </if>
40.31 +
40.32 + <if>
40.33 + <eq>
40.34 + <expr>
40.35 + <set name="x">1</set>
40.36 + <add><x/>1</add>
40.37 + <x/>
40.38 + </expr>
40.39 + <expr>
40.40 + <set name="x">1</set>
40.41 + <add><get>x</get>1</add>
40.42 + <x/>
40.43 + </expr>
40.44 + </eq>
40.45 + <expr>
40.46 + <print newline="true">FAIL</print>
40.47 + <false/>
40.48 + </expr>
40.49 + <print newline="true">PASS</print>
40.50 + </if>
40.51 +
40.52 + <if>
40.53 + <eq>
40.54 + <define name=".net">4.5.50709</define>
40.55 + <get>.net</get>
40.56 + </eq>
40.57 + <print newline="true">PASS</print>
40.58 + <expr>
40.59 + <print newline="true">FAIL</print>
40.60 + <false/>
40.61 + </expr>
40.62 + </if>
40.63 +
40.64 + <if>
40.65 + <eq>
40.66 + <expr>
40.67 + <define name="closure"/>
40.68 + <set name="closure">
40.69 + <get>.product</get>
40.70 + </set>
40.71 + <closure>1 2 3 4</closure>
40.72 + </expr>
40.73 + 14
40.74 + </eq>
40.75 + <print newline="true">PASS</print>
40.76 + <expr>
40.77 + <print newline="true">FAIL</print>
40.78 + <false/>
40.79 + </expr>
40.80 + </if>
40.81 +
40.82 + </and>
40.83 +</expr>
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/test/idb/namespaces.sh Wed Oct 10 22:58:21 2012 +0100
41.3 @@ -0,0 +1,2 @@
41.4 +#!/bin/sh
41.5 +$top_builddir/src/xexpr --test-result $srcdir/namespaces.xml
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/test/idb/namespaces.xml Wed Oct 10 22:58:21 2012 +0100
42.3 @@ -0,0 +1,10 @@
42.4 +<expr xmlns:xexpr="http://www.ebt.com/xexpr">
42.5 + <if>
42.6 + <xexpr:true/>
42.7 + <print newline="true">PASS</print>
42.8 + <expr>
42.9 + <print newline="true">FAIL</print>
42.10 + <false/>
42.11 + </expr>
42.12 + </if>
42.13 +</expr>
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/test/idb/numbers.sh Wed Oct 10 22:58:21 2012 +0100
43.3 @@ -0,0 +1,2 @@
43.4 +#!/bin/sh
43.5 +$top_builddir/src/xexpr --test-result $srcdir/numbers.xml
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/test/idb/numbers.xml Wed Oct 10 22:58:21 2012 +0100
44.3 @@ -0,0 +1,25 @@
44.4 +<and>
44.5 + <if>
44.6 + <eq>
44.7 + <integer>-1</integer>
44.8 + <subtract>0 1</subtract>
44.9 + </eq>
44.10 + <print newline="true">PASS</print>
44.11 + <expr>
44.12 + <print newline="true">FAIL</print>
44.13 + <false/>
44.14 + </expr>
44.15 + </if>
44.16 +
44.17 + <if>
44.18 + <eq>
44.19 + <float>+1.7</float>
44.20 + 1.7
44.21 + </eq>
44.22 + <print newline="true">PASS</print>
44.23 + <expr>
44.24 + <print newline="true">FAIL</print>
44.25 + <false/>
44.26 + </expr>
44.27 + </if>
44.28 +</and>
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/test/idb/pcdata.sh Wed Oct 10 22:58:21 2012 +0100
45.3 @@ -0,0 +1,2 @@
45.4 +#!/bin/sh
45.5 +$top_builddir/src/xexpr --test-result $srcdir/pcdata.xml
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/test/idb/pcdata.xml Wed Oct 10 22:58:21 2012 +0100
46.3 @@ -0,0 +1,19 @@
46.4 +<expr>
46.5 + <define name="foo" args="x y z"><x/><y/><z/></define>
46.6 +
46.7 + <if>
46.8 + <eq>
46.9 + <foo>This is the 0xdeadbeef constant.</foo>
46.10 + <foo>
46.11 + <string>This is the</string>
46.12 + <integer>0xdeadbeef</integer>
46.13 + <string>constant.</string>
46.14 + </foo>
46.15 + </eq>
46.16 + <print newline="true">PASS</print>
46.17 + <expr>
46.18 + <print newline="true">FAIL</print>
46.19 + <false/>
46.20 + </expr>
46.21 + </if>
46.22 +</expr>
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/test/libxexpr/Makefile.am Wed Oct 10 22:58:21 2012 +0100
47.3 @@ -0,0 +1,10 @@
47.4 +TESTS_ENVIRONMENT=top_builddir="$(top_builddir)"
47.5 +check_SCRIPTS=pi sin atan exp log
47.6 +TESTS=$(check_SCRIPTS)
47.7 +
47.8 +%: %.sh
47.9 + cp $(srcdir)/$*.sh $@
47.10 + chmod +x $@
47.11 +
47.12 +EXTRA_DIST=$(check_SCRIPTS:%=%.sh) $(check_SCRIPTS:%=%.xml)
47.13 +CLEANFILES=$(check_SCRIPTS)
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/test/libxexpr/atan.sh Wed Oct 10 22:58:21 2012 +0100
48.3 @@ -0,0 +1,2 @@
48.4 +#!/bin/sh
48.5 +$top_builddir/src/xexpr --test-result $srcdir/atan.xml
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/test/libxexpr/atan.xml Wed Oct 10 22:58:21 2012 +0100
49.3 @@ -0,0 +1,26 @@
49.4 +<expr xmlns="http://www.ebt.com/xexpr"
49.5 + xmlns:libxexpr="http://www.juiblex.co.uk/ns/libxexpr">
49.6 + <if>
49.7 + <eq>
49.8 + <libxexpr:atan>1 0</libxexpr:atan>
49.9 + <float>0</float>
49.10 + </eq>
49.11 + <print newline="true">PASS</print>
49.12 + <expr>
49.13 + <print newline="true">FAIL</print>
49.14 + <false/>
49.15 + </expr>
49.16 + </if>
49.17 +
49.18 + <if>
49.19 + <eq>
49.20 + <libxexpr:atan x="1" y="0"/>
49.21 + <float>0</float>
49.22 + </eq>
49.23 + <print newline="true">PASS</print>
49.24 + <expr>
49.25 + <print newline="true">FAIL</print>
49.26 + <false/>
49.27 + </expr>
49.28 + </if>
49.29 +</expr>
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/test/libxexpr/exp.sh Wed Oct 10 22:58:21 2012 +0100
50.3 @@ -0,0 +1,2 @@
50.4 +#!/bin/sh
50.5 +$top_builddir/src/xexpr --test-result $srcdir/exp.xml
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/test/libxexpr/exp.xml Wed Oct 10 22:58:21 2012 +0100
51.3 @@ -0,0 +1,15 @@
51.4 +<expr xmlns="http://www.ebt.com/xexpr"
51.5 + xmlns:libxexpr="http://www.juiblex.co.uk/ns/libxexpr">
51.6 + <if>
51.7 + <leq>
51.8 + <float>7.389</float>
51.9 + <libxexpr:exp>2</libxexpr:exp>
51.10 + <float>7.390</float>
51.11 + </leq>
51.12 + <print newline="true">PASS</print>
51.13 + <expr>
51.14 + <print newline="true">FAIL</print>
51.15 + <false/>
51.16 + </expr>
51.17 + </if>
51.18 +</expr>
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/test/libxexpr/log.sh Wed Oct 10 22:58:21 2012 +0100
52.3 @@ -0,0 +1,2 @@
52.4 +#!/bin/sh
52.5 +$top_builddir/src/xexpr --test-result $srcdir/log.xml
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/test/libxexpr/log.xml Wed Oct 10 22:58:21 2012 +0100
53.3 @@ -0,0 +1,16 @@
53.4 +<expr xmlns="http://www.ebt.com/xexpr"
53.5 + xmlns:libxexpr="http://www.juiblex.co.uk/ns/libxexpr">
53.6 + <if>
53.7 + <eq>
53.8 + <libxexpr:log>
53.9 + <libxexpr:exp>2</libxexpr:exp>
53.10 + </libxexpr:log>
53.11 + <float>2</float>
53.12 + </eq>
53.13 + <print newline="true">PASS</print>
53.14 + <expr>
53.15 + <print newline="true">FAIL</print>
53.16 + <false/>
53.17 + </expr>
53.18 + </if>
53.19 +</expr>
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/test/libxexpr/pi.sh Wed Oct 10 22:58:21 2012 +0100
54.3 @@ -0,0 +1,2 @@
54.4 +#!/bin/sh
54.5 +$top_builddir/src/xexpr --test-result $srcdir/pi.xml
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/test/libxexpr/pi.xml Wed Oct 10 22:58:21 2012 +0100
55.3 @@ -0,0 +1,17 @@
55.4 +<expr xmlns="http://www.ebt.com/xexpr"
55.5 + xmlns:libxexpr="http://www.juiblex.co.uk/ns/libxexpr">
55.6 + <if>
55.7 + <eq>
55.8 + <libxexpr:pi/>
55.9 + <multiply>
55.10 + <libxexpr:atan>1</libxexpr:atan>
55.11 + 4
55.12 + </multiply>
55.13 + </eq>
55.14 + <print newline="true">PASS</print>
55.15 + <expr>
55.16 + <print newline="true">FAIL</print>
55.17 + <false/>
55.18 + </expr>
55.19 + </if>
55.20 +</expr>
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/test/libxexpr/pow.xml Wed Oct 10 22:58:21 2012 +0100
56.3 @@ -0,0 +1,14 @@
56.4 +<expr xmlns="http://www.ebt.com/xexpr"
56.5 + xmlns:libxexpr="http://www.juiblex.co.uk/ns/libxexpr">
56.6 + <if>
56.7 + <eq>
56.8 + <libxexpr:pow>10 2</libxexpr:pow>
56.9 + <float>100</float>
56.10 + </eq>
56.11 + <print newline="true">PASS</print>
56.12 + <expr>
56.13 + <print newline="true">FAIL</print>
56.14 + <false/>
56.15 + </expr>
56.16 + </if>
56.17 +</expr>
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/test/libxexpr/sin.sh Wed Oct 10 22:58:21 2012 +0100
57.3 @@ -0,0 +1,2 @@
57.4 +#!/bin/sh
57.5 +$top_builddir/src/xexpr --test-result $srcdir/sin.xml
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/test/libxexpr/sin.xml Wed Oct 10 22:58:21 2012 +0100
58.3 @@ -0,0 +1,19 @@
58.4 +<expr xmlns="http://www.ebt.com/xexpr"
58.5 + xmlns:libxexpr="http://www.juiblex.co.uk/ns/libxexpr">
58.6 + <if>
58.7 + <eq>
58.8 + <libxexpr:sin>
58.9 + <divide>
58.10 + <libxexpr:pi/>
58.11 + 2
58.12 + </divide>
58.13 + </libxexpr:sin>
58.14 + <float>1</float>
58.15 + </eq>
58.16 + <print newline="true">PASS</print>
58.17 + <expr>
58.18 + <print newline="true">FAIL</print>
58.19 + <false/>
58.20 + </expr>
58.21 + </if>
58.22 +</expr>
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/test/spec/Makefile.am Wed Oct 10 22:58:21 2012 +0100
59.3 @@ -0,0 +1,15 @@
59.4 +TESTS_ENVIRONMENT=top_builddir="$(top_builddir)"
59.5 +check_SCRIPTS=spectest3 spectest4 spectest5 spectest6 spectest7 spectest8 \
59.6 + spectest11 spectest12 spectest13 spectest14 spectest15 spectest16 \
59.7 + spectest17 spectest19 spectest20 spectest21 spectest24 spectest26 \
59.8 + spectest27 spectest28 spectest29 spectest31 spectest32 spectest33 \
59.9 + spectest34 spectest35 spectest36 spectest38 spectest39 spectest40 \
59.10 + spectest42 spectest43 spectest45 spectest46 spectest48 spectest49
59.11 +TESTS=$(check_SCRIPTS)
59.12 +
59.13 +%: %.sh
59.14 + cp $(srcdir)/$*.sh $@
59.15 + chmod +x $@
59.16 +
59.17 +EXTRA_DIST=$(check_SCRIPTS:%=%.sh) $(check_SCRIPTS:%=%.xml)
59.18 +CLEANFILES=$(check_SCRIPTS)
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/test/spec/spectest11.sh Wed Oct 10 22:58:21 2012 +0100
60.3 @@ -0,0 +1,2 @@
60.4 +#!/bin/sh
60.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest11.xml
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/test/spec/spectest11.xml Wed Oct 10 22:58:21 2012 +0100
61.3 @@ -0,0 +1,71 @@
61.4 +<expr>
61.5 + <define name="pi">3.14</define>
61.6 +
61.7 + <define name="times-two" args="x">
61.8 + <multiply><get name="x"/>2</multiply>
61.9 + </define>
61.10 +
61.11 + <and>
61.12 + <if>
61.13 + <eq>
61.14 + <pi/>
61.15 + <float>3.14</float>
61.16 + </eq>
61.17 + <print newline="true">PASS</print>
61.18 + <expr>
61.19 + <print newline="true">FAIL</print>
61.20 + <false/>
61.21 + </expr>
61.22 + </if>
61.23 +
61.24 + <if>
61.25 + <eq>
61.26 + <times-two>10</times-two>
61.27 + <integer>20</integer>
61.28 + </eq>
61.29 + <print newline="true">PASS</print>
61.30 + <expr>
61.31 + <print newline="true">FAIL</print>
61.32 + <false/>
61.33 + </expr>
61.34 + </if>
61.35 +
61.36 + <if>
61.37 + <eq>
61.38 + <times-two>
61.39 + 2
61.40 + <set name="x">4</set>
61.41 + </times-two>
61.42 + <integer>8</integer>
61.43 + </eq>
61.44 + <print newline="true">PASS</print>
61.45 + <expr>
61.46 + <print newline="true">FAIL</print>
61.47 + <false/>
61.48 + </expr>
61.49 + </if>
61.50 +
61.51 + <print newline="true">
61.52 + <string>Times two returns: </string>
61.53 + <times-two>
61.54 + 2
61.55 + <define name="x">5</define>
61.56 + </times-two>
61.57 + </print>
61.58 +
61.59 + <if>
61.60 + <eq>
61.61 + <times-two>
61.62 + 2
61.63 + <define name="x">5</define>
61.64 + </times-two>
61.65 + <integer>10</integer>
61.66 + </eq>
61.67 + <print newline="true">PASS</print>
61.68 + <expr>
61.69 + <print newline="true">FAIL</print>
61.70 + <false/>
61.71 + </expr>
61.72 + </if>
61.73 + </and>
61.74 +</expr>
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/test/spec/spectest12.sh Wed Oct 10 22:58:21 2012 +0100
62.3 @@ -0,0 +1,8 @@
62.4 +#!/bin/sh
62.5 +set -e
62.6 +$top_builddir/src/xexpr --test-result $srcdir/spectest12.xml > spectest12.out
62.7 +echo "4Hello World" > spectest12.ref
62.8 +cmp spectest12.out spectest12.ref
62.9 +retval=$?
62.10 +rm -f spectest12.out spectest12.ref
62.11 +exit $retval
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/test/spec/spectest12.xml Wed Oct 10 22:58:21 2012 +0100
63.3 @@ -0,0 +1,5 @@
63.4 +<and>
63.5 + <print><add>2 2</add></print>
63.6 + <print>Hello World</print>
63.7 + <print newline="true"/>
63.8 +</and>
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/test/spec/spectest13.sh Wed Oct 10 22:58:21 2012 +0100
64.3 @@ -0,0 +1,8 @@
64.4 +#!/bin/sh
64.5 +set -e
64.6 +$top_builddir/src/xexpr --test-result $srcdir/spectest13.xml > spectest13.out
64.7 +echo "" > spectest13.ref
64.8 +cmp spectest13.out spectest13.ref
64.9 +retval=$?
64.10 +rm -f spectest13.out spectest13.ref
64.11 +exit $retval
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/test/spec/spectest13.xml Wed Oct 10 22:58:21 2012 +0100
65.3 @@ -0,0 +1,1 @@
65.4 +<println/>
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/test/spec/spectest14.sh Wed Oct 10 22:58:21 2012 +0100
66.3 @@ -0,0 +1,2 @@
66.4 +#!/bin/sh
66.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest14.xml
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/test/spec/spectest14.xml Wed Oct 10 22:58:21 2012 +0100
67.3 @@ -0,0 +1,31 @@
67.4 +<expr>
67.5 + <define name="x">1</define>
67.6 +
67.7 + <and>
67.8 + <if>
67.9 + <eq>
67.10 + <get name="x"/>
67.11 + <get>x</get>
67.12 + <x/>
67.13 + </eq>
67.14 + <print newline="true">PASS</print>
67.15 + <expr>
67.16 + <print newline="true">FAIL</print>
67.17 + <false/>
67.18 + </expr>
67.19 + </if>
67.20 +
67.21 + <if>
67.22 + <eq>
67.23 + <get name="y"/>
67.24 + <get>y</get>
67.25 + <nil/>
67.26 + </eq>
67.27 + <print newline="true">PASS</print>
67.28 + <expr>
67.29 + <print newline="true">FAIL</print>
67.30 + <false/>
67.31 + </expr>
67.32 + </if>
67.33 + </and>
67.34 +</expr>
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/test/spec/spectest15.sh Wed Oct 10 22:58:21 2012 +0100
68.3 @@ -0,0 +1,2 @@
68.4 +#!/bin/sh
68.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest15.xml
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/test/spec/spectest15.xml Wed Oct 10 22:58:21 2012 +0100
69.3 @@ -0,0 +1,37 @@
69.4 +<and>
69.5 + <if>
69.6 + <eq>
69.7 + <set name="x" value="hello"/>
69.8 + <string>hello</string>
69.9 + </eq>
69.10 + <print newline="true">PASS</print>
69.11 + <expr>
69.12 + <print newline="true">FAIL</print>
69.13 + <false/>
69.14 + </expr>
69.15 + </if>
69.16 +
69.17 + <if>
69.18 + <eq>
69.19 + <set name="x">hello</set>
69.20 + <string>hello</string>
69.21 + </eq>
69.22 + <print newline="true">PASS</print>
69.23 + <expr>
69.24 + <print newline="true">FAIL</print>
69.25 + <false/>
69.26 + </expr>
69.27 + </if>
69.28 +
69.29 + <if>
69.30 + <eq>
69.31 + <set>hello 123</set>
69.32 + <integer>123</integer>
69.33 + </eq>
69.34 + <print newline="true">PASS</print>
69.35 + <expr>
69.36 + <print newline="true">FAIL</print>
69.37 + <false/>
69.38 + </expr>
69.39 + </if>
69.40 +</and>
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/test/spec/spectest16.sh Wed Oct 10 22:58:21 2012 +0100
70.3 @@ -0,0 +1,8 @@
70.4 +#!/bin/sh
70.5 +set -e
70.6 +$top_builddir/src/xexpr --test-result $srcdir/spectest16.xml > spectest16.out
70.7 +echo -n "3" > spectest16.ref
70.8 +cmp spectest16.out spectest16.ref
70.9 +retval=$?
70.10 +rm -f spectest16.out spectest16.ref
70.11 +exit $retval
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/test/spec/spectest16.xml Wed Oct 10 22:58:21 2012 +0100
71.3 @@ -0,0 +1,11 @@
71.4 +<and>
71.5 + <expr>
71.6 + <set name="x">3</set>
71.7 + <print><x/></print>
71.8 + </expr>
71.9 +
71.10 + <eq>
71.11 + <expr/>
71.12 + <nil/>
71.13 + </eq>
71.14 +</and>
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/test/spec/spectest17.sh Wed Oct 10 22:58:21 2012 +0100
72.3 @@ -0,0 +1,2 @@
72.4 +#!/bin/sh
72.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest17.xml
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/test/spec/spectest17.xml Wed Oct 10 22:58:21 2012 +0100
73.3 @@ -0,0 +1,48 @@
73.4 +<expr x="1">
73.5 + <define name="foo">
73.6 + <return>bar</return>
73.7 + </define>
73.8 +
73.9 + <define name="bar">
73.10 + <return>1 2</return>
73.11 + <set name="x" value="2"/>
73.12 + </define>
73.13 +
73.14 + <and>
73.15 + <if>
73.16 + <eq>
73.17 + <foo/>
73.18 + <string>bar</string>
73.19 + </eq>
73.20 + <print newline="true">PASS</print>
73.21 + <expr>
73.22 + <print newline="true">FAIL</print>
73.23 + <false/>
73.24 + </expr>
73.25 + </if>
73.26 +
73.27 + <if>
73.28 + <eq>
73.29 + <bar/>
73.30 + <integer>2</integer>
73.31 + </eq>
73.32 + <print newline="true">PASS</print>
73.33 + <expr>
73.34 + <print newline="true">FAIL</print>
73.35 + <false/>
73.36 + </expr>
73.37 + </if>
73.38 +
73.39 + <if>
73.40 + <eq>
73.41 + <x/>
73.42 + <integer>1</integer>
73.43 + </eq>
73.44 + <print newline="true">PASS</print>
73.45 + <expr>
73.46 + <print newline="true">FAIL</print>
73.47 + <false/>
73.48 + </expr>
73.49 + </if>
73.50 + </and>
73.51 +</expr>
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/test/spec/spectest19.sh Wed Oct 10 22:58:21 2012 +0100
74.3 @@ -0,0 +1,2 @@
74.4 +#!/bin/sh
74.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest19.xml
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/test/spec/spectest19.xml Wed Oct 10 22:58:21 2012 +0100
75.3 @@ -0,0 +1,30 @@
75.4 +<and>
75.5 + <if>
75.6 + <eq>
75.7 + <string>This is #1</string>
75.8 + <add>This is #1</add>
75.9 + </eq>
75.10 + <print newline="true">PASS</print>
75.11 + <expr>
75.12 + <print newline="true">FAIL</print>
75.13 + <false/>
75.14 + </expr>
75.15 + </if>
75.16 +
75.17 + <if>
75.18 + <eq>
75.19 + <string>This is the 00 constant.</string>
75.20 + <add>
75.21 + <string>This is the </string>
75.22 + 0
75.23 + 0
75.24 + <string> constant.</string>
75.25 + </add>
75.26 + </eq>
75.27 + <print newline="true">PASS</print>
75.28 + <expr>
75.29 + <print newline="true">FAIL</print>
75.30 + <false/>
75.31 + </expr>
75.32 + </if>
75.33 +</and>
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/test/spec/spectest20.sh Wed Oct 10 22:58:21 2012 +0100
76.3 @@ -0,0 +1,2 @@
76.4 +#!/bin/sh
76.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest20.xml
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
77.2 +++ b/test/spec/spectest20.xml Wed Oct 10 22:58:21 2012 +0100
77.3 @@ -0,0 +1,13 @@
77.4 +<expr>
77.5 + <if>
77.6 + <eq>
77.7 + <integer>123</integer>
77.8 + 123
77.9 + </eq>
77.10 + <print newline="true">PASS</print>
77.11 + <expr>
77.12 + <print newline="true">FAIL</print>
77.13 + <false/>
77.14 + </expr>
77.15 + </if>
77.16 +</expr>
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/test/spec/spectest21.sh Wed Oct 10 22:58:21 2012 +0100
78.3 @@ -0,0 +1,2 @@
78.4 +#!/bin/sh
78.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest21.xml
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/test/spec/spectest21.xml Wed Oct 10 22:58:21 2012 +0100
79.3 @@ -0,0 +1,25 @@
79.4 +<and>
79.5 + <if>
79.6 + <eq>
79.7 + <float>123</float>
79.8 + 123
79.9 + </eq>
79.10 + <print newline="true">PASS</print>
79.11 + <expr>
79.12 + <print newline="true">FAIL</print>
79.13 + <false/>
79.14 + </expr>
79.15 + </if>
79.16 +
79.17 + <if>
79.18 + <eq>
79.19 + <float>123.143</float>
79.20 + 123.143
79.21 + </eq>
79.22 + <print newline="true">PASS</print>
79.23 + <expr>
79.24 + <print newline="true">FAIL</print>
79.25 + <false/>
79.26 + </expr>
79.27 + </if>
79.28 +</and>
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
80.2 +++ b/test/spec/spectest24.sh Wed Oct 10 22:58:21 2012 +0100
80.3 @@ -0,0 +1,2 @@
80.4 +#!/bin/sh
80.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest24.xml
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
81.2 +++ b/test/spec/spectest24.xml Wed Oct 10 22:58:21 2012 +0100
81.3 @@ -0,0 +1,22 @@
81.4 +<and>
81.5 + <if>
81.6 + <nil/>
81.7 + <expr>
81.8 + <print newline="true">FAIL</print>
81.9 + <false/>
81.10 + </expr>
81.11 + <print newline="true">PASS</print>
81.12 + </if>
81.13 +
81.14 + <if>
81.15 + <eq>
81.16 + <nil/>
81.17 + <false/>
81.18 + </eq>
81.19 + <expr>
81.20 + <print newline="true">FAIL</print>
81.21 + <false/>
81.22 + </expr>
81.23 + <print newline="true">PASS</print>
81.24 + </if>
81.25 +</and>
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/test/spec/spectest26.sh Wed Oct 10 22:58:21 2012 +0100
82.3 @@ -0,0 +1,2 @@
82.4 +#!/bin/sh
82.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest26.xml
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/test/spec/spectest26.xml Wed Oct 10 22:58:21 2012 +0100
83.3 @@ -0,0 +1,49 @@
83.4 +<and>
83.5 + <if>
83.6 + <eq>
83.7 + <add>1 2 3</add>
83.8 + <integer>6</integer>
83.9 + </eq>
83.10 + <print newline="true">PASS</print>
83.11 + <expr>
83.12 + <print newline="true">FAIL</print>
83.13 + <false/>
83.14 + </expr>
83.15 + </if>
83.16 +
83.17 + <if>
83.18 + <eq>
83.19 + <add>1 2 3.0</add>
83.20 + <float>6.0</float>
83.21 + </eq>
83.22 + <print newline="true">PASS</print>
83.23 + <expr>
83.24 + <print newline="true">FAIL</print>
83.25 + <false/>
83.26 + </expr>
83.27 + </if>
83.28 +
83.29 + <if>
83.30 + <eq>
83.31 + <add>Hello World#<add>2 2</add></add>
83.32 + <string>Hello World#4</string>
83.33 + </eq>
83.34 + <print newline="true">PASS</print>
83.35 + <expr>
83.36 + <print newline="true">FAIL</print>
83.37 + <false/>
83.38 + </expr>
83.39 + </if>
83.40 +
83.41 + <if>
83.42 + <eq>
83.43 + <add><set>x 3</set>2</add>
83.44 + <integer>5</integer>
83.45 + </eq>
83.46 + <print newline="true">PASS</print>
83.47 + <expr>
83.48 + <print newline="true">FAIL</print>
83.49 + <false/>
83.50 + </expr>
83.51 + </if>
83.52 +</and>
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/test/spec/spectest27.sh Wed Oct 10 22:58:21 2012 +0100
84.3 @@ -0,0 +1,2 @@
84.4 +#!/bin/sh
84.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest27.xml
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/test/spec/spectest27.xml Wed Oct 10 22:58:21 2012 +0100
85.3 @@ -0,0 +1,11 @@
85.4 +<if>
85.5 + <eq>
85.6 + <subtract>10 2 1</subtract>
85.7 + <integer>7</integer>
85.8 + </eq>
85.9 + <print newline="true">PASS</print>
85.10 + <expr>
85.11 + <print newline="true">FAIL</print>
85.12 + <false/>
85.13 + </expr>
85.14 +</if>
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/test/spec/spectest28.sh Wed Oct 10 22:58:21 2012 +0100
86.3 @@ -0,0 +1,2 @@
86.4 +#!/bin/sh
86.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest28.xml
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/test/spec/spectest28.xml Wed Oct 10 22:58:21 2012 +0100
87.3 @@ -0,0 +1,11 @@
87.4 +<if>
87.5 + <eq>
87.6 + <multiply>10 2 1</multiply>
87.7 + <integer>20</integer>
87.8 + </eq>
87.9 + <print newline="true">PASS</print>
87.10 + <expr>
87.11 + <print newline="true">FAIL</print>
87.12 + <false/>
87.13 + </expr>
87.14 +</if>
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/test/spec/spectest29.sh Wed Oct 10 22:58:21 2012 +0100
88.3 @@ -0,0 +1,2 @@
88.4 +#!/bin/sh
88.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest29.xml
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/test/spec/spectest29.xml Wed Oct 10 22:58:21 2012 +0100
89.3 @@ -0,0 +1,11 @@
89.4 +<if>
89.5 + <eq>
89.6 + <divide>20 2 2</divide>
89.7 + <integer>5</integer>
89.8 + </eq>
89.9 + <print newline="true">PASS</print>
89.10 + <expr>
89.11 + <print newline="true">FAIL</print>
89.12 + <false/>
89.13 + </expr>
89.14 +</if>
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/test/spec/spectest3.sh Wed Oct 10 22:58:21 2012 +0100
90.3 @@ -0,0 +1,8 @@
90.4 +#!/bin/sh
90.5 +set -e
90.6 +$top_builddir/src/xexpr --test-result $srcdir/spectest3.xml > spectest3.out
90.7 +echo -n "3" > spectest3.ref
90.8 +cmp spectest3.out spectest3.ref
90.9 +retval=$?
90.10 +rm -f spectest3.out spectest3.ref
90.11 +exit $retval
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/test/spec/spectest3.xml Wed Oct 10 22:58:21 2012 +0100
91.3 @@ -0,0 +1,25 @@
91.4 +<and>
91.5 + <expr>
91.6 + <define name="email" args="to body">
91.7 + <add>
91.8 + <string>From user@localhost </string>
91.9 + <string>To: </string>
91.10 + <to/>
91.11 + <string> </string>
91.12 + <string> </string>
91.13 + <body/>
91.14 + <string> </string>
91.15 + </add>
91.16 + </define>
91.17 +
91.18 + <eq>
91.19 + <email to="authors@ebt.com">hello</email>
91.20 + <email>
91.21 + <define name="to">authors@ebt.com</define>
91.22 + hello
91.23 + </email>
91.24 + </eq>
91.25 + </expr>
91.26 +
91.27 + <print x="2"><define name="x">3</define><x/></print>
91.28 +</and>
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
92.2 +++ b/test/spec/spectest31.sh Wed Oct 10 22:58:21 2012 +0100
92.3 @@ -0,0 +1,2 @@
92.4 +#!/bin/sh
92.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest31.xml
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
93.2 +++ b/test/spec/spectest31.xml Wed Oct 10 22:58:21 2012 +0100
93.3 @@ -0,0 +1,51 @@
93.4 +<and>
93.5 + <if>
93.6 + <eq>
93.7 + <string>A</string>
93.8 + A
93.9 + <set name="x">A</set>
93.10 + </eq>
93.11 + <print newline="true">PASS</print>
93.12 + <expr>
93.13 + <print newline="true">FAIL</print>
93.14 + <false/>
93.15 + </expr>
93.16 + </if>
93.17 +
93.18 + <if>
93.19 + <eq>
93.20 + 1 1 1
93.21 + <define name="x">1</define>
93.22 + </eq>
93.23 + <print newline="true">PASS</print>
93.24 + <expr>
93.25 + <print newline="true">FAIL</print>
93.26 + <false/>
93.27 + </expr>
93.28 + </if>
93.29 +
93.30 + <if>
93.31 + <eq>
93.32 + <string>A</string>
93.33 + A
93.34 + <define name="x">B</define>
93.35 + </eq>
93.36 + <expr>
93.37 + <print newline="true">FAIL</print>
93.38 + <false/>
93.39 + </expr>
93.40 + <print newline="true">PASS</print>
93.41 + </if>
93.42 +
93.43 + <if>
93.44 + <eq>
93.45 + 1 1 1
93.46 + <define name="x">2</define>
93.47 + </eq>
93.48 + <expr>
93.49 + <print newline="true">FAIL</print>
93.50 + <false/>
93.51 + </expr>
93.52 + <print newline="true">PASS</print>
93.53 + </if>
93.54 +</and>
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
94.2 +++ b/test/spec/spectest32.sh Wed Oct 10 22:58:21 2012 +0100
94.3 @@ -0,0 +1,2 @@
94.4 +#!/bin/sh
94.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest32.xml
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/test/spec/spectest32.xml Wed Oct 10 22:58:21 2012 +0100
95.3 @@ -0,0 +1,51 @@
95.4 +<and>
95.5 + <if>
95.6 + <neq>
95.7 + <string>A</string>
95.8 + B
95.9 + <set name="x">C</set>
95.10 + </neq>
95.11 + <print newline="true">PASS</print>
95.12 + <expr>
95.13 + <print newline="true">FAIL</print>
95.14 + <false/>
95.15 + </expr>
95.16 + </if>
95.17 +
95.18 + <if>
95.19 + <neq>
95.20 + 1 2 3
95.21 + <define name="x">4</define>
95.22 + </neq>
95.23 + <print newline="true">PASS</print>
95.24 + <expr>
95.25 + <print newline="true">FAIL</print>
95.26 + <false/>
95.27 + </expr>
95.28 + </if>
95.29 +
95.30 + <if>
95.31 + <neq>
95.32 + <string>A</string>
95.33 + B
95.34 + <define name="x">B</define>
95.35 + </neq>
95.36 + <expr>
95.37 + <print newline="true">FAIL</print>
95.38 + <false/>
95.39 + </expr>
95.40 + <print newline="true">PASS</print>
95.41 + </if>
95.42 +
95.43 + <if>
95.44 + <neq>
95.45 + 1 1 2
95.46 + <define name="x">2</define>
95.47 + </neq>
95.48 + <expr>
95.49 + <print newline="true">FAIL</print>
95.50 + <false/>
95.51 + </expr>
95.52 + <print newline="true">PASS</print>
95.53 + </if>
95.54 +</and>
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
96.2 +++ b/test/spec/spectest33.sh Wed Oct 10 22:58:21 2012 +0100
96.3 @@ -0,0 +1,2 @@
96.4 +#!/bin/sh
96.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest33.xml
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
97.2 +++ b/test/spec/spectest33.xml Wed Oct 10 22:58:21 2012 +0100
97.3 @@ -0,0 +1,63 @@
97.4 +<and>
97.5 + <if>
97.6 + <leq>
97.7 + <define name="x">B</define>
97.8 + B
97.9 + <string>C</string>
97.10 + </leq>
97.11 + <print newline="true">PASS</print>
97.12 + <expr>
97.13 + <print newline="true">FAIL</print>
97.14 + <false/>
97.15 + </expr>
97.16 + </if>
97.17 +
97.18 + <if>
97.19 + <leq>
97.20 + <define name="x">1</define>
97.21 + 1 2 3 4
97.22 + </leq>
97.23 + <print newline="true">PASS</print>
97.24 + <expr>
97.25 + <print newline="true">FAIL</print>
97.26 + <false/>
97.27 + </expr>
97.28 + </if>
97.29 +
97.30 + <if>
97.31 + <leq>
97.32 + <define name="x">C</define>
97.33 + B
97.34 + <string>C</string>
97.35 + </leq>
97.36 + <expr>
97.37 + <print newline="true">FAIL</print>
97.38 + <false/>
97.39 + </expr>
97.40 + <print newline="true">PASS</print>
97.41 + </if>
97.42 +
97.43 + <if>
97.44 + <leq>
97.45 + <define name="x">2</define>
97.46 + 1 2 3 4
97.47 + </leq>
97.48 + <expr>
97.49 + <print newline="true">FAIL</print>
97.50 + <false/>
97.51 + </expr>
97.52 + <print newline="true">PASS</print>
97.53 + </if>
97.54 +
97.55 + <if>
97.56 + <leq>
97.57 + <string>1</string>
97.58 + 1 2 3 4
97.59 + </leq>
97.60 + <expr>
97.61 + <print newline="true">FAIL</print>
97.62 + <false/>
97.63 + </expr>
97.64 + <print newline="true">PASS</print>
97.65 + </if>
97.66 +</and>
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
98.2 +++ b/test/spec/spectest34.sh Wed Oct 10 22:58:21 2012 +0100
98.3 @@ -0,0 +1,2 @@
98.4 +#!/bin/sh
98.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest34.xml
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
99.2 +++ b/test/spec/spectest34.xml Wed Oct 10 22:58:21 2012 +0100
99.3 @@ -0,0 +1,63 @@
99.4 +<and>
99.5 + <if>
99.6 + <geq>
99.7 + <define name="x">B</define>
99.8 + B
99.9 + <string>A</string>
99.10 + </geq>
99.11 + <print newline="true">PASS</print>
99.12 + <expr>
99.13 + <print newline="true">FAIL</print>
99.14 + <false/>
99.15 + </expr>
99.16 + </if>
99.17 +
99.18 + <if>
99.19 + <geq>
99.20 + <define name="x">3</define>
99.21 + 3 2 1
99.22 + </geq>
99.23 + <print newline="true">PASS</print>
99.24 + <expr>
99.25 + <print newline="true">FAIL</print>
99.26 + <false/>
99.27 + </expr>
99.28 + </if>
99.29 +
99.30 + <if>
99.31 + <geq>
99.32 + <define name="x">A</define>
99.33 + B
99.34 + <string>A</string>
99.35 + </geq>
99.36 + <expr>
99.37 + <print newline="true">FAIL</print>
99.38 + <false/>
99.39 + </expr>
99.40 + <print newline="true">PASS</print>
99.41 + </if>
99.42 +
99.43 + <if>
99.44 + <geq>
99.45 + <define name="x">1</define>
99.46 + 2 1 1
99.47 + </geq>
99.48 + <expr>
99.49 + <print newline="true">FAIL</print>
99.50 + <false/>
99.51 + </expr>
99.52 + <print newline="true">PASS</print>
99.53 + </if>
99.54 +
99.55 + <if>
99.56 + <geq>
99.57 + <string>3</string>
99.58 + 3 2 1
99.59 + </geq>
99.60 + <expr>
99.61 + <print newline="true">FAIL</print>
99.62 + <false/>
99.63 + </expr>
99.64 + <print newline="true">PASS</print>
99.65 + </if>
99.66 +</and>
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
100.2 +++ b/test/spec/spectest35.sh Wed Oct 10 22:58:21 2012 +0100
100.3 @@ -0,0 +1,2 @@
100.4 +#!/bin/sh
100.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest35.xml
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
101.2 +++ b/test/spec/spectest35.xml Wed Oct 10 22:58:21 2012 +0100
101.3 @@ -0,0 +1,63 @@
101.4 +<and>
101.5 + <if>
101.6 + <lt>
101.7 + <string>A</string>
101.8 + B
101.9 + <define name="x">C</define>
101.10 + </lt>
101.11 + <print newline="true">PASS</print>
101.12 + <expr>
101.13 + <print newline="true">FAIL</print>
101.14 + <false/>
101.15 + </expr>
101.16 + </if>
101.17 +
101.18 + <if>
101.19 + <lt>
101.20 + 1 2 3
101.21 + <define name="x">4</define>
101.22 + </lt>
101.23 + <print newline="true">PASS</print>
101.24 + <expr>
101.25 + <print newline="true">FAIL</print>
101.26 + <false/>
101.27 + </expr>
101.28 + </if>
101.29 +
101.30 + <if>
101.31 + <lt>
101.32 + <string>A</string>
101.33 + B
101.34 + <define name="x">B</define>
101.35 + </lt>
101.36 + <expr>
101.37 + <print newline="true">FAIL</print>
101.38 + <false/>
101.39 + </expr>
101.40 + <print newline="true">PASS</print>
101.41 + </if>
101.42 +
101.43 + <if>
101.44 + <lt>
101.45 + 1 2 3
101.46 + <define name="x">3</define>
101.47 + </lt>
101.48 + <expr>
101.49 + <print newline="true">FAIL</print>
101.50 + <false/>
101.51 + </expr>
101.52 + <print newline="true">PASS</print>
101.53 + </if>
101.54 +
101.55 + <if>
101.56 + <lt>
101.57 + 1 2 3
101.58 + <string>4</string>
101.59 + </lt>
101.60 + <expr>
101.61 + <print newline="true">FAIL</print>
101.62 + <false/>
101.63 + </expr>
101.64 + <print newline="true">PASS</print>
101.65 + </if>
101.66 +</and>
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
102.2 +++ b/test/spec/spectest36.sh Wed Oct 10 22:58:21 2012 +0100
102.3 @@ -0,0 +1,2 @@
102.4 +#!/bin/sh
102.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest36.xml
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
103.2 +++ b/test/spec/spectest36.xml Wed Oct 10 22:58:21 2012 +0100
103.3 @@ -0,0 +1,63 @@
103.4 +<and>
103.5 + <if>
103.6 + <gt>
103.7 + <string>C</string>
103.8 + B
103.9 + <define name="x">A</define>
103.10 + </gt>
103.11 + <print newline="true">PASS</print>
103.12 + <expr>
103.13 + <print newline="true">FAIL</print>
103.14 + <false/>
103.15 + </expr>
103.16 + </if>
103.17 +
103.18 + <if>
103.19 + <gt>
103.20 + 4 3 2
103.21 + <define name="x">1</define>
103.22 + </gt>
103.23 + <print newline="true">PASS</print>
103.24 + <expr>
103.25 + <print newline="true">FAIL</print>
103.26 + <false/>
103.27 + </expr>
103.28 + </if>
103.29 +
103.30 + <if>
103.31 + <gt>
103.32 + <string>C</string>
103.33 + B
103.34 + <define name="x">C</define>
103.35 + </gt>
103.36 + <expr>
103.37 + <print newline="true">FAIL</print>
103.38 + <false/>
103.39 + </expr>
103.40 + <print newline="true">PASS</print>
103.41 + </if>
103.42 +
103.43 + <if>
103.44 + <gt>
103.45 + 4 3 2
103.46 + <define name="x">3</define>
103.47 + </gt>
103.48 + <expr>
103.49 + <print newline="true">FAIL</print>
103.50 + <false/>
103.51 + </expr>
103.52 + <print newline="true">PASS</print>
103.53 + </if>
103.54 +
103.55 + <if>
103.56 + <gt>
103.57 + 4 3 2
103.58 + <string>1</string>
103.59 + </gt>
103.60 + <expr>
103.61 + <print newline="true">FAIL</print>
103.62 + <false/>
103.63 + </expr>
103.64 + <print newline="true">PASS</print>
103.65 + </if>
103.66 +</and>
104.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
104.2 +++ b/test/spec/spectest38.sh Wed Oct 10 22:58:21 2012 +0100
104.3 @@ -0,0 +1,2 @@
104.4 +#!/bin/sh
104.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest38.xml
105.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
105.2 +++ b/test/spec/spectest38.xml Wed Oct 10 22:58:21 2012 +0100
105.3 @@ -0,0 +1,43 @@
105.4 +<and>
105.5 + <if>
105.6 + <eq>
105.7 + <and>
105.8 + <true/>
105.9 + <define name="x"><true/></define>
105.10 + </and>
105.11 + <true/>
105.12 + </eq>
105.13 + <print newline="true">PASS</print>
105.14 + <expr>
105.15 + <print newline="true">FAIL</print>
105.16 + <false/>
105.17 + </expr>
105.18 + </if>
105.19 +
105.20 + <if>
105.21 + <eq>
105.22 + <and>
105.23 + <true/>
105.24 + <define name="x"><false/></define>
105.25 + </and>
105.26 + <false/>
105.27 + </eq>
105.28 + <print newline="true">PASS</print>
105.29 + <expr>
105.30 + <print newline="true">FAIL</print>
105.31 + <false/>
105.32 + </expr>
105.33 + </if>
105.34 +
105.35 + <if>
105.36 + <eq>
105.37 + <and/>
105.38 + <true/>
105.39 + </eq>
105.40 + <print newline="true">PASS</print>
105.41 + <expr>
105.42 + <print newline="true">FAIL</print>
105.43 + <false/>
105.44 + </expr>
105.45 + </if>
105.46 +</and>
106.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
106.2 +++ b/test/spec/spectest39.sh Wed Oct 10 22:58:21 2012 +0100
106.3 @@ -0,0 +1,2 @@
106.4 +#!/bin/sh
106.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest39.xml
107.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
107.2 +++ b/test/spec/spectest39.xml Wed Oct 10 22:58:21 2012 +0100
107.3 @@ -0,0 +1,58 @@
107.4 +<and>
107.5 + <if>
107.6 + <eq>
107.7 + <or>
107.8 + <true/>
107.9 + <define name="x"><true/></define>
107.10 + </or>
107.11 + <true/>
107.12 + </eq>
107.13 + <print newline="true">PASS</print>
107.14 + <expr>
107.15 + <print newline="true">FAIL</print>
107.16 + <false/>
107.17 + </expr>
107.18 + </if>
107.19 +
107.20 + <if>
107.21 + <eq>
107.22 + <or>
107.23 + <true/>
107.24 + <define name="x"><false/></define>
107.25 + </or>
107.26 + <true/>
107.27 + </eq>
107.28 + <print newline="true">PASS</print>
107.29 + <expr>
107.30 + <print newline="true">FAIL</print>
107.31 + <false/>
107.32 + </expr>
107.33 + </if>
107.34 +
107.35 + <if>
107.36 + <eq>
107.37 + <or>
107.38 + <false/>
107.39 + <define name="x"><false/></define>
107.40 + </or>
107.41 + <false/>
107.42 + </eq>
107.43 + <print newline="true">PASS</print>
107.44 + <expr>
107.45 + <print newline="true">FAIL</print>
107.46 + <false/>
107.47 + </expr>
107.48 + </if>
107.49 +
107.50 + <if>
107.51 + <eq>
107.52 + <or/>
107.53 + <true/>
107.54 + </eq>
107.55 + <print newline="true">PASS</print>
107.56 + <expr>
107.57 + <print newline="true">FAIL</print>
107.58 + <false/>
107.59 + </expr>
107.60 + </if>
107.61 +</and>
108.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
108.2 +++ b/test/spec/spectest4.sh Wed Oct 10 22:58:21 2012 +0100
108.3 @@ -0,0 +1,2 @@
108.4 +#!/bin/sh
108.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest4.xml
109.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
109.2 +++ b/test/spec/spectest4.xml Wed Oct 10 22:58:21 2012 +0100
109.3 @@ -0,0 +1,41 @@
109.4 +<expr>
109.5 + <define name="foo"/>
109.6 + <define name="constant"/>
109.7 +
109.8 + <and>
109.9 + <if>
109.10 + <eq>
109.11 + <foo>This is the 0xdeadbeef constant.</foo>
109.12 + <foo>
109.13 + <string>This is the</string>
109.14 + <integer>0xdeadbeef</integer>
109.15 + <string>constant.</string>
109.16 + </foo>
109.17 + </eq>
109.18 + <print newline="true">PASS</print>
109.19 + <expr>
109.20 + <print newline="true">FAIL</print>
109.21 + <false/>
109.22 + </expr>
109.23 + </if>
109.24 +
109.25 + <if>
109.26 + <eq>
109.27 + <foo>This is a <constant>constant</constant>.</foo>
109.28 + <foo>
109.29 + <string>This is a</string>
109.30 + <constant>
109.31 + <string>constant</string>
109.32 + </constant>
109.33 + <string>.</string>
109.34 + </foo>
109.35 + </eq>
109.36 + <print newline="true">PASS</print>
109.37 + <expr>
109.38 + <print newline="true">FAIL</print>
109.39 + <false/>
109.40 + </expr>
109.41 + </if>
109.42 +
109.43 + </and>
109.44 +</expr>
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
110.2 +++ b/test/spec/spectest40.sh Wed Oct 10 22:58:21 2012 +0100
110.3 @@ -0,0 +1,2 @@
110.4 +#!/bin/sh
110.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest40.xml
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
111.2 +++ b/test/spec/spectest40.xml Wed Oct 10 22:58:21 2012 +0100
111.3 @@ -0,0 +1,106 @@
111.4 +<and>
111.5 + <if>
111.6 + <eq>
111.7 + <not><true/></not>
111.8 + <false/>
111.9 + </eq>
111.10 + <print newline="true">PASS</print>
111.11 + <expr>
111.12 + <print newline="true">FAIL</print>
111.13 + <false/>
111.14 + </expr>
111.15 + </if>
111.16 +
111.17 + <if>
111.18 + <eq>
111.19 + <not><false/></not>
111.20 + <true/>
111.21 + </eq>
111.22 + <print newline="true">PASS</print>
111.23 + <expr>
111.24 + <print newline="true">FAIL</print>
111.25 + <false/>
111.26 + </expr>
111.27 + </if>
111.28 +
111.29 + <if>
111.30 + <eq>
111.31 + <not><nil/></not>
111.32 + <true/>
111.33 + </eq>
111.34 + <print newline="true">PASS</print>
111.35 + <expr>
111.36 + <print newline="true">FAIL</print>
111.37 + <false/>
111.38 + </expr>
111.39 + </if>
111.40 +
111.41 + <if>
111.42 + <eq>
111.43 + <not>1</not>
111.44 + <false/>
111.45 + </eq>
111.46 + <print newline="true">PASS</print>
111.47 + <expr>
111.48 + <print newline="true">FAIL</print>
111.49 + <false/>
111.50 + </expr>
111.51 + </if>
111.52 +
111.53 + <if>
111.54 + <eq>
111.55 + <not/>
111.56 + <true/>
111.57 + </eq>
111.58 + <print newline="true">PASS</print>
111.59 + <expr>
111.60 + <print newline="true">FAIL</print>
111.61 + <false/>
111.62 + </expr>
111.63 + </if>
111.64 +
111.65 + <if>
111.66 + <eq>
111.67 + <not>
111.68 + <true/>
111.69 + <true/>
111.70 + </not>
111.71 + <false/>
111.72 + </eq>
111.73 + <print newline="true">PASS</print>
111.74 + <expr>
111.75 + <print newline="true">FAIL</print>
111.76 + <false/>
111.77 + </expr>
111.78 + </if>
111.79 +
111.80 + <if>
111.81 + <eq>
111.82 + <not>
111.83 + <false/>
111.84 + <true/>
111.85 + </not>
111.86 + <true/>
111.87 + </eq>
111.88 + <print newline="true">PASS</print>
111.89 + <expr>
111.90 + <print newline="true">FAIL</print>
111.91 + <false/>
111.92 + </expr>
111.93 + </if>
111.94 +
111.95 + <if>
111.96 + <eq>
111.97 + <not>
111.98 + <false/>
111.99 + <false/>
111.100 + </not>
111.101 + <true/>
111.102 + </eq>
111.103 + <print newline="true">PASS</print>
111.104 + <expr>
111.105 + <print newline="true">FAIL</print>
111.106 + <false/>
111.107 + </expr>
111.108 + </if>
111.109 +</and>
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
112.2 +++ b/test/spec/spectest42.sh Wed Oct 10 22:58:21 2012 +0100
112.3 @@ -0,0 +1,2 @@
112.4 +#!/bin/sh
112.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest42.xml
113.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
113.2 +++ b/test/spec/spectest42.xml Wed Oct 10 22:58:21 2012 +0100
113.3 @@ -0,0 +1,38 @@
113.4 +<and>
113.5 + <if>
113.6 + <eq>
113.7 + <if>
113.8 + <eq>1 2</eq>
113.9 + <expr>
113.10 + <string>equal</string>
113.11 + </expr>
113.12 + <expr>
113.13 + <string>not equal</string>
113.14 + </expr>
113.15 + </if>
113.16 + <string>not equal</string>
113.17 + </eq>
113.18 + <print newline="true">PASS</print>
113.19 + <expr>
113.20 + <print newline="true">FAIL</print>
113.21 + <false/>
113.22 + </expr>
113.23 + </if>
113.24 +
113.25 + <if>
113.26 + <eq>
113.27 + <if>
113.28 + <eq>1 2</eq>
113.29 + <expr>
113.30 + <string>equal</string>
113.31 + </expr>
113.32 + </if>
113.33 + <nil/>
113.34 + </eq>
113.35 + <print newline="true">PASS</print>
113.36 + <expr>
113.37 + <print newline="true">FAIL</print>
113.38 + <false/>
113.39 + </expr>
113.40 + </if>
113.41 +</and>
114.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
114.2 +++ b/test/spec/spectest43.sh Wed Oct 10 22:58:21 2012 +0100
114.3 @@ -0,0 +1,2 @@
114.4 +#!/bin/sh
114.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest43.xml
115.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
115.2 +++ b/test/spec/spectest43.xml Wed Oct 10 22:58:21 2012 +0100
115.3 @@ -0,0 +1,73 @@
115.4 +<expr>
115.5 + <define name="test-one" args="x">
115.6 + <switch>
115.7 + <case>
115.8 + <eq><x/>1</eq>
115.9 + 1
115.10 + </case>
115.11 + <case>
115.12 + <true/>
115.13 + 2
115.14 + </case>
115.15 + </switch>
115.16 + </define>
115.17 +
115.18 + <define name="test-two" args="x">
115.19 + <switch>
115.20 + <case>
115.21 + <eq><x/>1</eq>
115.22 + 1
115.23 + </case>
115.24 + </switch>
115.25 + </define>
115.26 +
115.27 + <and>
115.28 + <if>
115.29 + <eq>
115.30 + <test-one>1</test-one>
115.31 + <integer>1</integer>
115.32 + </eq>
115.33 + <print newline="true">PASS</print>
115.34 + <expr>
115.35 + <print newline="true">FAIL</print>
115.36 + <false/>
115.37 + </expr>
115.38 + </if>
115.39 +
115.40 + <if>
115.41 + <eq>
115.42 + <test-one>2</test-one>
115.43 + <integer>2</integer>
115.44 + </eq>
115.45 + <print newline="true">PASS</print>
115.46 + <expr>
115.47 + <print newline="true">FAIL</print>
115.48 + <false/>
115.49 + </expr>
115.50 + </if>
115.51 +
115.52 + <if>
115.53 + <eq>
115.54 + <test-two>1</test-two>
115.55 + <integer>1</integer>
115.56 + </eq>
115.57 + <print newline="true">PASS</print>
115.58 + <expr>
115.59 + <print newline="true">FAIL</print>
115.60 + <false/>
115.61 + </expr>
115.62 + </if>
115.63 +
115.64 + <if>
115.65 + <eq>
115.66 + <test-two>2</test-two>
115.67 + <nil/>
115.68 + </eq>
115.69 + <print newline="true">PASS</print>
115.70 + <expr>
115.71 + <print newline="true">FAIL</print>
115.72 + <false/>
115.73 + </expr>
115.74 + </if>
115.75 + </and>
115.76 +</expr>
116.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
116.2 +++ b/test/spec/spectest45.sh Wed Oct 10 22:58:21 2012 +0100
116.3 @@ -0,0 +1,18 @@
116.4 +#!/bin/sh
116.5 +$top_builddir/src/xexpr $srcdir/spectest45.xml > spectest45.out
116.6 +cat <<-EOF > spectest45.ref
116.7 +10
116.8 +9
116.9 +8
116.10 +7
116.11 +6
116.12 +5
116.13 +4
116.14 +3
116.15 +2
116.16 +1
116.17 +EOF
116.18 +cmp spectest45.out spectest45.ref
116.19 +retval=$?
116.20 +rm -f spectest45.out spectest45.ref
116.21 +exit $retval
117.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
117.2 +++ b/test/spec/spectest45.xml Wed Oct 10 22:58:21 2012 +0100
117.3 @@ -0,0 +1,10 @@
117.4 +<expr>
117.5 + <set name="x">10</set>
117.6 + <while>
117.7 + <gt><x/> 0</gt>
117.8 + <expr>
117.9 + <print newline="true"><x/></print>
117.10 + <subtract><x/> 1</subtract>
117.11 + </expr>
117.12 + </while>
117.13 +</expr>
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
118.2 +++ b/test/spec/spectest46.sh Wed Oct 10 22:58:21 2012 +0100
118.3 @@ -0,0 +1,18 @@
118.4 +#!/bin/sh
118.5 +$top_builddir/src/xexpr $srcdir/spectest46.xml > spectest46.out
118.6 +cat <<-EOF > spectest46.ref
118.7 +10
118.8 +9
118.9 +8
118.10 +7
118.11 +6
118.12 +5
118.13 +4
118.14 +3
118.15 +2
118.16 +1
118.17 +EOF
118.18 +cmp spectest46.out spectest46.ref
118.19 +retval=$?
118.20 +rm -f spectest46.out spectest46.ref
118.21 +exit $retval
119.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
119.2 +++ b/test/spec/spectest46.xml Wed Oct 10 22:58:21 2012 +0100
119.3 @@ -0,0 +1,10 @@
119.4 +<expr>
119.5 + <set name="x">10</set>
119.6 + <do>
119.7 + <expr>
119.8 + <print newline="true"><x/></print>
119.9 + <subtract><x/> 1</subtract>
119.10 + </expr>
119.11 + <gt><x/> 0</gt>
119.12 + </do>
119.13 +</expr>
120.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
120.2 +++ b/test/spec/spectest48.sh Wed Oct 10 22:58:21 2012 +0100
120.3 @@ -0,0 +1,2 @@
120.4 +#!/bin/sh
120.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest48.xml
121.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
121.2 +++ b/test/spec/spectest48.xml Wed Oct 10 22:58:21 2012 +0100
121.3 @@ -0,0 +1,1 @@
121.4 +<true xmlns:xexpr="http://www.ebt.com/xexpr"/>
122.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
122.2 +++ b/test/spec/spectest49.sh Wed Oct 10 22:58:21 2012 +0100
122.3 @@ -0,0 +1,2 @@
122.4 +#!/bin/sh
122.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest49.xml
123.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
123.2 +++ b/test/spec/spectest49.xml Wed Oct 10 22:58:21 2012 +0100
123.3 @@ -0,0 +1,4 @@
123.4 +<!DOCTYPE xexpr PUBLIC "-//EBT//DTD XML Expression Language//EN" "xexpr.dtd">
123.5 +<xexpr xmlns="http://www.ebt.com/xexpr">
123.6 + <true/>
123.7 +</xexpr>
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
124.2 +++ b/test/spec/spectest5.sh Wed Oct 10 22:58:21 2012 +0100
124.3 @@ -0,0 +1,2 @@
124.4 +#!/bin/sh
124.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest5.xml
125.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125.2 +++ b/test/spec/spectest5.xml Wed Oct 10 22:58:21 2012 +0100
125.3 @@ -0,0 +1,19 @@
125.4 +<expr>
125.5 + <define name="foo"/>
125.6 +
125.7 + <if>
125.8 + <eq>
125.9 + <foo>
125.10 + This is a test.
125.11 + </foo>
125.12 + <foo>
125.13 + <string>This is a test.</string>
125.14 + </foo>
125.15 + </eq>
125.16 + <print newline="true">PASS</print>
125.17 + <expr>
125.18 + <print newline="true">FAIL</print>
125.19 + <false/>
125.20 + </expr>
125.21 + </if>
125.22 +</expr>
126.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
126.2 +++ b/test/spec/spectest6.sh Wed Oct 10 22:58:21 2012 +0100
126.3 @@ -0,0 +1,2 @@
126.4 +#!/bin/sh
126.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest6.xml
127.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
127.2 +++ b/test/spec/spectest6.xml Wed Oct 10 22:58:21 2012 +0100
127.3 @@ -0,0 +1,22 @@
127.4 +<expr>
127.5 + <define name="foo"/>
127.6 +
127.7 + <if>
127.8 + <eq>
127.9 + <foo>
127.10 + <string>
127.11 + abc
127.12 + def
127.13 + </string>
127.14 + </foo>
127.15 + <foo>
127.16 + <string> abc def </string>
127.17 + </foo>
127.18 + </eq>
127.19 + <print newline="true">PASS</print>
127.20 + <expr>
127.21 + <print newline="true">FAIL</print>
127.22 + <false/>
127.23 + </expr>
127.24 + </if>
127.25 +</expr>
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
128.2 +++ b/test/spec/spectest7.sh Wed Oct 10 22:58:21 2012 +0100
128.3 @@ -0,0 +1,2 @@
128.4 +#!/bin/sh
128.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest7.xml
129.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
129.2 +++ b/test/spec/spectest7.xml Wed Oct 10 22:58:21 2012 +0100
129.3 @@ -0,0 +1,16 @@
129.4 +<expr>
129.5 + <define name="square" args="x">
129.6 + <multiply><x/><x/></multiply>
129.7 + </define>
129.8 + <if>
129.9 + <eq>
129.10 + <square>2<define name="x">4</define></square>
129.11 + 16
129.12 + </eq>
129.13 + <print newline="true">PASS</print>
129.14 + <expr>
129.15 + <print newline="true">FAIL</print>
129.16 + <false/>
129.17 + </expr>
129.18 + </if>
129.19 +</expr>
130.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
130.2 +++ b/test/spec/spectest8.sh Wed Oct 10 22:58:21 2012 +0100
130.3 @@ -0,0 +1,2 @@
130.4 +#!/bin/sh
130.5 +$top_builddir/src/xexpr --test-result $srcdir/spectest8.xml
131.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
131.2 +++ b/test/spec/spectest8.xml Wed Oct 10 22:58:21 2012 +0100
131.3 @@ -0,0 +1,54 @@
131.4 +<and>
131.5 + <expr>
131.6 + <define name="factorial" args="x">
131.7 + <if>
131.8 + <lt><x/>2</lt>
131.9 + <x/>
131.10 + <multiply>
131.11 + <x/>
131.12 + <factorial><subtract><x/>1</subtract></factorial>
131.13 + </multiply>
131.14 + </if>
131.15 + </define>
131.16 + <if>
131.17 + <eq>
131.18 + <factorial>7</factorial>
131.19 + 5040
131.20 + </eq>
131.21 + <print newline="true">PASS</print>
131.22 + <expr>
131.23 + <print newline="true">FAIL</print>
131.24 + <false/>
131.25 + </expr>
131.26 + </if>
131.27 + </expr>
131.28 + <expr>
131.29 + <define name="factorial" args="x">
131.30 + <define name="iterator" args="product counter max">
131.31 + <if>
131.32 + <gt><counter/><max/></gt>
131.33 + <product/>
131.34 + <iterator>
131.35 + <multiply><counter/><product/></multiply>
131.36 + <add><counter/>1</add>
131.37 + <max/>
131.38 + </iterator>
131.39 + </if>
131.40 + </define>
131.41 +
131.42 + <iterator>1 1 <x/></iterator>
131.43 + </define>
131.44 +
131.45 + <if>
131.46 + <eq>
131.47 + <factorial>7</factorial>
131.48 + 5040
131.49 + </eq>
131.50 + <print newline="true">PASS</print>
131.51 + <expr>
131.52 + <print newline="true">FAIL</print>
131.53 + <false/>
131.54 + </expr>
131.55 + </if>
131.56 + </expr>
131.57 +</and>