xpath.c revision 2bdabbd711356e534940431053523f1538d1a93e
13473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
23473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xpath.c: XML Path Language implementation
33473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *          XPath is a language for addressing parts of an XML document,
43473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *          designed to be used by both XSLT and XPointer
53473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Reference: W3C Recommendation 16 November 1999
73473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     http://www.w3.org/TR/1999/REC-xpath-19991116
83473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Public reference:
93473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     http://www.w3.org/TR/xpath
103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
11cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * See Copyright for the status of this software
123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13c5d64345cf19bfd72418eb0a837869b0462e9130Daniel Veillard * Author: daniel@veillard.com
143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1734ce8bece2f22cc99d25221b77315cd008f4866bDaniel Veillard#define IN_LIBXML
1870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese#include "libxml.h"
193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <string.h>
213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_SYS_TYPES_H
233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <sys/types.h>
243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_MATH_H
263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <math.h>
273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_FLOAT_H
293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <float.h>
303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_CTYPE_H
323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <ctype.h>
333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
345792e16f0562d206e1ef4e611f7b43ec53c92149Daniel Veillard#ifdef HAVE_SIGNAL_H
35b45c43be206b8c824558269731128c6a64599a54Daniel Veillard#include <signal.h>
36b45c43be206b8c824558269731128c6a64599a54Daniel Veillard#endif
373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlmemory.h>
393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/tree.h>
403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/valid.h>
413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpath.h>
423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpathInternals.h>
433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/parserInternals.h>
443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/hash.h>
453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpointer.h>
473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_DEBUG_ENABLED
493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/debugXML.h>
503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlerror.h>
528146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#include <libxml/threads.h>
533c01b1d81b696fe8624b6d7e26ec0ebffcc7c06bDaniel Veillard#include <libxml/globals.h>
5456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef LIBXML_PATTERN_ENABLED
5556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#include <libxml/pattern.h>
5656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
5756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
5856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef LIBXML_PATTERN_ENABLED
59fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#define XPATH_STREAMING
6056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard#define TODO 								\
63d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    xmlGenericError(xmlGenericErrorContext,				\
64d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    "Unimplemented block at %s:%d\n",				\
65d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            __FILE__, __LINE__);
66d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
67d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack/*
6897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik* XP_PATTERN_TO_ANY_NODE_ENABLED: when an XPath expression can be
6997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   evaluated using the streaming mode (pattern.c) then this is used to
7097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   enable resolution to nodes of type text-node, cdata-section-node,
7197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   comment-node and pi-node. The only known scenario where this is
7297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   needed is an expression like "foo//.", "//.", etc.; i.e. an expression
7397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   where the final node to be selected can be of any type.
7497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   Disabling this #define will result in an incorrect evaluation to
7597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   only element-nodes and the document node.
7697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*/
7797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#define XP_PATTERN_TO_ANY_NODE_ENABLED
782bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
792bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik/*
802bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik* XP_FAST_NON_ELEM_COMPARISON:
812bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik* If defined, this will use xmlXPathCmpNodesExt() instead of
822bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik* xmlXPathCmpNodes(). The new function is optimized comparison of
832bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik* non-element nodes; actually it will speed up comparison only if
842bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik* xmlXPathOrderDocElems() was called in order to index the elements of
852bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik* a tree in document order; Libxslt does such an indexing, thus it will
862bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik* benefit from this optimization.
872bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik*/
882bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik#define XP_FAST_NON_ELEM_COMPARISON
8997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik/*
90d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack * TODO:
91d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack * There are a few spots where some tests are done which depend upon ascii
92d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack * data.  These should be enhanced for full UTF8 support (see particularly
93d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
94d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack */
9597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
9621e4ef20f64ebd740ebac0ead5d85a5631d2db5eWilliam M. Brack#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Floating point stuff				*
1009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
1019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
1029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
103c0631a608f62902eca453096f0b2fc5b449b0b0aDaniel Veillard#ifndef TRIO_REPLACE_STDIO
104cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard#define TRIO_PUBLIC static
105c0631a608f62902eca453096f0b2fc5b449b0b0aDaniel Veillard#endif
106cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard#include "trionan.c"
107cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
1083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
1093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The lack of portability of this section of the libc is annoying !
1103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathNAN = 0;
1123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathPINF = 1;
1133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathNINF = -1;
11424505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillardstatic double xmlXPathNZERO = 0; /* not exported from headers */
11520ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillardstatic int xmlXPathInitialized = 0;
1163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathInit:
1193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initialize the XPath environment
1213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
1233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathInit(void) {
12420ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    if (xmlXPathInitialized) return;
1253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
126450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathPINF = trio_pinf();
127450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathNINF = trio_ninf();
128450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathNAN = trio_nan();
1295fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    xmlXPathNZERO = trio_nzero();
1303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13120ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    xmlXPathInitialized = 1;
1323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
1333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
134cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard/**
135cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * xmlXPathIsNaN:
136cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * @val:  a double value
137cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
138cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Provides a portable isnan() function to detect whether a double
139cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * is a NotaNumber. Based on trio code
140cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * http://sourceforge.net/projects/ctrio/
141cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
142cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Returns 1 if the value is a NaN, 0 otherwise
143cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard */
144cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillardint
145cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel VeillardxmlXPathIsNaN(double val) {
146cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    return(trio_isnan(val));
147cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard}
148cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
149cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard/**
150cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * xmlXPathIsInf:
151cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * @val:  a double value
152cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
153cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Provides a portable isinf() function to detect whether a double
154cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * is a +Infinite or -Infinite. Based on trio code
155cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * http://sourceforge.net/projects/ctrio/
156cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
157cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise
158cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard */
159cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillardint
160cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel VeillardxmlXPathIsInf(double val) {
161cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    return(trio_isinf(val));
162cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard}
163cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
1644432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#endif /* SCHEMAS or XPATH */
1654432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#ifdef LIBXML_XPATH_ENABLED
1665fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard/**
1675fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * xmlXPathGetSign:
1685fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * @val:  a double value
1695fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard *
1705fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Provides a portable function to detect the sign of a double
1715fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Modified from trio code
1725fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * http://sourceforge.net/projects/ctrio/
1735fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard *
1745fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Returns 1 if the value is Negative, 0 if positive
1755fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard */
17621458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillardstatic int
1775fc1f0893af6ffe76453ac16817204a866bdeab2Daniel VeillardxmlXPathGetSign(double val) {
17821458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    return(trio_signbit(val));
1795fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard}
1805fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
1815fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
182d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/*
183d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * TODO: when compatibility allows remove all "fake node libxslt" strings
184d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard *       the test should just be name[0] = ' '
185d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard */
186d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG */
187d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_STEP */
188d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_STEP_NTH */
189d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_EXPR */
190d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_EVAL_COUNTS */
191d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard
192d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic xmlNs xmlXPathXMLNamespaceStruct = {
193d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    NULL,
194d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    XML_NAMESPACE_DECL,
195d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    XML_XML_NAMESPACE,
196d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    BAD_CAST "xml",
197d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    NULL
198d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard};
199d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
200d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard#ifndef LIBXML_THREAD_ENABLED
201d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/*
202d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * Optimizer is disabled only when threaded apps are detected while
203d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * the library ain't compiled for thread safety.
204d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard */
205d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic int xmlXPathDisableOptimizer = 0;
206d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard#endif
207d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard
2083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
209d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *									*
210d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *			Error handling routines				*
211d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *									*
212d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard ************************************************************************/
213d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
21424505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard/**
21524505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard * XP_ERRORNULL:
21624505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard * @X:  the error code
21724505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard *
21824505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard * Macro to raise an XPath error and return NULL.
21924505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard */
22024505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard#define XP_ERRORNULL(X)							\
22124505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard    { xmlXPathErr(ctxt, X); return(NULL); }
22224505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard
223081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack/*
224081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * The array xmlXPathErrorMessages corresponds to the enum xmlXPathError
225081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack */
226d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardstatic const char *xmlXPathErrorMessages[] = {
227d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Ok\n",
228d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Number encoding\n",
229d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Unfinished literal\n",
230d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Start of literal\n",
231d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Expected $ for variable reference\n",
232d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Undefined variable\n",
233d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid predicate\n",
234d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid expression\n",
235d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Missing closing curly brace\n",
236d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Unregistered function\n",
237d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid operand\n",
238d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid type\n",
239d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid number of arguments\n",
240d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid context size\n",
241d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid context position\n",
242d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Memory allocation error\n",
243d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Syntax error\n",
244d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Resource error\n",
245d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Sub resource error\n",
246d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Undefined namespace prefix\n",
247d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Encoding error\n",
24857b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard    "Char out of XML range\n",
249cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack    "Invalid or incomplete context\n",
250cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack    "?? Unknown error ??\n"	/* Must be last in the list! */
251d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard};
252cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack#define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) /	\
253cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack		   sizeof(xmlXPathErrorMessages[0])) - 1)
254d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/**
255d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * xmlXPathErrMemory:
256d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @ctxt:  an XPath context
257d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @extra:  extra informations
258d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *
259d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * Handle a redefinition of attribute error
260d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard */
261d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardstatic void
262d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel VeillardxmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra)
263d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard{
264d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    if (ctxt != NULL) {
265d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        if (extra) {
266d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            xmlChar buf[200];
267d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
268d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            xmlStrPrintf(buf, 200,
269d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                         BAD_CAST "Memory allocation failed : %s\n",
270d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                         extra);
271d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            ctxt->lastError.message = (char *) xmlStrdup(buf);
272d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        } else {
273d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            ctxt->lastError.message = (char *)
274d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	       xmlStrdup(BAD_CAST "Memory allocation failed\n");
275d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        }
276d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        ctxt->lastError.domain = XML_FROM_XPATH;
277d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        ctxt->lastError.code = XML_ERR_NO_MEMORY;
278d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	if (ctxt->error != NULL)
279d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    ctxt->error(ctxt->userData, &ctxt->lastError);
280d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    } else {
281d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        if (extra)
282659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard            __xmlRaiseError(NULL, NULL, NULL,
283d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            NULL, NULL, XML_FROM_XPATH,
284d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
285d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            extra, NULL, NULL, 0, 0,
286d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            "Memory allocation failed : %s\n", extra);
287d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        else
288659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard            __xmlRaiseError(NULL, NULL, NULL,
289d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            NULL, NULL, XML_FROM_XPATH,
290d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
291d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            NULL, NULL, NULL, 0, 0,
292d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            "Memory allocation failed\n");
293d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    }
294d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard}
295d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
296d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/**
2978de5c0bd79cceeca3d55d6dbf8f0248b7239e050Daniel Veillard * xmlXPathPErrMemory:
298d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @ctxt:  an XPath parser context
299d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @extra:  extra informations
300d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *
301d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * Handle a redefinition of attribute error
302d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard */
303d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardstatic void
304d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel VeillardxmlXPathPErrMemory(xmlXPathParserContextPtr ctxt, const char *extra)
305d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard{
306d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    if (ctxt == NULL)
307d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	xmlXPathErrMemory(NULL, extra);
30811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    else {
30911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard	ctxt->error = XPATH_MEMORY_ERROR;
310d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	xmlXPathErrMemory(ctxt->context, extra);
31111ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    }
312d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard}
313d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
314d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/**
315d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * xmlXPathErr:
316d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @ctxt:  a XPath parser context
317d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @error:  the error code
318d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *
319cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack * Handle an XPath error
320d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard */
321d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardvoid
322d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel VeillardxmlXPathErr(xmlXPathParserContextPtr ctxt, int error)
323d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard{
324cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack    if ((error < 0) || (error > MAXERRNO))
325cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack	error = MAXERRNO;
326f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard    if (ctxt == NULL) {
327659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard	__xmlRaiseError(NULL, NULL, NULL,
328d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			NULL, NULL, XML_FROM_XPATH,
329d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
330d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			XML_ERR_ERROR, NULL, 0,
331d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			NULL, NULL, NULL, 0, 0,
332d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			xmlXPathErrorMessages[error]);
333d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	return;
334d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    }
335f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard    ctxt->error = error;
336f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard    if (ctxt->context == NULL) {
337f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard	__xmlRaiseError(NULL, NULL, NULL,
338f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			NULL, NULL, XML_FROM_XPATH,
339f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
340f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			XML_ERR_ERROR, NULL, 0,
341f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			(const char *) ctxt->base, NULL, NULL,
342f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			ctxt->cur - ctxt->base, 0,
343f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			xmlXPathErrorMessages[error]);
344f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard	return;
345f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard    }
346d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.domain = XML_FROM_XPATH;
347d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.code = error + XML_XPATH_EXPRESSION_OK -
348d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                           XPATH_EXPRESSION_OK;
349fcf719ce0a94f0d438f69b73cd1ca31a7000da81Daniel Veillard    ctxt->context->lastError.level = XML_ERR_ERROR;
350d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
351d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
352d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.node = ctxt->context->debugNode;
353d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    if (ctxt->context->error != NULL) {
354d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	ctxt->context->error(ctxt->context->userData,
355d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	                     &ctxt->context->lastError);
356d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    } else {
357659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard	__xmlRaiseError(NULL, NULL, NULL,
358d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			NULL, ctxt->context->debugNode, XML_FROM_XPATH,
359d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
360d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			XML_ERR_ERROR, NULL, 0,
361d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			(const char *) ctxt->base, NULL, NULL,
362d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			ctxt->cur - ctxt->base, 0,
363d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			xmlXPathErrorMessages[error]);
364d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    }
365d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
366d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard}
367d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
368d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/**
369d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * xmlXPatherror:
370d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @ctxt:  the XPath Parser context
371d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @file:  the file name
372d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @line:  the line number
373d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @no:  the error number
374d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *
375d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * Formats an error message.
376d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard */
377d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardvoid
378d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel VeillardxmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED,
379d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard              int line ATTRIBUTE_UNUSED, int no) {
380d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    xmlXPathErr(ctxt, no);
381d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard}
382d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
383d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
384d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/************************************************************************
3859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
3869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Parser Types					*
3879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
3889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
3899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/*
3919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Types are private:
3929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
3939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
3959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_END=0,
3969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_AND,
3979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_OR,
3989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_EQUAL,
3999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_CMP,
4009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_PLUS,
4019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_MULT,
4029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_UNION,
4039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_ROOT,
4049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_NODE,
4059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_RESET,
4069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_COLLECT,
4079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_VALUE,
4089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_VARIABLE,
4099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_FUNCTION,
4109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_ARG,
4119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_PREDICATE,
412d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    XPATH_OP_FILTER,
4139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_SORT
4149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#ifdef LIBXML_XPTR_ENABLED
4159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ,XPATH_OP_RANGETO
4169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif
4179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathOp;
4189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
4209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ANCESTOR = 1,
4219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ANCESTOR_OR_SELF,
4229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ATTRIBUTE,
4239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_CHILD,
4249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_DESCENDANT,
4259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_DESCENDANT_OR_SELF,
4269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_FOLLOWING,
4279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_FOLLOWING_SIBLING,
4289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_NAMESPACE,
4299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PARENT,
4309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PRECEDING,
4319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PRECEDING_SIBLING,
4329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_SELF
4339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathAxisVal;
4349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
4369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NONE = 0,
4379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_TYPE = 1,
4389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_PI = 2,
4399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_ALL = 3,
4409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NS = 4,
4419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NAME = 5
4429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathTestVal;
4439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
4459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_NODE = 0,
4469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_COMMENT = XML_COMMENT_NODE,
4479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_TEXT = XML_TEXT_NODE,
4489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_PI = XML_PI_NODE
4499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathTypeVal;
4509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef struct _xmlXPathStepOp xmlXPathStepOp;
4539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef xmlXPathStepOp *xmlXPathStepOpPtr;
4549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardstruct _xmlXPathStepOp {
455081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    xmlXPathOp op;		/* The identifier of the operation */
456081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int ch1;			/* First child */
457081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int ch2;			/* Second child */
4589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value;
4599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value2;
4609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value3;
4619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    void *value4;
4629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    void *value5;
463e39a93d0d3df9907cf3538cd3f1fbbe4106e893dDaniel Veillard    void *cache;
46442596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard    void *cacheURI;
4659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard};
4669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardstruct _xmlXPathCompExpr {
468081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int nbStep;			/* Number of steps in this expression */
469081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int maxStep;		/* Maximum number of steps allocated */
470081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    xmlXPathStepOp *steps;	/* ops for computation of this expression */
471081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int last;			/* index of last step in expression */
472081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    xmlChar *expr;		/* the expression being computed */
4734773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    xmlDictPtr dict;		/* the dictionnary to use if any */
474f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
475f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int nb;
476f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlChar *string;
477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
47856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
47956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlPatternPtr stream;
48056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
4819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard};
4829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
4849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
4859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Parser Type functions 				*
4869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
4879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
4889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
4909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathNewCompExpr:
4919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
4929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Create a new Xpath component
4939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
4949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error
4959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
49656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathCompExprPtr
4979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathNewCompExpr(void) {
4989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprPtr cur;
4999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
5009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
5019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (cur == NULL) {
502d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "allocating component\n");
5039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
5049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
5059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(cur, 0, sizeof(xmlXPathCompExpr));
5069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->maxStep = 10;
5079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->nbStep = 0;
5089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
5099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                                   sizeof(xmlXPathStepOp));
5109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (cur->steps == NULL) {
511d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "allocating steps\n");
5129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(cur);
5139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
5149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
5159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
5169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->last = -1;
517f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
518f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    cur->nb = 0;
519f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
5209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(cur);
5219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
5229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
5239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
5249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathFreeCompExpr:
5259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  an XPATH comp
5269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
5279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Free up the memory allocated by @comp
5289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
5299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardvoid
530f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
5329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathStepOpPtr op;
5339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
5349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
5359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp == NULL)
536f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return;
5374773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if (comp->dict == NULL) {
5384773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	for (i = 0; i < comp->nbStep; i++) {
5394773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    op = &comp->steps[i];
5404773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    if (op->value4 != NULL) {
5414773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		if (op->op == XPATH_OP_VALUE)
5424773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		    xmlXPathFreeObject(op->value4);
5434773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		else
5444773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		    xmlFree(op->value4);
5454773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    }
5464773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    if (op->value5 != NULL)
5474773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		xmlFree(op->value5);
5484773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	}
5494773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    } else {
5504773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	for (i = 0; i < comp->nbStep; i++) {
5514773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    op = &comp->steps[i];
5524773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    if (op->value4 != NULL) {
5534773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		if (op->op == XPATH_OP_VALUE)
5544773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		    xmlXPathFreeObject(op->value4);
5554773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    }
5564773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	}
5574773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        xmlDictFree(comp->dict);
5589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
5599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp->steps != NULL) {
560f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlFree(comp->steps);
5619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
562f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
563f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (comp->string != NULL) {
564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlFree(comp->string);
565f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
56756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
56856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp->stream != NULL) {
56956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        xmlFreePatternList(comp->stream);
57056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
57156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
572118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    if (comp->expr != NULL) {
573118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard        xmlFree(comp->expr);
574118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    }
575f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
5769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlFree(comp);
5779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
5789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
5799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
5809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompExprAdd:
5819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the compiled expression
5829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ch1: first child index
5839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ch2: second child index
5849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @op:  an op
5859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value:  the first int value
5869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value2:  the second int value
5879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value3:  the third int value
5889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value4:  the first string value
5899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value5:  the second string value
5909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
591081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Add a step to an XPath Compiled Expression
5929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
5939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns -1 in case of failure, the index otherwise
5949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
59556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
5969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
5979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard   xmlXPathOp op, int value,
5989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard   int value2, int value3, void *value4, void *value5) {
5999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp->nbStep >= comp->maxStep) {
6009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathStepOp *real;
6019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	comp->maxStep *= 2;
6039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
6049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		                      comp->maxStep * sizeof(xmlXPathStepOp));
6059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (real == NULL) {
6069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    comp->maxStep /= 2;
607d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "adding step\n");
6089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    return(-1);
6099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
6109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	comp->steps = real;
6119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
6129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->last = comp->nbStep;
6139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].ch1 = ch1;
6149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].ch2 = ch2;
6159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].op = op;
6169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value = value;
6179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value2 = value2;
6189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value3 = value3;
6194773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if ((comp->dict != NULL) &&
6204773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) ||
6214773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	 (op == XPATH_OP_COLLECT))) {
6224773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        if (value4 != NULL) {
623b337795500cbe3fc47ac2b81f3d955126c6fbfdeDaniel Veillard	    comp->steps[comp->nbStep].value4 = (xmlChar *)
624c07ed5e6a14fb801cfd6bbb2a582caf726e5324eWilliam M. Brack	        (void *)xmlDictLookup(comp->dict, value4, -1);
6254773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    xmlFree(value4);
6264773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	} else
6274773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    comp->steps[comp->nbStep].value4 = NULL;
6284773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        if (value5 != NULL) {
629b337795500cbe3fc47ac2b81f3d955126c6fbfdeDaniel Veillard	    comp->steps[comp->nbStep].value5 = (xmlChar *)
630c07ed5e6a14fb801cfd6bbb2a582caf726e5324eWilliam M. Brack	        (void *)xmlDictLookup(comp->dict, value5, -1);
6314773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    xmlFree(value5);
6324773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	} else
6334773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    comp->steps[comp->nbStep].value5 = NULL;
6344773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    } else {
6354773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	comp->steps[comp->nbStep].value4 = value4;
6364773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	comp->steps[comp->nbStep].value5 = value5;
6374773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    }
638e39a93d0d3df9907cf3538cd3f1fbbe4106e893dDaniel Veillard    comp->steps[comp->nbStep].cache = NULL;
6399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(comp->nbStep++);
6409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
6419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
642f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
643f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompSwap:
644f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @comp:  the compiled expression
645f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op: operation index
646f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
647f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Swaps 2 operations in the compiled expression
648f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
649f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic void
650f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompSwap(xmlXPathStepOpPtr op) {
651f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int tmp;
652f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
653bc6f759ac9b41773e3643ad288b5214732051c98Daniel Veillard#ifndef LIBXML_THREAD_ENABLED
6548146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    /*
6558146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * Since this manipulates possibly shared variables, this is
656081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * disabled if one detects that the library is used in a multithreaded
6578146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * application
6588146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     */
6598146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    if (xmlXPathDisableOptimizer)
6608146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard	return;
6618146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
6628146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard
663f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    tmp = op->ch1;
664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    op->ch1 = op->ch2;
665f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    op->ch2 = tmp;
666f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
667f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
668d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5)	\
669d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathCompExprAdd(ctxt->comp, (op1), (op2),			\
670d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	                (op), (val), (val2), (val3), (val4), (val5))
6719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5)			\
6729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1,		\
6739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                (op), (val), (val2), (val3), (val4), (val5))
6749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_LEAVE_EXPR(op, val, val2) 					\
6769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
6779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_UNARY_EXPR(op, ch, val, val2) 				\
6799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
6809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) 			\
682081719182de3d15e6a438f32fdc3d1ca240a08e8William M. BrackxmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op),			\
683081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack			(val), (val2), 0 ,NULL ,NULL)
6849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
6863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
6873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 		Debugging related functions				*
6883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
6893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
6903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define STRANGE 							\
6923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,				\
6933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "Internal error at %s:%d\n",				\
6943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            __FILE__, __LINE__);
6953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_DEBUG_ENABLED
69756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
69856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
6993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
7003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
7013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
7033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
7043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
7053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
7063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
7073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "Node is NULL !\n");
7083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
7093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur->type == XML_DOCUMENT_NODE) ||
7133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     (cur->type == XML_HTML_DOCUMENT_NODE)) {
7143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
7153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, " /\n");
7163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->type == XML_ATTRIBUTE_NODE)
7173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
7183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
7193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlDebugDumpOneNode(output, cur, depth);
7203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
72156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
72256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) {
723f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    xmlNodePtr tmp;
724f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    int i;
725f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    char shift[100];
726f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
727f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
728f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
729f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
730f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    if (cur == NULL) {
731f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, shift);
732f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, "Node is NULL !\n");
733f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	return;
734f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
735f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
736f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
737f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    while (cur != NULL) {
738f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	tmp = cur;
739f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	cur = cur->next;
740f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	xmlDebugDumpOneNode(output, tmp, depth);
741f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
742f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard}
7433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
74556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
7463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
7473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
7483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
7503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
7513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
7523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
7543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
7553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "NodeSet is NULL !\n");
7563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
7573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
760911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (cur != NULL) {
761911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
762911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < cur->nodeNr;i++) {
763911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    fprintf(output, shift);
764911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    fprintf(output, "%d", i + 1);
765911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
766911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
7673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
7693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
77156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) {
772f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    int i;
773f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    char shift[100];
774f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
775f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
776f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
777f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
778f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
779f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) {
780f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, shift);
781f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, "Value Tree is NULL !\n");
782f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	return;
783f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
784f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
785f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
786f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    fprintf(output, shift);
787f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    fprintf(output, "%d", i + 1);
788f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);
789f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard}
7903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(LIBXML_XPTR_ENABLED)
79156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
79256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
7933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
7943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
7953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
7973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
7983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
7993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
8013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
8023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "LocationSet is NULL !\n");
8033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
8043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->locNr;i++) {
8083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
8093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "%d : ", i + 1);
8103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1);
8113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
813017b108fcf16dbce05ca7ebd75763f3d888abb5fDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
8143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
815afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
816afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathDebugDumpObject:
817afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @output:  the FILE * to dump the output
818afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @cur:  the object to inspect
819afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @depth:  indentation level
820afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
821afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Dump the content of the object for debugging purposes
822afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
823afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardvoid
824afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
8253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
8263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
8273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
828a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (output == NULL) return;
829a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
8303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
8313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
8323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
8333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
83597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    fprintf(output, shift);
8363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
8383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "Object is empty (NULL)\n");
8393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
8403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(cur->type) {
8423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_UNDEFINED:
8433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is uninitialized\n");
8443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
8463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Node Set :\n");
8473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
8483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_XSLT_TREE:
8503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is an XSLT value tree :\n");
851f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	    xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth);
8523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
8543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Boolean : ");
8553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (cur->boolval) fprintf(output, "true\n");
8563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else fprintf(output, "false\n");
8573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
859cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	    switch (xmlXPathIsInf(cur->floatval)) {
860357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    case 1:
8615fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard		fprintf(output, "Object is a number : Infinity\n");
862357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		break;
863357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    case -1:
864357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		fprintf(output, "Object is a number : -Infinity\n");
865357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		break;
866357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    default:
867cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard		if (xmlXPathIsNaN(cur->floatval)) {
868357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		    fprintf(output, "Object is a number : NaN\n");
869d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		} else if (cur->floatval == 0 && xmlXPathGetSign(cur->floatval) != 0) {
870d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    fprintf(output, "Object is a number : 0\n");
871357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		} else {
872357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		    fprintf(output, "Object is a number : %0g\n", cur->floatval);
873357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		}
874357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    }
8753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
8773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a string : ");
8783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlDebugDumpString(output, cur->stringval);
8793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "\n");
8803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
8823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a point : index %d in node", cur->index);
8833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
8843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "\n");
8853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
8873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((cur->user2 == NULL) ||
8883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		((cur->user2 == cur->user) && (cur->index == cur->index2))) {
8893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "Object is a collapsed range :\n");
8903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
8913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index >= 0)
8923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index);
8933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
8943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
8953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
8963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else  {
8973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "Object is a range :\n");
8983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
8993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "From ");
9003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index >= 0)
9013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index);
9023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
9033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
9043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
9053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
9063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "To ");
9073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index2 >= 0)
9083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index2);
9093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
9103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2,
9113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
9123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "\n");
9133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
9143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
9153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
9163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(LIBXML_XPTR_ENABLED)
9173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Location Set:\n");
9183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpLocationSet(output,
9193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    (xmlLocationSetPtr) cur->user, depth);
9203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
9213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
9223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_USERS:
9233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is user defined\n");
9243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
9253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
9263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
9279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
92856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
92956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
9309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                     xmlXPathStepOpPtr op, int depth) {
9319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
9329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    char shift[100];
9339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
9359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
9369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
9379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, shift);
9399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op == NULL) {
9409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	fprintf(output, "Step is NULL\n");
9419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
9429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
9439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    switch (op->op) {
9449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_END:
9459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "END"); break;
9469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_AND:
9479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "AND"); break;
9489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_OR:
9499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "OR"); break;
9509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_EQUAL:
9519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value)
9529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "EQUAL =");
9539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
9549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "EQUAL !=");
9559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
9569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_CMP:
9579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value)
9589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "CMP <");
9599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
9609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "CMP >");
9619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (!op->value2)
9629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "=");
9639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
9649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_PLUS:
9659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value == 0)
9669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS -");
9679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 1)
9689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS +");
9699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 2)
9709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS unary -");
9719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 3)
9729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS unary - -");
9739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
9749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_MULT:
9759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value == 0)
9769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT *");
9779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 1)
9789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT div");
9799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
9809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT mod");
9819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
9829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_UNION:
9839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "UNION"); break;
9849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_ROOT:
9859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "ROOT"); break;
9869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_NODE:
9879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "NODE"); break;
9889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_RESET:
9899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "RESET"); break;
9909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_SORT:
9919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "SORT"); break;
9929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_COLLECT: {
99378637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathAxisVal axis = (xmlXPathAxisVal)op->value;
99478637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathTestVal test = (xmlXPathTestVal)op->value2;
99578637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathTypeVal type = (xmlXPathTypeVal)op->value3;
9969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value4;
9979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value5;
9989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "COLLECT ");
10009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (axis) {
10019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ANCESTOR:
10029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'ancestors' "); break;
10039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ANCESTOR_OR_SELF:
10049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'ancestors-or-self' "); break;
10059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ATTRIBUTE:
10069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'attributes' "); break;
10079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_CHILD:
10089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'child' "); break;
10099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_DESCENDANT:
10109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'descendant' "); break;
10119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_DESCENDANT_OR_SELF:
10129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'descendant-or-self' "); break;
10139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_FOLLOWING:
10149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'following' "); break;
10159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_FOLLOWING_SIBLING:
10169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'following-siblings' "); break;
10179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_NAMESPACE:
10189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'namespace' "); break;
10199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PARENT:
10209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'parent' "); break;
10219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PRECEDING:
10229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'preceding' "); break;
10239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PRECEDING_SIBLING:
10249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'preceding-sibling' "); break;
10259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_SELF:
10269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'self' "); break;
10279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
10289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (test) {
10299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NONE:
10309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'none' "); break;
10319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_TYPE:
10329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'type' "); break;
10339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_PI:
10349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'PI' "); break;
10359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_ALL:
10369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'all' "); break;
10379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NS:
10389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'namespace' "); break;
10399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NAME:
10409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'name' "); break;
10419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
10429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (type) {
10439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_NODE:
10449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'node' "); break;
10459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_COMMENT:
10469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'comment' "); break;
10479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_TEXT:
10489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'text' "); break;
10499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_PI:
10509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'PI' "); break;
10519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
10529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
10539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "%s:", prefix);
10549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (name != NULL)
1055580ced8ee28ecd99374da9383897678e4ba6c358Daniel Veillard		fprintf(output, "%s", (const char *) name);
10569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
10579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        }
10599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_VALUE: {
10609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4;
10619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "ELEM ");
10639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathDebugDumpObject(output, object, 0);
10649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    goto finish;
10659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
10669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_VARIABLE: {
10679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value5;
10689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value4;
10699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
10719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "VARIABLE %s:%s", prefix, name);
10729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    else
10739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "VARIABLE %s", name);
10749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
10759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
10769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_FUNCTION: {
10779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    int nbargs = op->value;
10789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value5;
10799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value4;
10809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
10829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "FUNCTION %s:%s(%d args)",
10839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			prefix, name, nbargs);
10849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    else
10859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "FUNCTION %s(%d args)", name, nbargs);
10869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
10879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
10889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_ARG: fprintf(output, "ARG"); break;
10899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
1090d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
1091fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
1092fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard        case XPATH_OP_RANGETO: fprintf(output, "RANGETO"); break;
1093fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
10949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	default:
10959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        fprintf(output, "UNKNOWN %d\n", op->op); return;
10969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
10979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, "\n");
10989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardfinish:
10999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op->ch1 >= 0)
11009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1);
11019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op->ch2 >= 0)
11029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1);
11039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
110456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard
11055e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
11065e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathDebugDumpCompExpr:
11075e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @output:  the FILE * for the output
11085e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @comp:  the precompiled XPath expression
11095e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @depth:  the indentation level.
11105e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
11115e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Dumps the tree of the compiled XPath expression.
11125e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
111356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardvoid
111456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
111556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	                  int depth) {
11169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
11179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    char shift[100];
11189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1119a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((output == NULL) || (comp == NULL)) return;
1120a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
11219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
11229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
11239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
11249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, shift);
11269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, "Compiled Expression : %d elements\n",
11289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    comp->nbStep);
11299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    i = comp->last;
11309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
11319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
1132017b108fcf16dbce05ca7ebd75763f3d888abb5fDaniel Veillard#endif /* LIBXML_DEBUG_ENABLED */
11333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
11353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
11363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 		Parser stacks related functions and macros		*
11373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
11383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
11393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11405e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
11415e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * valuePop:
11425e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @ctxt: an XPath evaluation context
11435e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
11445e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Pops the top XPath object from the value stack
11455e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
11465e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Returns the XPath object just removed
11475e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
114824505b0f5c872c5afb6da5093565e5a6e09ca541Daniel VeillardxmlXPathObjectPtr
11491c732d2e10935529b717864b6fa4296f80edace1Daniel VeillardvaluePop(xmlXPathParserContextPtr ctxt)
11501c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard{
11511c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    xmlXPathObjectPtr ret;
11521c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard
1153a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->valueNr <= 0))
115424505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard        return (NULL);
11551c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->valueNr--;
11561c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    if (ctxt->valueNr > 0)
11571c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
11581c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    else
11591c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        ctxt->value = NULL;
11601c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ret = ctxt->valueTab[ctxt->valueNr];
116124505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard    ctxt->valueTab[ctxt->valueNr] = NULL;
11621c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    return (ret);
11631c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard}
11645e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
11655e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * valuePush:
11665e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @ctxt:  an XPath evaluation context
11675e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @value:  the XPath object
11685e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
11695e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Pushes a new XPath object on top of the value stack
1170cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *
1171cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * returns the number of items on the value stack
11725e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
117324505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillardint
11741c732d2e10935529b717864b6fa4296f80edace1Daniel VeillardvaluePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
11751c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard{
1176a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (value == NULL)) return(-1);
11771c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    if (ctxt->valueNr >= ctxt->valueMax) {
1178a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard        xmlXPathObjectPtr *tmp;
1179a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard
1180a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard        tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
1181a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard                                             2 * ctxt->valueMax *
11821c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard                                             sizeof(ctxt->valueTab[0]));
1183a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard        if (tmp == NULL) {
11841c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
11851c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard            return (0);
11861c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        }
1187a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard        ctxt->valueMax *= 2;
1188a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard	ctxt->valueTab = tmp;
11891c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    }
11901c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->valueTab[ctxt->valueNr] = value;
11911c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->value = value;
11921c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    return (ctxt->valueNr++);
11931c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard}
11943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1195f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1196f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopBoolean:
1197f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1198f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1199f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a boolean from the stack, handling conversion if needed.
1200f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1201f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1202f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the boolean
1203f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1204f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
1205f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
1206f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1207f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int ret;
1208f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1209f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1210f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
1211f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1212f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
1213f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1214081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    if (obj->type != XPATH_BOOLEAN)
1215081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	ret = xmlXPathCastToBoolean(obj);
1216081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    else
1217081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack        ret = obj->boolval;
1218f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1219f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1220f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1221f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1222f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1223f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopNumber:
1224f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1225f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1226f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a number from the stack, handling conversion if needed.
1227f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1228f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1229f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the number
1230f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1231f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerdouble
1232f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
1233f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1234f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    double ret;
1235f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1236f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1237f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
1238f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1239f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
1240f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1241081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    if (obj->type != XPATH_NUMBER)
1242081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	ret = xmlXPathCastToNumber(obj);
1243081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    else
1244081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack        ret = obj->floatval;
1245f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1246f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1247f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1248f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1249f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1250f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopString:
1251f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1252f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1253f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a string from the stack, handling conversion if needed.
1254f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1255f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1256f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the string
1257f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1258f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlChar *
1259f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopString (xmlXPathParserContextPtr ctxt) {
1260f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1261f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlChar * ret;
1262f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1263f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1264f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
1265f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1266f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1267f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1268081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    ret = xmlXPathCastToString(obj);	/* this does required strdup */
1269f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    /* TODO: needs refactoring somewhere else */
1270f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj->stringval == ret)
1271f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	obj->stringval = NULL;
1272f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1273f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1274f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1275f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1276f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1277f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopNodeSet:
1278f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1279f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1280f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a node-set from the stack, handling conversion if needed.
1281f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1282f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1283f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the node-set
1284f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1285f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
1286f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
1287f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1288f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
1289f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1290f2a36f98e16efa8a89d9bed359d59be10e5d33cdDaniel Veillard    if (ctxt == NULL) return(NULL);
1291f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value == NULL) {
1292f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1293f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1294f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1295f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (!xmlXPathStackIsNodeSet(ctxt)) {
1296f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetTypeError(ctxt);
1297f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1298f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1299f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1300f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = obj->nodesetval;
1301e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#if 0
13029deb242b558cbcff45165866e0634a1962404885Daniel Veillard    /* to fix memory leak of not clearing obj->user */
13039deb242b558cbcff45165866e0634a1962404885Daniel Veillard    if (obj->boolval && obj->user != NULL)
13049deb242b558cbcff45165866e0634a1962404885Daniel Veillard        xmlFreeNodeList((xmlNodePtr) obj->user);
1305e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#endif
1306f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeNodeSetList(obj);
1307f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1308f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1309f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1310f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1311f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopExternal:
1312f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1313f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1314cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Pops an external object from the stack, handling conversion if needed.
1315f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1316f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1317f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the object
1318f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1319f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyervoid *
1320f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
1321f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1322f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    void * ret;
1323f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1324a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->value == NULL)) {
1325f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1326f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1327f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1328f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value->type != XPATH_USERS) {
1329f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetTypeError(ctxt);
1330f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1331f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1332f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1333f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = obj->user;
1334f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1335f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1336f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1337f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
13383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
13393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Macros for accessing the content. Those should be used only by the parser,
13403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and not exported.
13413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Dirty macros, i.e. one need to make assumption on the context to use them
13433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CUR_PTR return the current pointer to the xmlChar to be parsed.
13453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CUR     returns the current xmlChar value, i.e. a 8 bit value
13463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           in ISO-Latin or UTF-8.
13473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           This should be used internally by the parser
13483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           only to compare to ASCII values otherwise it would break when
13493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           running with UTF-8 encoding.
13503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
13513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           to compare on ASCII based substring.
13523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
13533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           strings within the parser.
13543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CURRENT Returns the current char value, with the full decoding of
13553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           UTF-8 if we are using this mode. It returns an int.
13563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   NEXT    Skip to the next character, this does the proper decoding
13573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
13583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           It returns the pointer to the current xmlChar.
13593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
13603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CUR (*ctxt->cur)
13623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SKIP(val) ctxt->cur += (val)
13633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define NXT(val) ctxt->cur[(val)]
13643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CUR_PTR ctxt->cur
136561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
136661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
136761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define COPY_BUF(l,b,i,v)                                              \
136861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (l == 1) b[i++] = (xmlChar) v;                                  \
136961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    else i += xmlCopyChar(l,&b[i],v)
137061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
137161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define NEXTL(l)  ctxt->cur += l
13723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SKIP_BLANKS 							\
137476e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*(ctxt->cur))) NEXT
13753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CURRENT (*ctxt->cur)
13773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)
13783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1379e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1380e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#ifndef DBL_DIG
1381e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define DBL_DIG 16
1382e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#endif
1383e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#ifndef DBL_EPSILON
1384e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define DBL_EPSILON 1E-9
1385e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#endif
1386e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1387e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define UPPER_DOUBLE 1E9
1388e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define LOWER_DOUBLE 1E-5
1389e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1390e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define INTEGER_DIGITS DBL_DIG
1391e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define FRACTION_DIGITS (DBL_DIG + 1)
1392e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define EXPONENT_DIGITS (3 + 2)
1393e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1394e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese/**
1395e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * xmlXPathFormatNumber:
1396e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @number:     number to format
1397e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @buffer:     output buffer
1398e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @buffersize: size of output buffer
1399e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese *
1400e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * Convert the number into a string representation.
1401e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese */
1402e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reesestatic void
1403e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn ReesexmlXPathFormatNumber(double number, char buffer[], int buffersize)
1404e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese{
1405cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    switch (xmlXPathIsInf(number)) {
1406e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    case 1:
14075fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (buffersize > (int)sizeof("Infinity"))
140849cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "Infinity");
1409e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1410e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    case -1:
1411e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	if (buffersize > (int)sizeof("-Infinity"))
141249cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "-Infinity");
1413e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1414e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    default:
1415cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(number)) {
1416e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    if (buffersize > (int)sizeof("NaN"))
141749cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin		snprintf(buffer, buffersize, "NaN");
1418d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	} else if (number == 0 && xmlXPathGetSign(number) != 0) {
141949cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "0");
142028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	} else if (number == ((int) number)) {
142128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    char work[30];
142228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    char *ptr, *cur;
1423b3d1491b69060f8a67516b9a3ef12617adf88954Daniel Veillard	    int value = (int) number;
142428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard
142528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard            ptr = &buffer[0];
142628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (value == 0) {
142728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr++ = '0';
142828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    } else {
1429b3d1491b69060f8a67516b9a3ef12617adf88954Daniel Veillard		snprintf(work, 29, "%d", value);
143028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		cur = &work[0];
1431b3d1491b69060f8a67516b9a3ef12617adf88954Daniel Veillard		while ((*cur) && (ptr - buffer < buffersize)) {
1432b3d1491b69060f8a67516b9a3ef12617adf88954Daniel Veillard		    *ptr++ = *cur++;
143328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		}
143428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
143528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (ptr - buffer < buffersize) {
143628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr = 0;
143728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    } else if (buffersize > 0) {
143828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		ptr--;
143928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr = 0;
144028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
1441e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	} else {
144270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* 3 is sign, decimal point, and terminating zero */
144370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
144470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    int integer_place, fraction_place;
144570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char *ptr;
144670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char *after_fraction;
144770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    double absolute_value;
144870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    int size;
144970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
145070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    absolute_value = fabs(number);
145170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
145270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /*
145370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * First choose format - scientific or regular floating point.
145470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * In either case, result is in work, and after_fraction points
145570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * just past the fractional part.
145670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    */
145770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if ( ((absolute_value > UPPER_DOUBLE) ||
145870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		  (absolute_value < LOWER_DOUBLE)) &&
145970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		 (absolute_value != 0.0) ) {
146070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		/* Use scientific notation */
146170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
146270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		fraction_place = DBL_DIG - 1;
146311ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		size = snprintf(work, sizeof(work),"%*.*e",
146470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese			 integer_place, fraction_place, number);
146511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		while ((size > 0) && (work[size] != 'e')) size--;
146611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		after_fraction = work + size;
146711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard
1468e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    }
146970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    else {
147070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		/* Use regular notation */
147156f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		if (absolute_value > 0.0)
147256f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		    integer_place = 1 + (int)log10(absolute_value);
147356f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		else
1474a3067d19ec3a96fd6e7997753e27a5422a2856f7Daniel Veillard		    integer_place = 0;
147570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		fraction_place = (integer_place > 0)
147670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		    ? DBL_DIG - integer_place
147770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		    : DBL_DIG;
147870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		size = snprintf(work, sizeof(work), "%0.*f",
147970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese				fraction_place, number);
148070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		after_fraction = work + size;
1481e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    }
1482e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
148370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* Remove fractional trailing zeroes */
148470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    ptr = after_fraction;
148570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    while (*(--ptr) == '0')
148670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		;
148770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if (*ptr != '.')
148870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	        ptr++;
14895dd3c9622ab6a8e75870bc5351499155e7963abcDaniel Veillard	    while ((*ptr++ = *after_fraction++) != 0);
149070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
149170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* Finally copy result back to caller */
149270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    size = strlen(work) + 1;
149370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if (size > buffersize) {
149470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		work[buffersize - 1] = 0;
149570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		size = buffersize;
149670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    }
14975dd3c9622ab6a8e75870bc5351499155e7963abcDaniel Veillard	    memmove(buffer, work, size);
1498e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	}
1499e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1500e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    }
1501e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese}
1502e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
15033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
15053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
15063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle NodeSets			*
15073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
15083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
15093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1511e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * xmlXPathOrderDocElems:
1512e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * @doc:  an input document
1513e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *
1514e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * Call this routine to speed up XPath computation on static documents.
1515e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * This stamps all the element nodes with the document order
1516e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * Like for line information, the order is kept in the element->content
1517081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * field, the value stored is actually - the node number (starting at -1)
1518081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * to be able to differentiate from line numbers.
1519e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *
1520081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the number of elements found in the document or -1 in case
1521e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *    of error.
1522e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard */
1523e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillardlong
1524e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel VeillardxmlXPathOrderDocElems(xmlDocPtr doc) {
1525e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    long count = 0;
1526e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    xmlNodePtr cur;
1527e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1528e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    if (doc == NULL)
1529e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	return(-1);
1530e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    cur = doc->children;
1531e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    while (cur != NULL) {
1532e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	if (cur->type == XML_ELEMENT_NODE) {
1533e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur->content = (void *) (-(++count));
1534e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur->children != NULL) {
1535e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = cur->children;
1536e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		continue;
1537e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1538e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	}
1539e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	if (cur->next != NULL) {
1540e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur = cur->next;
1541e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    continue;
1542e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	}
1543e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	do {
1544e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur = cur->parent;
1545e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur == NULL)
1546e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1547e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur == (xmlNodePtr) doc) {
1548e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = NULL;
1549e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1550e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1551e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur->next != NULL) {
1552e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = cur->next;
1553e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1554e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1555e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	} while (cur != NULL);
1556e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    }
1557e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    return(count);
1558e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard}
1559e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1560e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard/**
15613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCmpNodes:
15623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node1:  the first node
15633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node2:  the second node
15643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
15653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Compare two nodes w.r.t document order
15663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
15673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -2 in case of error 1 if first point < second point, 0 if
1568081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack *         it's the same node, -1 otherwise
15693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
15703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
15713473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
15723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int depth1, depth2;
1573edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    int attr1 = 0, attr2 = 0;
1574e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack    xmlNodePtr attrNode1 = NULL, attrNode2 = NULL;
15753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodePtr cur, root;
15763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((node1 == NULL) || (node2 == NULL))
15783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-2);
15793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
15803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * a couple of optimizations which will avoid computations in most cases
15813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1582edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node1->type == XML_ATTRIBUTE_NODE) {
1583edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	attr1 = 1;
1584e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	attrNode1 = node1;
1585edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	node1 = node1->parent;
1586edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1587edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node2->type == XML_ATTRIBUTE_NODE) {
1588edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	attr2 = 1;
1589e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	attrNode2 = node2;
1590edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	node2 = node2->parent;
1591edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1592edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node1 == node2) {
1593e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	if (attr1 == attr2) {
1594e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	    /* not required, but we keep attributes in order */
1595e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	    if (attr1 != 0) {
1596e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	        cur = attrNode2->prev;
1597e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		while (cur != NULL) {
1598e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		    if (cur == attrNode1)
1599e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		        return (1);
1600e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		    cur = cur->prev;
1601e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		}
1602e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		return (-1);
1603e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	    }
1604edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	    return(0);
1605e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	}
1606edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	if (attr2 == 1)
1607edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	    return(1);
1608edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	return(-1);
1609edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1610b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard    if ((node1->type == XML_NAMESPACE_DECL) ||
1611b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard        (node2->type == XML_NAMESPACE_DECL))
1612b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard	return(1);
16133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->prev)
16143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
16153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->next)
16163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
16173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
1619e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard     * Speedup using document order if availble.
16207216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard     */
16217216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    if ((node1->type == XML_ELEMENT_NODE) &&
16227216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	(node2->type == XML_ELEMENT_NODE) &&
1623e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(0 > (long) node1->content) &&
1624e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(0 > (long) node2->content) &&
1625e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(node1->doc == node2->doc)) {
1626e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	long l1, l2;
1627e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1628e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	l1 = -((long) node1->content);
1629e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	l2 = -((long) node2->content);
16307216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	if (l1 < l2)
16317216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	    return(1);
16327216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	if (l1 > l2)
16337216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	    return(-1);
16347216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    }
1635e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
16367216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    /*
16373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * compute depth to root
16383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
16393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
16403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node1)
16413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(1);
16423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth2++;
16433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    root = cur;
16453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
16463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node2)
16473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-1);
16483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth1++;
16493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
16513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Distinct document (or distinct entities :-( ) case.
16523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
16533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (root != cur) {
16543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-2);
16553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
16573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * get the nearest common ancestor.
16583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
16593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (depth1 > depth2) {
16603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth1--;
16613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node1 = node1->parent;
16623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (depth2 > depth1) {
16643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth2--;
16653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node2 = node2->parent;
16663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (node1->parent != node2->parent) {
16683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node1 = node1->parent;
16693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node2 = node2->parent;
16703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* should not happen but just in case ... */
16713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((node1 == NULL) || (node2 == NULL))
16723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-2);
16733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
16753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Find who's first.
16763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1677f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard    if (node1 == node2->prev)
1678f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	return(1);
16793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->next)
16803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
1681f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard    /*
1682f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard     * Speedup using document order if availble.
1683f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard     */
1684f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard    if ((node1->type == XML_ELEMENT_NODE) &&
1685f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	(node2->type == XML_ELEMENT_NODE) &&
1686f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	(0 > (long) node1->content) &&
1687f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	(0 > (long) node2->content) &&
1688f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	(node1->doc == node2->doc)) {
1689f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	long l1, l2;
1690f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard
1691f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	l1 = -((long) node1->content);
1692f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	l2 = -((long) node2->content);
1693f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	if (l1 < l2)
1694f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	    return(1);
1695f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	if (l1 > l2)
1696f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	    return(-1);
1697f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard    }
1698f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard
16993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (cur = node1->next;cur != NULL;cur = cur->next)
17003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node2)
17013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(1);
17023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(-1); /* assume there is no sibling list corruption */
17033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
17043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17052bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik#ifdef XP_FAST_NON_ELEM_COMPARISON
17062bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik/**
17072bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik * xmlXPathCmpNodesExt:
17082bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik * @node1:  the first node
17092bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik * @node2:  the second node
17102bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik *
17112bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik * Compare two nodes w.r.t document order.
17122bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik * This one is optimized for handling of non-element nodes.
17132bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik *
17142bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik * Returns -2 in case of error 1 if first point < second point, 0 if
17152bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik *         it's the same node, -1 otherwise
17162bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik */
17172bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcikstatic int
17182bdabbd711356e534940431053523f1538d1a93eKasimier T. BuchcikxmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
17192bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    int depth1, depth2;
17202bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    int misc = 0, precedence1 = 0, precedence2 = 0;
17212bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
17222bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    xmlNodePtr cur, root;
17232bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
17242bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if ((node1 == NULL) || (node2 == NULL))
17252bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	return(-2);
17262bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
17272bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if (node1 == node2)
17282bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	return(0);
17292bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
17302bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    /*
17312bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     * a couple of optimizations which will avoid computations in most cases
17322bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     */
17332bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
17342bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    switch (node1->type) {
17352bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_ELEMENT_NODE:
17362bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    break;
17372bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_ATTRIBUTE_NODE:
17382bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    precedence1 = 1; /* element is owner */
17392bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    miscNode1 = node1;
17402bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    node1 = node1->parent;
17412bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    misc = 1;
17422bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    break;
17432bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_TEXT_NODE:
17442bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_CDATA_SECTION_NODE:
17452bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_COMMENT_NODE:
17462bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_PI_NODE: {
17472bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    miscNode1 = node1;
17482bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    /*
17492bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    * Find nearest element node.
17502bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    */
17512bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    if (node1->prev != NULL) {
17522bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		do {
17532bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    node1 = node1->prev;
17542bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    if (node1->type == XML_ELEMENT_NODE) {
17552bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			precedence1 = 3; /* element in prev-sibl axis */
17562bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			break;
17572bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    }
17582bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    if (node1->prev == NULL) {
17592bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			precedence1 = 2; /* element is parent */
17602bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			/*
17612bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			* URGENT TODO: Are there any cases, where the
17622bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			* parent of such a node is not an element node?
17632bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			*/
17642bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			node1 = node1->parent;
17652bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			break;
17662bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    }
17672bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		} while (1);
17682bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    } else {
17692bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		precedence1 = 2; /* element is parent */
17702bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		node1 = node1->parent;
17712bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    }
17722bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE)) {
17732bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		/*
17742bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		* Fallback for whatever case.
17752bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		*/
17762bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		node1 = miscNode1;
17772bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		precedence1 = 0;
17782bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    } else
17792bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		misc = 1;
17802bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	}
17812bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    break;
17822bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_NAMESPACE_DECL:
17832bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    /*
17842bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    * TODO: why do we return 1 for namespace nodes?
17852bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    */
17862bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(1);
17872bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	default:
17882bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    break;
17892bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
17902bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    switch (node2->type) {
17912bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_ELEMENT_NODE:
17922bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    break;
17932bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_ATTRIBUTE_NODE:
17942bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    precedence2 = 1; /* element is owner */
17952bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    miscNode2 = node2;
17962bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    node2 = node2->parent;
17972bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    misc = 1;
17982bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    break;
17992bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_TEXT_NODE:
18002bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_CDATA_SECTION_NODE:
18012bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_COMMENT_NODE:
18022bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_PI_NODE: {
18032bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    miscNode2 = node2;
18042bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    if (node2->prev != NULL) {
18052bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		do {
18062bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    node2 = node2->prev;
18072bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    if (node2->type == XML_ELEMENT_NODE) {
18082bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			precedence2 = 3; /* element in prev-sibl axis */
18092bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			break;
18102bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    }
18112bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    if (node2->prev == NULL) {
18122bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			precedence2 = 2; /* element is parent */
18132bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			node2 = node2->parent;
18142bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			break;
18152bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    }
18162bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		} while (1);
18172bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    } else {
18182bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		precedence2 = 2; /* element is parent */
18192bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		node2 = node2->parent;
18202bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    }
18212bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
18222bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		(0 <= (long) node1->content))
18232bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    {
18242bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		node2 = miscNode2;
18252bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		precedence2 = 0;
18262bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    } else
18272bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		misc = 1;
18282bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	}
18292bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    break;
18302bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	case XML_NAMESPACE_DECL:
18312bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(1);
18322bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	default:
18332bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    break;
18342bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
18352bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if (misc) {
18362bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if (node1 == node2) {
18372bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    if (precedence1 == precedence2) {
18382bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		/*
18392bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		* The ugly case; but normally there aren't many
18402bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		* adjacent non-element nodes around.
18412bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		*/
18422bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		cur = miscNode2->prev;
18432bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		while (cur != NULL) {
18442bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    if (cur == miscNode1)
18452bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			return(1);
18462bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    if (cur->type == XML_ELEMENT_NODE)
18472bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			return(-1);
18482bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    cur = cur->prev;
18492bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		}
18502bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		return (-1);
18512bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    } else {
18522bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		/*
18532bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		* Evaluate based on higher precedence wrt to the element.
18542bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		* TODO: This assumes attributes are sorted before content.
18552bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		*   Is this 100% correct?
18562bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		*/
18572bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		if (precedence1 < precedence2)
18582bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    return(1);
18592bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		else
18602bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    return(-1);
18612bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    }
18622bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	}
18632bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	/*
18642bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	* Special case: One of the helper-elements is contained by the other.
18652bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	* <foo>
18662bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	*   <node2>
18672bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	*     <node1>Text-1(precedence1 == 2)</node1>
18682bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	*   </node2>
18692bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	*   Text-6(precedence2 == 3)
18702bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	* </foo>
18712bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	*/
18722bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if ((precedence2 == 3) && (precedence1 > 1)) {
18732bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    cur = node1->parent;
18742bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    while (cur) {
18752bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		if (cur == node2)
18762bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    return(1);
18772bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		cur = cur->parent;
18782bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    }
18792bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	}
18802bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if ((precedence1 == 3) && (precedence2 > 1)) {
18812bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    cur = node2->parent;
18822bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    while (cur) {
18832bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		if (cur == node1)
18842bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		    return(-1);
18852bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		cur = cur->parent;
18862bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    }
18872bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	}
18882bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
18892bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
18902bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if (node1 == node2->prev)
18912bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	return(1);
18922bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if (node1 == node2->next)
18932bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	return(-1);
18942bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
18952bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    /*
18962bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     * Speedup using document order if availble.
18972bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     */
18982bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if ((node1->type == XML_ELEMENT_NODE) &&
18992bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	(node2->type == XML_ELEMENT_NODE) &&
19002bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	(0 > (long) node1->content) &&
19012bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	(0 > (long) node2->content) &&
19022bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	(node1->doc == node2->doc)) {
19032bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	long l1, l2;
19042bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
19052bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	l1 = -((long) node1->content);
19062bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	l2 = -((long) node2->content);
19072bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if (l1 < l2)
19082bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(1);
19092bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if (l1 > l2)
19102bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(-1);
19112bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
19122bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
19132bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    /*
19142bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     * compute depth to root
19152bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     */
19162bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
19172bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if (cur == node1)
19182bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(1);
19192bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	depth2++;
19202bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
19212bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    root = cur;
19222bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
19232bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if (cur == node2)
19242bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(-1);
19252bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	depth1++;
19262bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
19272bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    /*
19282bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     * Distinct document (or distinct entities :-( ) case.
19292bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     */
19302bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if (root != cur) {
19312bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	return(-2);
19322bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
19332bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    /*
19342bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     * get the nearest common ancestor.
19352bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     */
19362bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    while (depth1 > depth2) {
19372bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	depth1--;
19382bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	node1 = node1->parent;
19392bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
19402bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    while (depth2 > depth1) {
19412bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	depth2--;
19422bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	node2 = node2->parent;
19432bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
19442bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    while (node1->parent != node2->parent) {
19452bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	node1 = node1->parent;
19462bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	node2 = node2->parent;
19472bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	/* should not happen but just in case ... */
19482bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if ((node1 == NULL) || (node2 == NULL))
19492bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(-2);
19502bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
19512bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    /*
19522bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     * Find who's first.
19532bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     */
19542bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if (node1 == node2->prev)
19552bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	return(1);
19562bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if (node1 == node2->next)
19572bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	return(-1);
19582bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    /*
19592bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     * Speedup using document order if availble.
19602bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik     */
19612bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    if ((node1->type == XML_ELEMENT_NODE) &&
19622bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	(node2->type == XML_ELEMENT_NODE) &&
19632bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	(0 > (long) node1->content) &&
19642bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	(0 > (long) node2->content) &&
19652bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	(node1->doc == node2->doc)) {
19662bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	long l1, l2;
19672bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
19682bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	l1 = -((long) node1->content);
19692bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	l2 = -((long) node2->content);
19702bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if (l1 < l2)
19712bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(1);
19722bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if (l1 > l2)
19732bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(-1);
19742bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    }
19752bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
19762bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    for (cur = node1->next;cur != NULL;cur = cur->next)
19772bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	if (cur == node2)
19782bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik	    return(1);
19792bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik    return(-1); /* assume there is no sibling list corruption */
19802bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik}
19812bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik#endif /* XP_FAST_NON_ELEM_COMPARISON */
19822bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik
19833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
19843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetSort:
19853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @set:  the node set
19863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
19873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Sort the node set in document order
19883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
19893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
19903473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetSort(xmlNodeSetPtr set) {
1991e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    int i, j, incr, len;
19923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodePtr tmp;
19933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (set == NULL)
19953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
19963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Use Shell's sort to sort the node-set */
19983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    len = set->nodeNr;
19993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (incr = len / 2; incr > 0; incr /= 2) {
20003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (i = incr; i < len; i++) {
20013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    j = i - incr;
20023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (j >= 0) {
20032bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik#ifdef XP_FAST_NON_ELEM_COMPARISON
20042bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		if (xmlXPathCmpNodesExt(set->nodeTab[j],
20052bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			set->nodeTab[j + incr]) == -1)
20062bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik#else
2007e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese		if (xmlXPathCmpNodes(set->nodeTab[j],
20082bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik			set->nodeTab[j + incr]) == -1)
20092bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik#endif
20102bdabbd711356e534940431053523f1538d1a93eKasimier T. Buchcik		{
20113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    tmp = set->nodeTab[j];
20123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    set->nodeTab[j] = set->nodeTab[j + incr];
20133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    set->nodeTab[j + incr] = tmp;
20143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    j -= incr;
20153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else
20163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
20173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
20183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
20193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
20213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NODESET_DEFAULT	10
20233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
2024044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetDupNs:
2025044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @node:  the parent node of the namespace XPath node
2026044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  the libxml namespace declaration node.
2027044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
2028044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Namespace node in libxml don't match the XPath semantic. In a node set
2029044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * the namespace nodes are duplicated and the next pointer is set to the
2030044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * parent node in the XPath semantic.
2031044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
2032044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Returns the newly created object.
2033044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
2034044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillardstatic xmlNodePtr
2035044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
2036044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    xmlNsPtr cur;
2037044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2038044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
2039044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return(NULL);
2040044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
2041044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return((xmlNodePtr) ns);
2042044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2043044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
2044044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * Allocate a new Namespace and fill the fields.
2045044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
2046044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
2047044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (cur == NULL) {
2048d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "duplicating namespace\n");
2049044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return(NULL);
2050044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
2051044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    memset(cur, 0, sizeof(xmlNs));
2052044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->type = XML_NAMESPACE_DECL;
2053044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (ns->href != NULL)
2054044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->href = xmlStrdup(ns->href);
2055044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (ns->prefix != NULL)
2056044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->prefix = xmlStrdup(ns->prefix);
2057044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->next = (xmlNsPtr) node;
2058044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    return((xmlNodePtr) cur);
2059044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
2060044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2061044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
2062044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetFreeNs:
2063044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  the XPath namespace node found in a nodeset.
2064044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
2065081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Namespace nodes in libxml don't match the XPath semantic. In a node set
2066044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * the namespace nodes are duplicated and the next pointer is set to the
2067081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * parent node in the XPath semantic. Check if such a node needs to be freed
2068044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
2069f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Saninvoid
2070044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetFreeNs(xmlNsPtr ns) {
2071044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
2072044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return;
2073044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2074044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) {
2075044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (ns->href != NULL)
2076044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlFree((xmlChar *)ns->href);
2077044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (ns->prefix != NULL)
2078044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlFree((xmlChar *)ns->prefix);
2079044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlFree(ns);
2080044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
2081044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
2082044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2083044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
20843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetCreate:
20853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an initial xmlNodePtr, or NULL
20863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlNodeSetPtr of type double and of value @val
20883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
20903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
20913473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodeSetPtr
20923473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetCreate(xmlNodePtr val) {
20933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ret;
20943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
20963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
2097d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating nodeset\n");
20983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
20993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlNodeSet));
21013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val != NULL) {
21023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
21033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
21043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret->nodeTab == NULL) {
2105d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "creating nodeset\n");
2106d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlFree(ret);
21073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
21083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
21093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(ret->nodeTab, 0 ,
21103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
21113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret->nodeMax = XML_NODESET_DEFAULT;
2112044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (val->type == XML_NAMESPACE_DECL) {
2113044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val;
2114044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2115044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    ret->nodeTab[ret->nodeNr++] =
2116044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2117044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	} else
2118044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    ret->nodeTab[ret->nodeNr++] = val;
21193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
21213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
2124f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeSetContains:
2125f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @cur:  the node-set
2126f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @val:  the node
2127f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2128f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * checks whether @cur contains @val
2129f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2130f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns true (1) if @cur contains @val, false (0) otherwise
2131f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2132f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
2133f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
2134f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i;
2135f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2136a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((cur == NULL) || (val == NULL)) return(0);
2137044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
2138044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0; i < cur->nodeNr; i++) {
2139044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2140044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns1, ns2;
2141044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2142044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns1 = (xmlNsPtr) val;
2143044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns2 = (xmlNsPtr) cur->nodeTab[i];
2144044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if (ns1 == ns2)
2145044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return(1);
2146044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns1->next != NULL) && (ns2->next == ns1->next) &&
2147044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	            (xmlStrEqual(ns1->prefix, ns2->prefix)))
2148044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return(1);
2149044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
2150044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
2151044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else {
2152044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0; i < cur->nodeNr; i++) {
2153044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (cur->nodeTab[i] == val)
2154044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		return(1);
2155044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
2156f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2157f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(0);
2158f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2159f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2160f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2161044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetAddNs:
2162044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @cur:  the initial node set
2163044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @node:  the hosting node
2164044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  a the namespace node
2165044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
2166044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * add a new namespace node to an existing NodeSet
2167044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
216879376ba94845db7096c3917f4f40baeb450eb0e9Aleksey Saninvoid
2169044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
2170044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    int i;
2171044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2172a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
2173a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
2174a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard        (ns->type != XML_NAMESPACE_DECL) ||
2175044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(node->type != XML_ELEMENT_NODE))
2176044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return;
2177044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2178081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2179044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
2180081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * prevent duplicates
2181044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
2182044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    for (i = 0;i < cur->nodeNr;i++) {
2183044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        if ((cur->nodeTab[i] != NULL) &&
2184044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
2185c62a147963b5839fc815267706eaec381f90ca16Daniel Veillard	    (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
2186044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
2187044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
2188044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
2189044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2190044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
2191044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * grow the nodeTab if needed
2192044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
2193044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (cur->nodeMax == 0) {
2194044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2195044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					     sizeof(xmlNodePtr));
2196044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (cur->nodeTab == NULL) {
2197d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
2198044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
2199044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
2200044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	memset(cur->nodeTab, 0 ,
2201044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
2202044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeMax = XML_NODESET_DEFAULT;
2203044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else if (cur->nodeNr == cur->nodeMax) {
2204044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        xmlNodePtr *temp;
2205044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2206044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeMax *= 2;
2207044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
2208044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				      sizeof(xmlNodePtr));
2209044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (temp == NULL) {
2210d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
2211044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
2212044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
2213044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab = temp;
2214044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
2215044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
2216044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
2217044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2218044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
22193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetAdd:
22203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
22213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  a new xmlNodePtr
22223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
2223cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * add a new xmlNodePtr to an existing NodeSet
22243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
22253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
22263473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
22273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
22283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2229a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((cur == NULL) || (val == NULL)) return;
22303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2231ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#if 0
2232652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard    if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
2233652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	return;	/* an XSLT fake node */
2234ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#endif
2235652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard
2236081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
22373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
2238081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * prevent duplcates
22393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
22403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->nodeNr;i++)
22413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->nodeTab[i] == val) return;
22423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
22443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * grow the nodeTab if needed
22453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
22463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->nodeMax == 0) {
22473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
22483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
22493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->nodeTab == NULL) {
2250d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
22513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
22523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
22533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(cur->nodeTab, 0 ,
22543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
22553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax = XML_NODESET_DEFAULT;
22563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->nodeNr == cur->nodeMax) {
22573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNodePtr *temp;
22583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax *= 2;
22603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
22613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				      sizeof(xmlNodePtr));
22623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (temp == NULL) {
2263d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
22643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
22653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
22663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->nodeTab = temp;
22673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2268044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
2269044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlNsPtr ns = (xmlNsPtr) val;
2270044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2271044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] =
2272044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2273044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else
2274044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] = val;
22753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
22783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetAddUnique:
22793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
22803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  a new xmlNodePtr
22813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
2282cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * add a new xmlNodePtr to an existing NodeSet, optimized version
22833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * when we are sure the node is not already in the set.
22843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
22853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
22863473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
2287a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((cur == NULL) || (val == NULL)) return;
22883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2289ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#if 0
2290652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard    if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
2291652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	return;	/* an XSLT fake node */
2292ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#endif
2293652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard
2294081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
22953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
22963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * grow the nodeTab if needed
22973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
22983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->nodeMax == 0) {
22993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
23003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
23013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->nodeTab == NULL) {
2302d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
23033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
23043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
23053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(cur->nodeTab, 0 ,
23063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
23073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax = XML_NODESET_DEFAULT;
23083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->nodeNr == cur->nodeMax) {
23093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNodePtr *temp;
23103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax *= 2;
23123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
23133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				      sizeof(xmlNodePtr));
23143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (temp == NULL) {
2315d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
23163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
23173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
23183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->nodeTab = temp;
23193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2320044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
2321044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlNsPtr ns = (xmlNsPtr) val;
2322044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2323044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] =
2324044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2325044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else
2326044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] = val;
23273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
23283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
23303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetMerge:
23313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val1:  the first NodeSet or NULL
23323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val2:  the second NodeSet
23333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Merges two nodesets, all nodes from @val2 are added to @val1
23353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if @val1 is NULL, a new set is created and copied from @val2
23363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
2337cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns @val1 once extended or NULL in case of error.
23383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
23393473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodeSetPtr
23403473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
2341d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    int i, j, initNr, skip;
23423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val2 == NULL) return(val1);
23443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val1 == NULL) {
23453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	val1 = xmlXPathNodeSetCreate(NULL);
23463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
23473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2348081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
23493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    initNr = val1->nodeNr;
23503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < val2->nodeNr;i++) {
23523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
2353081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	 * check against duplicates
23543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
2355d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	skip = 0;
2356d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	for (j = 0; j < initNr; j++) {
2357d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    if (val1->nodeTab[j] == val2->nodeTab[i]) {
2358d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		skip = 1;
2359d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		break;
2360044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    } else if ((val1->nodeTab[j]->type == XML_NAMESPACE_DECL) &&
2361044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		       (val2->nodeTab[i]->type == XML_NAMESPACE_DECL)) {
2362044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns1, ns2;
2363044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns1 = (xmlNsPtr) val1->nodeTab[j];
2364044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns2 = (xmlNsPtr) val2->nodeTab[i];
2365044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns1->next == ns2->next) &&
2366044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (xmlStrEqual(ns1->prefix, ns2->prefix))) {
2367044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    skip = 1;
2368044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    break;
2369044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		}
2370d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    }
2371d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	}
2372d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	if (skip)
2373d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    continue;
23743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
23763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * grow the nodeTab if needed
23773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
23783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (val1->nodeMax == 0) {
23793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
23803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor						    sizeof(xmlNodePtr));
23813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (val1->nodeTab == NULL) {
2382d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	        xmlXPathErrMemory(NULL, "merging nodeset\n");
23833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
23843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
23853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    memset(val1->nodeTab, 0 ,
23863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
23873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeMax = XML_NODESET_DEFAULT;
23883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (val1->nodeNr == val1->nodeMax) {
23893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNodePtr *temp;
23903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeMax *= 2;
23923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
23933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
23943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (temp == NULL) {
2395d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	        xmlXPathErrMemory(NULL, "merging nodeset\n");
23963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
23973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
23983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeTab = temp;
23993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
2400044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2401044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
2402044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2403044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    val1->nodeTab[val1->nodeNr++] =
2404044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2405044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	} else
2406044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
24073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
24083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
24093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(val1);
24103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
24113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
24123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
241375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * xmlXPathNodeSetMergeUnique:
241475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * @val1:  the first NodeSet or NULL
241575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * @val2:  the second NodeSet
241675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard *
241775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * Merges two nodesets, all nodes from @val2 are added to @val1
241875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * if @val1 is NULL, a new set is created and copied from @val2
241975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard *
242075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * Returns @val1 once extended or NULL in case of error.
242175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard */
242275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillardstatic xmlNodeSetPtr
242375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel VeillardxmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
242478637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    int i;
242575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
242675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    if (val2 == NULL) return(val1);
242775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    if (val1 == NULL) {
242875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	val1 = xmlXPathNodeSetCreate(NULL);
242975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    }
243075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
2431081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
243275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
243375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    for (i = 0;i < val2->nodeNr;i++) {
243475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	/*
243575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	 * grow the nodeTab if needed
243675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	 */
243775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	if (val1->nodeMax == 0) {
243875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
243975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard						    sizeof(xmlNodePtr));
244075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    if (val1->nodeTab == NULL) {
2441d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	        xmlXPathErrMemory(NULL, "merging nodeset\n");
244275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		return(NULL);
244375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    }
244475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    memset(val1->nodeTab, 0 ,
244575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
244675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeMax = XML_NODESET_DEFAULT;
244775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	} else if (val1->nodeNr == val1->nodeMax) {
244875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    xmlNodePtr *temp;
244975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
245075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeMax *= 2;
245175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
245275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard					     sizeof(xmlNodePtr));
245375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    if (temp == NULL) {
2454d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	        xmlXPathErrMemory(NULL, "merging nodeset\n");
245575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		return(NULL);
245675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    }
245775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab = temp;
245875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	}
245975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
246075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
246175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
246275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab[val1->nodeNr++] =
246375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
246475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	} else
246575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
246675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    }
246775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
246875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    return(val1);
246975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard}
247075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
247175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard/**
24723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetDel:
24733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
24743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an xmlNodePtr
24753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
24763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Removes an xmlNodePtr from an existing NodeSet
24773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
24783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
24793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
24803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
24813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
24823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return;
24833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL) return;
24843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
24853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
2486081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * find node in nodeTab
24873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
24883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->nodeNr;i++)
24893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->nodeTab[i] == val) break;
24903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2491081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    if (i >= cur->nodeNr) {	/* not found */
24923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG
24933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
24943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
24953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		val->name);
24963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
24973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return;
24983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2499044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((cur->nodeTab[i] != NULL) &&
2500044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(cur->nodeTab[i]->type == XML_NAMESPACE_DECL))
2501044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]);
25023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeNr--;
25033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (;i < cur->nodeNr;i++)
25043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab[i] = cur->nodeTab[i + 1];
25053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeTab[cur->nodeNr] = NULL;
25063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
25073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
25093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetRemove:
25103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
25113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the index to remove
25123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Removes an entry from an existing NodeSet list.
25143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
25153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
25163473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) {
25173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return;
25183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val >= cur->nodeNr) return;
2519044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((cur->nodeTab[val] != NULL) &&
2520044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(cur->nodeTab[val]->type == XML_NAMESPACE_DECL))
2521044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]);
25223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeNr--;
25233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (;val < cur->nodeNr;val++)
25243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab[val] = cur->nodeTab[val + 1];
25253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeTab[cur->nodeNr] = NULL;
25263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
25273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
25293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeNodeSet:
25303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
25313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free the NodeSet compound (not the actual nodes !).
25333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
25343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
25353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
25363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
25373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab != NULL) {
2538044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	int i;
2539044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2540081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	/* @@ with_ns to check whether namespace nodes should be looked at @@ */
2541044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0;i < obj->nodeNr;i++)
2542044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if ((obj->nodeTab[i] != NULL) &&
2543044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		(obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
2544044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
25453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(obj->nodeTab);
25463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
25473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
25483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
25493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
25513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeValueTree:
25523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
25533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free the NodeSet compound and the actual tree, this is different
25553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * from xmlXPathFreeNodeSet()
25563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
255756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
25583473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeValueTree(xmlNodeSetPtr obj) {
25593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
25603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
25623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab != NULL) {
2564044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0;i < obj->nodeNr;i++) {
2565044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (obj->nodeTab[i] != NULL) {
2566044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if (obj->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2567044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
2568044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		} else {
2569044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    xmlFreeNodeList(obj->nodeTab[i]);
2570044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		}
2571044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
2572044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
25733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(obj->nodeTab);
25743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
25753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
25763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
25773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(DEBUG) || defined(DEBUG_STEP)
25793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
25803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlGenericErrorContextNodeSet:
25813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @output:  a FILE * for the output
2582081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * @obj:  the xmlNodeSetPtr to display
25833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
25843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Quick display of a NodeSet
25853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
25863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
25873473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) {
25883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
25893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
25903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (output == NULL) output = xmlGenericErrorContext;
25913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL)  {
25923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "NodeSet == NULL !\n");
25933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
25943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
25953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeNr == 0) {
25963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "NodeSet is empty\n");
25973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
25983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
25993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab == NULL) {
26003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, " nodeTab == NULL !\n");
26013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
26023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
26033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0; i < obj->nodeNr; i++) {
26043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (obj->nodeTab[i] == NULL) {
26053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " NULL !\n");
26063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
26073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
26083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) ||
26093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE))
26103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " /");
26113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (obj->nodeTab[i]->name == NULL)
26123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " noname!");
26133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else fprintf(output, " %s", obj->nodeTab[i]->name);
26143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
26153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fprintf(output, "\n");
26163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
26183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewNodeSet:
26213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
26223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type NodeSet and initialize
26243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the single Node @val
26253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
26273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26283473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
26293473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewNodeSet(xmlNodePtr val) {
26303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
26313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
26333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
2634d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating nodeset\n");
26353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
26363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
26373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
26383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NODESET;
263977851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard    ret->boolval = 0;
26403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = xmlXPathNodeSetCreate(val);
2641081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
26423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
26433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewValueTree:
26473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
26483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize
26503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the tree root @val
26513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
26533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26543473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
26553473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewValueTree(xmlNodePtr val) {
26563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
26573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
26593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
2660d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating result value tree\n");
26613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
26623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
26633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
26643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_XSLT_TREE;
26650ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    ret->boolval = 1;
26660ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    ret->user = (void *) val;
26673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = xmlXPathNodeSetCreate(val);
26683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
26693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewNodeSetList:
26733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an existing NodeSet
26743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type NodeSet and initialize
26763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the Nodeset @val
26773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
26793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26803473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
2681044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNewNodeSetList(xmlNodeSetPtr val)
2682044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard{
26833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
26843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
26853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL)
2687044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = NULL;
26883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (val->nodeTab == NULL)
2689044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = xmlXPathNewNodeSet(NULL);
2690044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    else {
2691044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = xmlXPathNewNodeSet(val->nodeTab[0]);
2692044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        for (i = 1; i < val->nodeNr; ++i)
2693044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard            xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]);
2694044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
26953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2696044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    return (ret);
26973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathWrapNodeSet:
27013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
27023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Wrap the Nodeset @val in a new xmlXPathObjectPtr
27043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
27063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27073473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
27083473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathWrapNodeSet(xmlNodeSetPtr val) {
27093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
27103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
27123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
2713d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating node set object\n");
27143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
27153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
27163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
27173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NODESET;
27183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = val;
27193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
27203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeNodeSetList:
27243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  an existing NodeSetList object
27253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
27273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the list contrary to xmlXPathFreeObject().
27283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
27303473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
27313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
27323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
27333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2735f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2736f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDifference:
2737f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2738f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2739f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2740f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets difference() function:
2741f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:difference (node-set, node-set)
2742f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2743f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the difference between the two node sets, or nodes1 if
2744f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         nodes2 is empty
2745f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2746f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2747f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2748f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2749f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l1;
2750f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2751f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2752f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2753f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2754f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2755f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2756f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2757f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2758f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2759f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l1 = xmlXPathNodeSetGetLength(nodes1);
2760f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2761f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l1; i++) {
2762f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2763f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (!xmlXPathNodeSetContains(nodes2, cur))
2764f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2765f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2766f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2767f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2768f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2769f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2770f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathIntersection:
2771f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2772f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2773f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2774f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets intersection() function:
2775f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:intersection (node-set, node-set)
2776f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2777f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a node set comprising the nodes that are within both the
2778f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         node sets passed as arguments
2779f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2780f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2781f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2782f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
2783f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l1;
2784f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2785f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2786f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2787f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2788f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2789f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2790f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2791f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l1 = xmlXPathNodeSetGetLength(nodes1);
2792f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2793f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l1; i++) {
2794f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2795f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlXPathNodeSetContains(nodes2, cur))
2796f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2797f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2798f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2799f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2800f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2801f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2802f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDistinctSorted:
2803f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set, sorted by document order
2804f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2805f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets distinct() function:
2806f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:distinct (node-set)
2807f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2808f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a subset of the nodes contained in @nodes, or @nodes if
2809f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         it is empty
2810f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2811f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2812f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
2813f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2814f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlHashTablePtr hash;
2815f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2816f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlChar * strval;
2817f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2818f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2819f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes))
2820f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2821f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2822f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2823f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2824f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    hash = xmlHashCreate (l);
2825f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2826f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2827f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	strval = xmlXPathCastNodeToString(cur);
2828f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlHashLookup(hash, strval) == NULL) {
2829f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlHashAddEntry(hash, strval, strval);
2830f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2831f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	} else {
2832f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlFree(strval);
2833f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	}
2834f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2835f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlHashFree(hash, (xmlHashDeallocator) xmlFree);
2836f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2837f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2838f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2839f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2840f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDistinct:
2841f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2842f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2843f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets distinct() function:
2844f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:distinct (node-set)
2845f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #exslSetsDistinctSorted
2846f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called with the sorted node-set
2847f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2848f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a subset of the nodes contained in @nodes, or @nodes if
2849f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         it is empty
2850f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2851f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2852f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDistinct (xmlNodeSetPtr nodes) {
2853f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes))
2854f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2855f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2856f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2857f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathDistinctSorted(nodes));
2858f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2859f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2860f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2861f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathHasSameNodes:
2862f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2863f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2864f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2865f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets has-same-nodes function:
2866f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    boolean set:has-same-node(node-set, node-set)
2867f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2868f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
2869f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         otherwise
2870f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2871f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
2872f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2873f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2874f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2875f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2876f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1) ||
2877f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetIsEmpty(nodes2))
2878f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
2879f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2880f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes1);
2881f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2882f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2883f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlXPathNodeSetContains(nodes2, cur))
2884f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    return(1);
2885f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2886f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(0);
2887f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2888f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2889f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2890f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeLeadingSorted:
2891f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes: a node-set, sorted by document order
2892f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node: a node
2893f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2894f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2895f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2896f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2897f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that precede @node in document order,
2898f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2899f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2900f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2901f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2902f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
2903f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2904f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2905f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2906f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2907f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (node == NULL)
2908f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2909f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2910f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2911f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes) ||
2912f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	(!xmlXPathNodeSetContains(nodes, node)))
2913f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2914f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2915f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2916f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2917f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2918f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (cur == node)
2919f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    break;
2920f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetAddUnique(ret, cur);
2921f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2922f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2923f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2924f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2925f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2926f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeLeading:
2927f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2928f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node:  a node
2929f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2930f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2931f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2932f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
2933f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called.
2934f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2935f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that precede @node in document order,
2936f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2937f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2938f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2939f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2940f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
2941f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2942f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes, node));
2943f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2944f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2945f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2946f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathLeadingSorted:
2947f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set, sorted by document order
2948f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set, sorted by document order
2949f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2950f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2951f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2952f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2953f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that precede the first node in @nodes2
2954f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2955f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2956f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2957f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2958f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2959f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2960f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2961f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes1,
2962f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				     xmlXPathNodeSetItem(nodes2, 1)));
2963f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2964f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2965f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2966f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathLeading:
2967f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2968f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2969f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2970f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2971f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2972f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1 and @nodes2 are sorted by document order, then
2973f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * #exslSetsLeadingSorted is called.
2974f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2975f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that precede the first node in @nodes2
2976f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2977f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2978f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2979f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2980f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2981f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2982f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2983f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2984f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(xmlXPathNodeSetCreate(NULL));
2985f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes1);
2986f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes2);
2987f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes1,
2988f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				     xmlXPathNodeSetItem(nodes2, 1)));
2989f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2990f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2991f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2992f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeTrailingSorted:
2993f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes: a node-set, sorted by document order
2994f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node: a node
2995f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2996f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2997f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2998f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2999f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that follow @node in document order,
3000f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
3001f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
3002f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
3003f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
3004f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
3005f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
3006f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
3007f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
3008f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3009f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (node == NULL)
3010f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
3011f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3012f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
3013f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes) ||
3014f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	(!xmlXPathNodeSetContains(nodes, node)))
3015f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
3016f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3017f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
3018f186c8259ae985cd56b3e14c1def484ab127fd14Thomas Broyer    for (i = l; i > 0; i--) {
3019f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
3020f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (cur == node)
3021f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    break;
3022f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetAddUnique(ret, cur);
3023f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
3024f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
3025f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
3026f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3027f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
3028f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeTrailing:
3029f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
3030f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node:  a node
3031f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3032f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
3033f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
3034f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
3035f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called.
3036f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3037f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that follow @node in document order,
3038f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
3039f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
3040f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
3041f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
3042f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
3043f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
3044f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes, node));
3045f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
3046f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3047f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
3048f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathTrailingSorted:
3049f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set, sorted by document order
3050f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set, sorted by document order
3051f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3052f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
3053f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
3054f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3055f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that follow the first node in @nodes2
3056f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
3057f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
3058f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
3059f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
3060f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3061f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
3062f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
3063f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes1,
3064f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				      xmlXPathNodeSetItem(nodes2, 0)));
3065f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
3066f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3067f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
3068f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathTrailing:
3069f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
3070f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
3071f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3072f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
3073f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
3074f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1 and @nodes2 are sorted by document order, then
3075f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * #xmlXPathTrailingSorted is called.
3076f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3077f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that follow the first node in @nodes2
3078f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
3079f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
3080f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
3081f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
3082f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3083f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
3084f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
3085f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
3086f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(xmlXPathNodeSetCreate(NULL));
3087f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes1);
3088f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes2);
3089f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes1,
3090f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				      xmlXPathNodeSetItem(nodes2, 0)));
3091f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
3092f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
30933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
30943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
30953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle extra functions			*
30963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
30973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
30983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
31003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterFunc:
31013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
31023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
31033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the function implementation or NULL
31043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new function. If @f is NULL it unregisters the function
31063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
31083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
31103473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
31113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		     xmlXPathFunction f) {
31123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f));
31133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
31163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterFuncNS:
31173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
31183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
31193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the function namespace URI
31203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the function implementation or NULL
31213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new function. If @f is NULL it unregisters the function
31233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
31253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
31273473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
31283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		       const xmlChar *ns_uri, xmlXPathFunction f) {
31293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
31303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
31313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
31323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
31333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->funcHash == NULL)
31353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->funcHash = xmlHashCreate(0);
31363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->funcHash == NULL)
31373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
313894394cd1e494f8d669b310748f54192268185c8dDaniel Veillard    if (f == NULL)
313994394cd1e494f8d669b310748f54192268185c8dDaniel Veillard        return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL));
3140ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack    return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, XML_CAST_FPTR(f)));
31413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3144ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * xmlXPathRegisterFuncLookup:
3145ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * @ctxt:  the XPath context
3146ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * @f:  the lookup function
3147cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @funcCtxt:  the lookup data
3148ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer *
3149cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Registers an external mechanism to do function lookup.
3150ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer */
3151ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyervoid
3152ba4ad3263bf7f5625329f115367e0c7018521a16Thomas BroyerxmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
3153ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer			    xmlXPathFuncLookupFunc f,
3154ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer			    void *funcCtxt) {
3155ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt == NULL)
3156ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return;
31576ebf3c4c1a78406d15e8629b4a7b3d52549f0c8bDaniel Veillard    ctxt->funcLookupFunc = f;
3158ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    ctxt->funcLookupData = funcCtxt;
3159ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer}
3160ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
3161ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer/**
31623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFunctionLookup:
31633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
31643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
31653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Function array of the context for the given
31673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * function.
31683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathFunction or NULL if not found
31703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31713473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunction
31723473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
3173ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt == NULL)
3174ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return (NULL);
3175ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
3176ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcLookupFunc != NULL) {
3177ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	xmlXPathFunction ret;
317899e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	xmlXPathFuncLookupFunc f;
3179ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
31806ebf3c4c1a78406d15e8629b4a7b3d52549f0c8bDaniel Veillard	f = ctxt->funcLookupFunc;
3181963d2ae41574066f9b44bcae610dd280c1e57dd8Daniel Veillard	ret = f(ctxt->funcLookupData, name, NULL);
3182ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	if (ret != NULL)
3183ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	    return(ret);
3184ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    }
31853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
31863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
31893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFunctionLookupNS:
31903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
31913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
31923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the function namespace URI
31933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Function array of the context for the given
31953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * function.
31963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathFunction or NULL if not found
31983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31993473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunction
32003473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
32013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 const xmlChar *ns_uri) {
3202ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack    xmlXPathFunction ret;
3203ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack
32043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
32053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
32063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
32073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
32083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3209ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcLookupFunc != NULL) {
321099e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	xmlXPathFuncLookupFunc f;
3211ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
32126ebf3c4c1a78406d15e8629b4a7b3d52549f0c8bDaniel Veillard	f = ctxt->funcLookupFunc;
3213963d2ae41574066f9b44bcae610dd280c1e57dd8Daniel Veillard	ret = f(ctxt->funcLookupData, name, ns_uri);
3214ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	if (ret != NULL)
3215ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	    return(ret);
3216ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    }
3217ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
3218ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcHash == NULL)
3219ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return(NULL);
3220ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
3221ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack    XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
3222ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack    return(ret);
32233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
32263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisteredFuncsCleanup:
32273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
32283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered functions
32303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
32313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
32323473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
32333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
32343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
32353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlHashFree(ctxt->funcHash, NULL);
32373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->funcHash = NULL;
32383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
32413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
3242081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack *			Routines to handle Variables			*
32433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
32443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
32453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
32473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariable:
32483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
32493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
32503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @value:  the variable value or NULL
32513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new variable value. If @value is NULL it unregisters
32533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the variable
32543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
32563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
32573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
32583473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
32593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 xmlXPathObjectPtr value) {
32603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value));
32613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
32643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariableNS:
32653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
32663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
32673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the variable namespace URI
32683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @value:  the variable value or NULL
32693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new variable value. If @value is NULL it unregisters
32713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the variable
32723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
32743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
32753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
32763473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name,
32773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   const xmlChar *ns_uri,
32783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   xmlXPathObjectPtr value) {
32793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
32803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
32813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
32823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
32833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
32853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->varHash = xmlHashCreate(0);
32863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
32873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
328894394cd1e494f8d669b310748f54192268185c8dDaniel Veillard    if (value == NULL)
328994394cd1e494f8d669b310748f54192268185c8dDaniel Veillard        return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri,
329094394cd1e494f8d669b310748f54192268185c8dDaniel Veillard	                           (xmlHashDeallocator)xmlXPathFreeObject));
32913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
32923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			       (void *) value,
32933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			       (xmlHashDeallocator)xmlXPathFreeObject));
32943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
32973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariableLookup:
32983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
32993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the lookup function
33003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @data:  the lookup data
33013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
33023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * register an external mechanism to do variable lookup
33033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
33043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
33053473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
33063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 xmlXPathVariableLookupFunc f, void *data) {
33073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
33083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
33096ebf3c4c1a78406d15e8629b4a7b3d52549f0c8bDaniel Veillard    ctxt->varLookupFunc = f;
33103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varLookupData = data;
33113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
33123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
33143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathVariableLookup:
33153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
33163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
33173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
33183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Variable array of the context for the given
33193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * variable value.
33203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
332173c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * Returns a copy of the value or NULL if not found
33223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
33233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
33243473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
33253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
33263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
33273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varLookupFunc != NULL) {
33293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathObjectPtr ret;
33303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
33323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        (ctxt->varLookupData, name, NULL);
3333556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	return(ret);
33343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
33353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathVariableLookupNS(ctxt, name, NULL));
33363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
33373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
33393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathVariableLookupNS:
33403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
33413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
33423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the variable namespace URI
33433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
33443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Variable array of the context for the given
334573c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * variable value.
33463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
334773c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * Returns the a copy of the value or NULL if not found
33483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
33493473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
33503473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
33513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 const xmlChar *ns_uri) {
33523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
33533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
33543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varLookupFunc != NULL) {
33563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathObjectPtr ret;
33573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
33593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        (ctxt->varLookupData, name, ns_uri);
33603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret != NULL) return(ret);
33613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
33623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
33643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
33653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
33663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
33673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33688c357d58c2d1dde022b67393a47dcb52100ce129Daniel Veillard    return(xmlXPathObjectCopy((xmlXPathObjectPtr)
33698c357d58c2d1dde022b67393a47dcb52100ce129Daniel Veillard		xmlHashLookup2(ctxt->varHash, name, ns_uri)));
33703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
33713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
33733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisteredVariablesCleanup:
33743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
33753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
33763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered variables
33773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
33783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
33793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
33803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
33813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
33823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
338376d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard    xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject);
33843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varHash = NULL;
33853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
33863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
33883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterNs:
33893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
33903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  the namespace prefix
33913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the namespace name
33923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
33933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new namespace. If @ns_uri is NULL it unregisters
33943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the namespace
33953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
33963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
33973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
33983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
33993473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
34003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   const xmlChar *ns_uri) {
34013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
34023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
34033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
34043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
34053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->nsHash == NULL)
34073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->nsHash = xmlHashCreate(10);
34083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->nsHash == NULL)
34093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
3410e991fe958f5269a459262bcff802a3d26167edb8Daniel Veillard    if (ns_uri == NULL)
341194394cd1e494f8d669b310748f54192268185c8dDaniel Veillard        return(xmlHashRemoveEntry(ctxt->nsHash, prefix,
3412e991fe958f5269a459262bcff802a3d26167edb8Daniel Veillard	                          (xmlHashDeallocator)xmlFree));
341342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri),
34143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			      (xmlHashDeallocator)xmlFree));
34153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
34163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
34183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNsLookup:
34193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
34203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  the namespace prefix value
34213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
34223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the namespace declaration array of the context for the given
34233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace name associated to the given prefix
34243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
34253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the value or NULL if not found
34263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
34273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorconst xmlChar *
34283473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
34293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
34303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
34313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
34323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
34333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef XML_XML_NAMESPACE
34353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
34363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(XML_XML_NAMESPACE);
34373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
34383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3439c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard    if (ctxt->namespaces != NULL) {
3440c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	int i;
3441c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard
3442c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	for (i = 0;i < ctxt->nsNr;i++) {
3443c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	    if ((ctxt->namespaces[i] != NULL) &&
3444c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard		(xmlStrEqual(ctxt->namespaces[i]->prefix, prefix)))
3445c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard		return(ctxt->namespaces[i]->href);
3446c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	}
3447c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard    }
34483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
34503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
34513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
34535e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathRegisteredNsCleanup:
34543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
34553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
34563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered variables
34573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
34583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
34593473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
34603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
34613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
34623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
346342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlHashFree(ctxt->nsHash, (xmlHashDeallocator)xmlFree);
34643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->nsHash = NULL;
34653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
34663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
34683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
34693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle Values			*
34703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
34713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
34723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3473081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack/* Allocations are terrible, one needs to optimize all this !!! */
34743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
34763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewFloat:
34773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the double value
34783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
34793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type double and of value @val
34803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
34813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
34823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
34833473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
34843473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewFloat(double val) {
34853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
34863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
34883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3489d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating float object\n");
34903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
34913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
34923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
34933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NUMBER;
34943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->floatval = val;
34953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
34963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
34973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
34993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewBoolean:
35003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the boolean value
35013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
35023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type boolean and of value @val
35033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
35043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
35053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
35063473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
35073473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewBoolean(int val) {
35083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
35093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
35103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
35113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3512d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating boolean object\n");
35133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
35143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
35153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
35163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_BOOLEAN;
35173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->boolval = (val != 0);
35183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
35193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
35203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
35213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
35223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewString:
35233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the xmlChar * value
35243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
35253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type string and of value @val
35263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
35273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
35283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
35293473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
35303473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewString(const xmlChar *val) {
35313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
35323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
35333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
35343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3535d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating string object\n");
35363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
35373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
35383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
35393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_STRING;
35403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val != NULL)
35413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret->stringval = xmlStrdup(val);
35423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
35433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret->stringval = xmlStrdup((const xmlChar *)"");
35443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
35453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
35463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
35473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3548ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathWrapString:
3549ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  the xmlChar * value
3550ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3551ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Wraps the @val string into an XPath object.
3552ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3553ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the newly created object.
3554ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3555ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3556ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathWrapString (xmlChar *val) {
3557ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3558ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3559ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3560ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (ret == NULL) {
3561d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating string object\n");
3562ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(NULL);
3563ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3564ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
3565ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret->type = XPATH_STRING;
3566ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret->stringval = val;
3567ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3568ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3569ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3570ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
35713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewCString:
35723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the char * value
35733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
35743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type string and of value @val
35753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
35763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
35773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
35783473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
35793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewCString(const char *val) {
35803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
35813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
35823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
35833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3584d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating string object\n");
35853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
35863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
35873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
35883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_STRING;
35893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->stringval = xmlStrdup(BAD_CAST val);
35903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
35913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
35923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
35933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3594ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathWrapCString:
3595ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  the char * value
3596ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3597ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Wraps a string into an XPath object.
3598ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3599ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the newly created object.
3600ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3601ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3602ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathWrapCString (char * val) {
3603ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathWrapString((xmlChar *)(val)));
3604ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3605ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3606ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3607f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathWrapExternal:
3608f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @val:  the user data
3609f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3610f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Wraps the @val data into an XPath object.
3611f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3612f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the newly created object.
3613f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
3614f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathObjectPtr
3615f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathWrapExternal (void *val) {
3616f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr ret;
3617f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3618f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3619f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ret == NULL) {
3620d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating user object\n");
3621f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
3622f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
3623f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
3624f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret->type = XPATH_USERS;
3625f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret->user = val;
3626f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
3627f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
3628f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3629f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
36303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathObjectCopy:
36313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the original object
36323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
36333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * allocate a new copy of a given object
36343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
36353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
36363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
36373473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
36383473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectCopy(xmlXPathObjectPtr val) {
36393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
36403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL)
36423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
36433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
36443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
36453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3646d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "copying object\n");
36473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
36483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
36493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memcpy(ret, val , (size_t) sizeof(xmlXPathObject));
36503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (val->type) {
36513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_BOOLEAN:
36523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_NUMBER:
36533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
36543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
36553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
36563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_STRING:
36573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->stringval = xmlStrdup(val->stringval);
36583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
36593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_XSLT_TREE:
3660e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#if 0
3661e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack/*
3662e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack  Removed 11 July 2004 - the current handling of xslt tmpRVT nodes means that
3663e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack  this previous handling is no longer correct, and can cause some serious
3664e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack  problems (ref. bug 145547)
3665e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack*/
36663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((val->nodesetval != NULL) &&
36670ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard		(val->nodesetval->nodeTab != NULL)) {
36689adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		xmlNodePtr cur, tmp;
36699adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		xmlDocPtr top;
3670ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard
36710ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard		ret->boolval = 1;
36729adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		top =  xmlNewDoc(NULL);
36739adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		top->name = (char *)
36749adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    xmlStrdup(val->nodesetval->nodeTab[0]->name);
3675ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		ret->user = top;
3676ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		if (top != NULL) {
36779adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    top->doc = top;
3678ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    cur = val->nodesetval->nodeTab[0]->children;
3679ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    while (cur != NULL) {
36809adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard			tmp = xmlDocCopyNode(cur, top, 1);
36819adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard			xmlAddChild((xmlNodePtr) top, tmp);
3682ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard			cur = cur->next;
3683ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    }
3684ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		}
3685e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack
36869adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		ret->nodesetval = xmlXPathNodeSetCreate((xmlNodePtr) top);
36870ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    } else
36883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret->nodesetval = xmlXPathNodeSetCreate(NULL);
36890ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    /* Deallocate the copied tree value */
36903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
3691e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#endif
36923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_NODESET:
36933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
36940ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    /* Do not deallocate the copied tree value */
36950ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    ret->boolval = 0;
36963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
36973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
36983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
36993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	{
37003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlLocationSetPtr loc = val->user;
37013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc);
37023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
37033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
37043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
370547334c09f4373e4cff71334e60a623fee73a525fThomas Broyer        case XPATH_USERS:
370647334c09f4373e4cff71334e60a623fee73a525fThomas Broyer	    ret->user = val->user;
370747334c09f4373e4cff71334e60a623fee73a525fThomas Broyer	    break;
370847334c09f4373e4cff71334e60a623fee73a525fThomas Broyer        case XPATH_UNDEFINED:
37093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
37103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathObjectCopy: unsupported type %d\n",
37113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    val->type);
37123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
37133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
37143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
37153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
37163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
37183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeObject:
37193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the object to free
37203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
37213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathObjectPtr object.
37223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
37233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
37243473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeObject(xmlXPathObjectPtr obj) {
37253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
37260ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
372777851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	if (obj->boolval) {
3728e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#if 0
37290ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    if (obj->user != NULL) {
37300ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard                xmlXPathFreeNodeSet(obj->nodesetval);
373138bf6f042507c6051bfa2db5cc9b6666cfc35c2aDaniel Veillard		xmlFreeNodeList((xmlNodePtr) obj->user);
3732e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack	    } else
3733e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#endif
3734e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack	    if (obj->nodesetval != NULL)
373577851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard		xmlXPathFreeValueTree(obj->nodesetval);
373677851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	} else {
373777851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	    if (obj->nodesetval != NULL)
373877851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard		xmlXPathFreeNodeSet(obj->nodesetval);
373977851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	}
37403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
37413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (obj->type == XPATH_LOCATIONSET) {
37423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (obj->user != NULL)
37433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPtrFreeLocationSet(obj->user);
37443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
37453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (obj->type == XPATH_STRING) {
37463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (obj->stringval != NULL)
37473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(obj->stringval);
37483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
37493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
37513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
37523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3753ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3754ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/************************************************************************
3755ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *									*
3756ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *			Type Casting Routines				*
3757ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *									*
3758ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard ************************************************************************/
3759ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3760ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3761ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastBooleanToString:
3762ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a boolean
3763ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3764ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a boolean to its string value.
3765ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3766ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3767ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3768ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3769ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastBooleanToString (int val) {
3770ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret;
3771ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val)
3772ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "true");
3773ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    else
3774ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "false");
3775ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3776ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3777ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3778ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3779ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNumberToString:
3780ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a number
3781ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3782ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a number to its string value.
3783ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3784ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3785ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3786ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3787ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNumberToString (double val) {
3788ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret;
3789cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    switch (xmlXPathIsInf(val)) {
3790ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case 1:
37915fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	ret = xmlStrdup((const xmlChar *) "Infinity");
3792ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3793ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case -1:
3794ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "-Infinity");
3795ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3796ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    default:
3797cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(val)) {
3798ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "NaN");
3799d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	} else if (val == 0 && xmlXPathGetSign(val) != 0) {
3800d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "0");
3801ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	} else {
3802ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    /* could be improved */
3803ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    char buf[100];
380411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard	    xmlXPathFormatNumber(val, buf, 99);
380511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard	    buf[99] = 0;
3806ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) buf);
3807ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	}
3808ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3809ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3810ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3811ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3812ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3813ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeToString:
3814ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @node:  a node
3815ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3816ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node to its string value.
3817ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3818ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3819ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3820ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3821ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeToString (xmlNodePtr node) {
3822ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlNodeGetContent(node));
3823ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3824ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3825ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3826ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToString:
3827ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3828ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3829ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its string value.
3830ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3831ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3832ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3833ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3834ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
3835ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
3836ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlStrdup((const xmlChar *) ""));
3837ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3838ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathNodeSetSort(ns);
3839ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathCastNodeToString(ns->nodeTab[0]));
3840ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3841ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3842ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3843ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastToString:
3844ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3845ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3846ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its string() equivalent
3847ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3848ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the string value of the object, NULL in case of error.
3849cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *         A new string is allocated only if needed (@val isn't a
3850ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         string object).
3851ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3852ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3853ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToString(xmlXPathObjectPtr val) {
3854ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret = NULL;
3855ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3856ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3857ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlStrdup((const xmlChar *) ""));
3858ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3859ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_UNDEFINED:
3860ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3861ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
3862ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3863ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "");
3864ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3865ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_NODESET:
38660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        case XPATH_XSLT_TREE:
3867ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastNodeSetToString(val->nodesetval);
3868ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3869ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_STRING:
38704e2df54bb17645ef0d3f28b9665b2d2dde4b47a3Daniel Veillard	    return(xmlStrdup(val->stringval));
3871ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_BOOLEAN:
3872ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastBooleanToString(val->boolval);
3873ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3874ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_NUMBER: {
3875ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastNumberToString(val->floatval);
3876ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3877ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	}
3878ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_USERS:
3879ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_POINT:
3880ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_RANGE:
3881ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_LOCATIONSET:
3882ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    TODO
3883ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "");
3884ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3885ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3886ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3887ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3888ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3889ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3890ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertString:
3891ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3892ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3893ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its string() equivalent
3894ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3895ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3896ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3897ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3898ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3899ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertString(xmlXPathObjectPtr val) {
3900ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *res = NULL;
3901ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3902ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3903ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewCString(""));
3904ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3905ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3906ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3907ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3908ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
3909ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3910ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3911ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
39120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
3913ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastNodeSetToString(val->nodesetval);
3914ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3915ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3916ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3917ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3918ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastBooleanToString(val->boolval);
3919ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3920ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3921ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastNumberToString(val->floatval);
3922ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3923ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3924ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3925ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3926ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3927ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3928ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3929ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3930ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3931ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (res == NULL)
3932ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewCString(""));
3933ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathWrapString(res));
3934ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3935ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3936ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3937ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastBooleanToNumber:
3938ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a boolean
3939ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3940ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a boolean to its number value
3941ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3942ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3943ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3944ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3945ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastBooleanToNumber(int val) {
3946ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val)
3947ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(1.0);
3948ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(0.0);
3949ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3950ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3951ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3952ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastStringToNumber:
3953ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a string
3954ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3955ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a string to its number value
3956ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3957ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3958ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3959ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3960ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastStringToNumber(const xmlChar * val) {
3961ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathStringEvalNumber(val));
3962ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3963ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3964ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3965ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeToNumber:
3966ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @node:  a node
3967ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3968ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node to its number value
3969ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3970ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3971ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3972ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3973ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeToNumber (xmlNodePtr node) {
3974ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *strval;
3975ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret;
3976ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3977ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (node == NULL)
3978ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3979ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    strval = xmlXPathCastNodeToString(node);
3980ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (strval == NULL)
3981ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3982ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathCastStringToNumber(strval);
3983ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlFree(strval);
3984ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3985ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3986ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3987ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3988ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3989ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToNumber:
3990ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3991ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3992ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its number value
3993ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3994ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3995ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3996ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3997ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
3998ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *str;
3999ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret;
4000ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4001ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (ns == NULL)
4002ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
4003ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    str = xmlXPathCastNodeSetToString(ns);
4004ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathCastStringToNumber(str);
4005ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlFree(str);
4006ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
4007ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
4008ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4009ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
4010ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastToNumber:
4011ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
4012ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4013ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an XPath object to its number value
4014ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4015ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
4016ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
4017ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
4018ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToNumber(xmlXPathObjectPtr val) {
4019ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret = 0.0;
4020ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4021ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
4022ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
4023ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
4024ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
4025ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEGUB_EXPR
4026ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
4027ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
4028ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNAN;
4029ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4030ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
40310c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
4032ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNodeSetToNumber(val->nodesetval);
4033ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4034ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
4035ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastStringToNumber(val->stringval);
4036ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4037ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
4038ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = val->floatval;
4039ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4040ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
4041ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastBooleanToNumber(val->boolval);
4042ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4043ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
4044ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
4045ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
4046ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
4047ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
4048ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNAN;
4049ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4050ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
4051ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
4052ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
4053ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4054ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
4055ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertNumber:
4056ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
4057ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4058ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its number() equivalent
4059ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4060ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
4061ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
4062ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
4063ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
4064ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertNumber(xmlXPathObjectPtr val) {
4065ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
4066ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4067ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
4068ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewFloat(0.0));
4069ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val->type == XPATH_NUMBER)
4070ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
4071ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
4072ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
4073ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
4074ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
4075ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4076ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
4077ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNumberToBoolean:
4078ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a number
4079ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4080ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a number to its boolean value
4081ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4082ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
4083ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
4084ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
4085ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNumberToBoolean (double val) {
4086cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard     if (xmlXPathIsNaN(val) || (val == 0.0))
4087ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	 return(0);
4088ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard     return(1);
4089ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
4090ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4091ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
4092ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastStringToBoolean:
4093ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a string
4094ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4095ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a string to its boolean value
4096ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4097ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
4098ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
4099ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
4100ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastStringToBoolean (const xmlChar *val) {
4101ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((val == NULL) || (xmlStrlen(val) == 0))
4102ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
4103ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(1);
4104ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
4105ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4106ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
4107ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToBoolean:
4108ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
4109ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4110ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its boolean value
4111ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4112ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
4113ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
4114ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
4115ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
4116ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((ns == NULL) || (ns->nodeNr == 0))
4117ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
4118ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(1);
4119ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
4120ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4121ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
41225e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathCastToBoolean:
4123ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
4124ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4125ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an XPath object to its boolean value
4126ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4127ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
4128ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
4129ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
4130ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToBoolean (xmlXPathObjectPtr val) {
4131ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    int ret = 0;
4132ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4133ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
4134ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
4135ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
4136ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
4137ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
4138ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n");
4139ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
4140ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = 0;
4141ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4142ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
41430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
4144ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
4145ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4146ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
4147ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastStringToBoolean(val->stringval);
4148ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4149ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
4150ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNumberToBoolean(val->floatval);
4151ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4152ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
4153ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = val->boolval;
4154ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4155ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
4156ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
4157ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
4158ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
4159ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
4160ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = 0;
4161ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
4162ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
4163ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
4164ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
4165ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4166ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4167ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
4168ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertBoolean:
4169ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
4170ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4171ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its boolean() equivalent
4172ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
4173ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
4174ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
4175ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
4176ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
4177ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertBoolean(xmlXPathObjectPtr val) {
4178ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
4179ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
4180ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
4181ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewBoolean(0));
4182ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val->type == XPATH_BOOLEAN)
4183ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
4184ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
4185ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
4186ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
4187ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
4188ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
41893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
41903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
41913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle XPath contexts			*
41923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
41933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
41943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
41963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewContext:
41973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @doc:  the XML document
41983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathContext
42003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
4201af43f63aaabf0dc4b4a070773875d0927da3d8a2Daniel Veillard * Returns the xmlXPathContext just allocated. The caller will need to free it.
42023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
42033473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathContextPtr
42043473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewContext(xmlDocPtr doc) {
42053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathContextPtr ret;
42063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
42083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
4209d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating context\n");
42103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
42113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
42123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
42133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->doc = doc;
42143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->node = NULL;
42153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->varHash = NULL;
42173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nb_types = 0;
42193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->max_types = 0;
42203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->types = NULL;
42213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->funcHash = xmlHashCreate(0);
42233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nb_axis = 0;
42253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->max_axis = 0;
42263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->axis = NULL;
42273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nsHash = NULL;
42293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->user = NULL;
42303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->contextSize = -1;
42323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->proximityPosition = -1;
42333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterAllFunctions(ret);
42353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
42373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
42383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
42403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeContext:
42413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the context to free
42423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathContext
42443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
42453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
42463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeContext(xmlXPathContextPtr ctxt) {
42477eca35fbaef6bd06074c4b978d381303609fcb0bDaniel Veillard    if (ctxt == NULL) return;
42487eca35fbaef6bd06074c4b978d381303609fcb0bDaniel Veillard
42493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredNsCleanup(ctxt);
42503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredFuncsCleanup(ctxt);
42513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredVariablesCleanup(ctxt);
42527eca35fbaef6bd06074c4b978d381303609fcb0bDaniel Veillard    xmlResetError(&ctxt->lastError);
42533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
42543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
42553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
42573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
42583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle XPath parser contexts		*
42593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
42603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
42613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CHECK_CTXT(ctxt)						\
42633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) { 						\
4264f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack	__xmlRaiseError(NULL, NULL, NULL,				\
4265f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		NULL, NULL, XML_FROM_XPATH,				\
4266f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL,			\
4267f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		__FILE__, __LINE__,					\
4268f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		NULL, NULL, NULL, 0, 0,					\
4269f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		"NULL context pointer\n");				\
4270f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack	return(NULL);							\
42713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
42723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CHECK_CONTEXT(ctxt)						\
427557b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard    if ((ctxt == NULL) || (ctxt->doc == NULL) ||			\
427657b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard        (ctxt->doc->children == NULL)) { 				\
427757b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_INVALID_CTXT);	\
4278ce682bc24b79f1dd29b781d4c17f9bf169ce7e32Daniel Veillard	return(NULL);							\
427957b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard    }
42803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
42833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewParserContext:
42843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
42853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
42863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathParserContext
42883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathParserContext just allocated.
42903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
42913473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParserContextPtr
42923473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
42933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr ret;
42943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
42963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
4297d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(ctxt, "creating parser context\n");
42983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
42993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
43003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
43013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->cur = ret->base = str;
43023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->context = ctxt;
43033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret->comp = xmlXPathNewCompExpr();
43059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret->comp == NULL) {
43069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret->valueTab);
43079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret);
43089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
43099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
43104773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if ((ctxt != NULL) && (ctxt->dict != NULL)) {
43114773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        ret->comp->dict = ctxt->dict;
43124773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	xmlDictReference(ret->comp->dict);
43134773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    }
43149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
43159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(ret);
43169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
43179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
43189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
43199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompParserContext:
43209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the XPath compiled expression
43219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctxt:  the XPath context
43229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
43239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Create a new xmlXPathParserContext when processing a compiled expression
43249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
43259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns the xmlXPathParserContext just allocated.
43269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
432756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathParserContextPtr
43289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
43299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathParserContextPtr ret;
43309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
43319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
43329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret == NULL) {
4333d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(ctxt, "creating evaluation context\n");
43349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
43359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
43369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
43379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
43383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Allocate the value stack */
43393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueTab = (xmlXPathObjectPtr *)
43403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                     xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
43419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret->valueTab == NULL) {
43429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret);
4343d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	xmlXPathErrMemory(ctxt, "creating evaluation context\n");
43449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
43459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
43463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueNr = 0;
43473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueMax = 10;
43483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->value = NULL;
43499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4350fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    ret->context = ctxt;
43519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret->comp = comp;
43529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
43533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
43543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
43553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
43573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeParserContext:
43583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the context to free
43593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathParserContext
43613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
43623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
43633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
43643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->valueTab != NULL) {
43653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(ctxt->valueTab);
43663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
436756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (ctxt->comp != NULL) {
436856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
436956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ctxt->comp->stream != NULL) {
437056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    xmlFreePatternList(ctxt->comp->stream);
437156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    ctxt->comp->stream = NULL;
437256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
437356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
43749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathFreeCompExpr(ctxt->comp);
437556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
43763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
43773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
43783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
43803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
43813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		The implicit core function library			*
43823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
43833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
43843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
438601c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathNodeValHash:
4387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @node:  a node pointer
4388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Function computing the beginning of the string value of the node,
4390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * used to speed up comparisons
4391f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4392f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns an int usable as a hash
4393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
4394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic unsigned int
4395f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNodeValHash(xmlNodePtr node) {
4396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int len = 2;
4397f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar * string = NULL;
4398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr tmp = NULL;
4399f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int ret = 0;
4400f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (node == NULL)
4402f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4403f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
44049adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard    if (node->type == XML_DOCUMENT_NODE) {
44059adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	tmp = xmlDocGetRootElement((xmlDocPtr) node);
44069adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	if (tmp == NULL)
44079adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    node = node->children;
44089adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	else
44099adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    node = tmp;
44109adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard
44119adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	if (node == NULL)
44129adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    return(0);
44139adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard    }
4414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4415f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (node->type) {
4416f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_COMMENT_NODE:
4417f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_PI_NODE:
4418f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_CDATA_SECTION_NODE:
4419f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_TEXT_NODE:
4420f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    string = node->content;
4421f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string == NULL)
4422f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
4423f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
4424f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
4425f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(((unsigned int) string[0]) +
4426f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		   (((unsigned int) string[1]) << 8));
4427f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_NAMESPACE_DECL:
4428f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    string = ((xmlNsPtr)node)->href;
4429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string == NULL)
4430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
4431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
4432f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
4433f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(((unsigned int) string[0]) +
4434f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		   (((unsigned int) string[1]) << 8));
4435f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_ATTRIBUTE_NODE:
4436f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = ((xmlAttrPtr) node)->children;
4437f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
4438f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_ELEMENT_NODE:
4439f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = node->children;
4440f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
4441f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	default:
4442f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(0);
4443f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
4444f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (tmp != NULL) {
4445f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	switch (tmp->type) {
4446f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_COMMENT_NODE:
4447f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_PI_NODE:
4448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_CDATA_SECTION_NODE:
4449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_TEXT_NODE:
4450f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		string = tmp->content;
4451f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4452f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_NAMESPACE_DECL:
4453f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		string = ((xmlNsPtr)tmp)->href;
4454f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4455f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    default:
4456f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4457f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4458f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if ((string != NULL) && (string[0] != 0)) {
4459f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (len == 1) {
4460f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(ret + (((unsigned int) string[0]) << 8));
4461f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4462f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[1] == 0) {
4463f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		len = 1;
4464f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		ret = (unsigned int) string[0];
4465f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    } else {
4466f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(((unsigned int) string[0]) +
4467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		       (((unsigned int) string[1]) << 8));
4468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4469f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	/*
4471f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	 * Skip to next node
4472f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	 */
4473f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if ((tmp->children != NULL) && (tmp->type != XML_DTD_NODE)) {
4474f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp->children->type != XML_ENTITY_DECL) {
4475f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = tmp->children;
4476f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		continue;
4477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4479f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (tmp == node)
4480f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
4481f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (tmp->next != NULL) {
4483f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = tmp->next;
4484f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    continue;
4485f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4487f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	do {
4488f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = tmp->parent;
4489f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp == NULL)
4490f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4491f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp == node) {
4492f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = NULL;
4493f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4494f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4495f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp->next != NULL) {
4496f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = tmp->next;
4497f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	} while (tmp != NULL);
4500f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
4501f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(ret);
4502f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
4503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
4505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathStringHash:
4506f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @string:  a string
4507f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4508f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Function computing the beginning of the string value of the node,
4509f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * used to speed up comparisons
4510f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4511f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns an int usable as a hash
4512f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
4513f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic unsigned int
4514f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathStringHash(const xmlChar * string) {
4515f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (string == NULL)
4516f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return((unsigned int) 0);
4517f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (string[0] == 0)
4518f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4519f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(((unsigned int) string[0]) +
4520f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	   (((unsigned int) string[1]) << 8));
4521f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
4522f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4523f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
45243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetFloat:
45253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
45263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
45273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
45283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
45293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the value
45303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a number
45323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
45333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
45343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
45353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
45363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a number,
45383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in the
45393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node-set such that the result of performing the comparison on the number
45403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be compared and on the result of converting the string-value of that
45413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node to a number using the number function is true.
45423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
45443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
454556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
45463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
45473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr f) {
45483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, ret = 0;
45493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
45503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
45513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((f == NULL) || (arg == NULL) ||
45533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
45543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg);
45553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(f);
45563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
45573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
45583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4559911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (ns != NULL) {
4560911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < ns->nodeNr;i++) {
4561ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
4562911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     if (str2 != NULL) {
4563911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt,
4564911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard			   xmlXPathNewString(str2));
4565911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlFree(str2);
4566911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlXPathNumberFunction(ctxt, 1);
4567911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt, xmlXPathObjectCopy(f));
4568911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 ret = xmlXPathCompareValues(ctxt, inf, strict);
4569911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 if (ret)
4570911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		     break;
4571911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     }
4572911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
45733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
45743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
45753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(f);
45763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
45773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
45783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
45803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetString:
45813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
45823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
45833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
45843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
45853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @s:  the value
45863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a string
45883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
45893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
45903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
45913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
45923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a string,
45943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
45953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
45963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string-value of the node and the other string is true.
45973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
45993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
460056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
46013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
46023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr s) {
46033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, ret = 0;
46043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
46053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
46063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((s == NULL) || (arg == NULL) ||
46083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
46093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg);
46103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(s);
46113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
46123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4614911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (ns != NULL) {
4615911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < ns->nodeNr;i++) {
4616ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
4617911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     if (str2 != NULL) {
4618911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt,
4619911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard			   xmlXPathNewString(str2));
4620911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlFree(str2);
4621911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt, xmlXPathObjectCopy(s));
4622911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 ret = xmlXPathCompareValues(ctxt, inf, strict);
4623911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 if (ret)
4624911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		     break;
4625911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     }
4626911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
46273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
46293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(s);
46303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
46313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
46323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
46343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSets:
4635ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @inf:  less than (1) or greater than (0)
46363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
4637cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @arg1:  the first node set object
46383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg2:  the second node set object
46393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
46403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation on nodesets:
46413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
46423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If both objects to be compared are node-sets, then the comparison
46433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if there is a node in the first node-set
46443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and a node in the second node-set such that the result of performing
46453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the comparison on the string-values of the two nodes is true.
46463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ....
46473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * When neither object to be compared is a node-set and the operator
46483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is <=, <, >= or >, then the objects are compared by converting both
46493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * objects to numbers and comparing the numbers according to IEEE 754.
46503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ....
46513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The number function converts its argument to a number as follows:
46523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - a string that consists of optional whitespace followed by an
46533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    optional minus sign followed by a Number followed by whitespace
46543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    is converted to the IEEE 754 number that is nearest (according
46553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    to the IEEE 754 round-to-nearest rule) to the mathematical value
46563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    represented by the string; any other string is converted to NaN
46573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
46583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Conclusion all nodes need to be converted first to their string value
46593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and then the comparison must be done when possible
46603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
466156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
466256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathCompareNodeSets(int inf, int strict,
46633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
46643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, j, init = 0;
46653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val1;
46663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double *values2;
46673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
46683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns1;
46693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns2;
46703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg1 == NULL) ||
46724dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) {
46734dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
46743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
46754dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
46763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2 == NULL) ||
46774dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) {
46784dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
46794dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
46803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
46814dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
46823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns1 = arg1->nodesetval;
46843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns2 = arg2->nodesetval;
46853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4686d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
46874dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
46884dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
46893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
46904dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
4691d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
46924dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
46934dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
46943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
46954dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
46963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
46983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values2 == NULL) {
4699d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
47004dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
47014dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
47023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
47033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
47043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++) {
4705ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]);
4706cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(val1))
47073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    continue;
47083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++) {
47093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (init == 0) {
4710ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]);
47113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
4712cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	    if (xmlXPathIsNaN(values2[j]))
47133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		continue;
47143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (inf && strict)
47153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 < values2[j]);
47163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (inf && !strict)
47173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 <= values2[j]);
47183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (!inf && strict)
47193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 > values2[j]);
47203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (!inf && !strict)
47213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 >= values2[j]);
47223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ret)
47233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		break;
47243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
47253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret)
47263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
47273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	init = 1;
47283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
47293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values2);
47304dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    xmlXPathFreeObject(arg1);
47314dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    xmlXPathFreeObject(arg2);
47323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
47333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
47363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetValue:
47373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
47383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
47393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
47403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
47413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the value
47423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
47433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a value
47443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
47453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
47463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
47473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
47483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
47493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a boolean,
47503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if the result of performing
47513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the comparison on the boolean and on the result of converting
47523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set to a boolean using the boolean function is true.
47533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
47543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
47553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
475656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
47573473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
47583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr val) {
47593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((val == NULL) || (arg == NULL) ||
47603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
47613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
47623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(val->type) {
47643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
47653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
47663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
47673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_XSLT_TREE:
476856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    return(xmlXPathCompareNodeSets(inf, strict, arg, val));
47693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
47703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
47713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
47723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, arg);
47733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathBooleanFunction(ctxt, 1);
47743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, val);
47753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareValues(ctxt, inf, strict));
47763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
47773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    TODO
47783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
47793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
47803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
478301c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSetString:
47843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the nodeset object argument
47853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the string to compare to.
47860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:  flag to show whether for '=' (0) or '!=' (1)
47873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
47883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
47893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a string,
47903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
47913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
47923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string-value of the node and the other string is true.
47933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
47943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
47953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
479656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
47970c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq)
4798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
47993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
48003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
48013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
4802f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int hash;
48033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((str == NULL) || (arg == NULL) ||
4805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
4806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return (0);
48073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4808c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack    /*
4809c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack     * A NULL nodeset compared with a string is always false
4810c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack     * (since there is no node equal, and no node not equal)
4811c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack     */
4812c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack    if ((ns == NULL) || (ns->nodeNr <= 0) )
4813f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return (0);
4814c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack    hash = xmlXPathStringHash(str);
4815f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < ns->nodeNr; i++) {
4816f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
4817f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            str2 = xmlNodeGetContent(ns->nodeTab[i]);
4818f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((str2 != NULL) && (xmlStrEqual(str, str2))) {
4819f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(str2);
48200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (neq)
48210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    continue;
4822f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (1);
48239adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    } else if ((str2 == NULL) && (xmlStrEqual(str, BAD_CAST ""))) {
48249adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		if (neq)
48259adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    continue;
48269adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard                return (1);
48270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack            } else if (neq) {
48280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (str2 != NULL)
48290c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    xmlFree(str2);
48300c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		return (1);
48310c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
4832f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (str2 != NULL)
4833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(str2);
48340c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        } else if (neq)
48350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    return (1);
48363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4837f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (0);
48383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
48393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
484101c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSetFloat:
48423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the nodeset object argument
48433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the float to compare to
48440c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:  flag to show whether to compare '=' (0) or '!=' (1)
48453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
48463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
48473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a number,
48483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
48493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
48503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number to be compared and on the result of converting the string-value
48513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of that node to a number using the number function is true.
48523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
48533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
48543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
485556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
48560c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
48570c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg, double f, int neq) {
48580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  int i, ret=0;
48590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlNodeSetPtr ns;
48600c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlChar *str2;
48610c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlXPathObjectPtr val;
48620c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  double v;
48633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg == NULL) ||
48653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
48663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
48673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48680c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    ns = arg->nodesetval;
48690c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (ns != NULL) {
48700c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	for (i=0;i<ns->nodeNr;i++) {
48710c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
48720c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (str2 != NULL) {
48730c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		valuePush(ctxt, xmlXPathNewString(str2));
48740c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlFree(str2);
48750c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlXPathNumberFunction(ctxt, 1);
48760c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		val = valuePop(ctxt);
48770c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		v = val->floatval;
48780c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlXPathFreeObject(val);
48790c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (!xmlXPathIsNaN(v)) {
48800c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    if ((!neq) && (v==f)) {
48810c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			ret = 1;
48820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			break;
48830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    } else if ((neq) && (v!=f)) {
48840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			ret = 1;
48850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			break;
48860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    }
488732f0f717d1e7854d87e03b659e772fa48ec9f91aWilliam M. Brack		} else {	/* NaN is unequal to any value */
488832f0f717d1e7854d87e03b659e772fa48ec9f91aWilliam M. Brack		    if (neq)
488932f0f717d1e7854d87e03b659e772fa48ec9f91aWilliam M. Brack			ret = 1;
48900c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		}
48910c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
48920c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
48930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
48940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
48950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return(ret);
48963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
48973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
490001c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSets:
49013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg1:  first nodeset object argument
49023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg2:  second nodeset object argument
49030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:   flag to show whether to test '=' (0) or '!=' (1)
49043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal / not equal operation on XPath nodesets:
49060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @arg1 == @arg2  or  @arg1 != @arg2
49073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If both objects to be compared are node-sets, then the comparison
49083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if there is a node in the first node-set and
49093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * a node in the second node-set such that the result of performing the
49103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * comparison on the string-values of the two nodes is true.
49113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (needless to say, this is a costly operation)
49133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
49143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
49153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
491656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
49170c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) {
49183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, j;
4919f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int *hashs1;
4920f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int *hashs2;
49213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar **values1;
49223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar **values2;
49233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
49243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns1;
49253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns2;
49263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg1 == NULL) ||
49283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)))
49293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
49303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2 == NULL) ||
49313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE)))
49323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
49333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns1 = arg1->nodesetval;
49353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns2 = arg2->nodesetval;
49363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4937911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((ns1 == NULL) || (ns1->nodeNr <= 0))
49383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
4939911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((ns2 == NULL) || (ns2->nodeNr <= 0))
49403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
49413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
49430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     * for equal, check if there is a node pertaining to both sets
49443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
49450c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (neq == 0)
49460c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	for (i = 0;i < ns1->nodeNr;i++)
49470c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    for (j = 0;j < ns2->nodeNr;j++)
49480c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (ns1->nodeTab[i] == ns2->nodeTab[j])
49490c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    return(1);
49503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
4952d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    if (values1 == NULL) {
4953d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
49543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
4955d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    }
4956f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
4957f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (hashs1 == NULL) {
4958d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
4959f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values1);
4960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4961f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
49623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
49633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
49643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values2 == NULL) {
4965d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
4966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(hashs1);
49673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(values1);
49683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
49693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4970f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
4971f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (hashs2 == NULL) {
4972d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
4973f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(hashs1);
4974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values1);
4975f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values2);
4976f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4977f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
49783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *));
49793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++) {
4980f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]);
49813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++) {
49823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (i == 0)
4983f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]);
49840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (hashs1[i] != hashs2[j]) {
49850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (neq) {
49860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
49870c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
49880c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		}
49890c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
49900c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    else {
4991f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (values1[i] == NULL)
4992f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
4993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (values2[j] == NULL)
4994f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
49950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlStrEqual(values1[i], values2[j]) ^ neq;
4996f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (ret)
4997f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    break;
4998f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
49993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
50003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret)
50013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
50023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
50033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++)
50043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (values1[i] != NULL)
50053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(values1[i]);
50063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (j = 0;j < ns2->nodeNr;j++)
50073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (values2[j] != NULL)
50083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(values2[j]);
50093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values1);
50103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values2);
5011f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlFree(hashs1);
5012f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlFree(hashs2);
50133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
50143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
50153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50160c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackstatic int
50170c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
50180c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
50193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
50200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
50210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *At this point we are assured neither arg1 nor arg2
50220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *is a nodeset, so we can just pick the appropriate routine.
50230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
50243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (arg1->type) {
50253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_UNDEFINED:
50263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
50273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
50283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "Equal: undefined\n");
50293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
50303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
50313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
50323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
50333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
50343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
50353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
50363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
50373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
50383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
50393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
50403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
50413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
50423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: %d boolean %d \n",
50433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    arg1->boolval, arg2->boolval);
50443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
50453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == arg2->boolval);
50463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
50473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
5048ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		    ret = (arg1->boolval ==
5049ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack			   xmlXPathCastNumberToBoolean(arg2->floatval));
50503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
50513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
50523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg2->stringval == NULL) ||
50533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg2->stringval[0] == 0)) ret = 0;
50543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
50553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
50563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == ret);
50573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
50583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
50593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
50603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
50613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
50623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
50633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
50640c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
50650c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
50660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
50673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
50683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
50693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
50703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
50713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
50723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
50733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
50743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
50753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
50763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
50773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
5078ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		    ret = (arg2->boolval==
5079ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack			   xmlXPathCastNumberToBoolean(arg1->floatval));
50803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
50813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
50823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    valuePush(ctxt, arg2);
50833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlXPathNumberFunction(ctxt, 1);
50843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    arg2 = valuePop(ctxt);
50853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* no break on purpose */
50863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
5087d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    /* Hand check NaN and Infinity equalities */
5088081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    if (xmlXPathIsNaN(arg1->floatval) ||
5089081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    	    xmlXPathIsNaN(arg2->floatval)) {
509021458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = 0;
5091d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
5092d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		        if (xmlXPathIsInf(arg2->floatval) == 1)
5093d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
5094d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
5095d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
5096d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
5097d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == -1)
5098d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
5099d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
5100d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
5101d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
5102d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == 1)
5103d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
5104d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
5105d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
5106d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
5107d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == -1)
5108d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
5109d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
5110d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
511121458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    } else {
511221458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = (arg1->floatval == arg2->floatval);
511321458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    }
51143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
51153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
51163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
51173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
51183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
51193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
51203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
51210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
51220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
51230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
51243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
51253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
51263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
51273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
51283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
51293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
51303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
51313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
51323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
51333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
51343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
51353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg1->stringval == NULL) ||
51363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg1->stringval[0] == 0)) ret = 0;
51373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
51383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
51393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg2->boolval == ret);
51403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
51413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
51423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlStrEqual(arg1->stringval, arg2->stringval);
51433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
51443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
51453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    valuePush(ctxt, arg1);
51463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlXPathNumberFunction(ctxt, 1);
51473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    arg1 = valuePop(ctxt);
5148d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    /* Hand check NaN and Infinity equalities */
5149081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    if (xmlXPathIsNaN(arg1->floatval) ||
5150081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    	    xmlXPathIsNaN(arg2->floatval)) {
515121458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = 0;
5152d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
5153d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == 1)
5154d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
5155d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
5156d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
5157d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
5158d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == -1)
5159d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
5160d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
5161d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
5162d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
5163d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == 1)
5164d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
5165d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
5166d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
5167d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
5168d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == -1)
5169d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
5170d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
5171d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
517221458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    } else {
517321458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = (arg1->floatval == arg2->floatval);
517421458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    }
51753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
51763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
51773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
51783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
51793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
51803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
51813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
51820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
51830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
51840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
51853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
51863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
51873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_USERS:
51883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
51893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
51903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
51913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    TODO
51923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
51930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	case XPATH_NODESET:
51940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	case XPATH_XSLT_TREE:
51950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    break;
51963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg1);
51983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg2);
51993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
52003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52020c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack/**
52030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * xmlXPathEqualValues:
52040c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @ctxt:  the XPath Parser context
52050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
52060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal operation on XPath objects content: @arg1 == @arg2
52070c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
52080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Returns 0 or 1 depending on the results of the test.
52090c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack */
52100c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackint
52110c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
52120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg1, arg2, argtmp;
52130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    int ret = 0;
52140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
52156128c01ca6a5c1d67970b44cd11aa95a392d8a2dDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
52160c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
52170c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg1 = valuePop(ctxt);
52180c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
52190c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
52200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
52210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
52220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
52230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	XP_ERROR0(XPATH_INVALID_OPERAND);
52240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
52250c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
52260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (arg1 == arg2) {
52270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
52280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        xmlGenericError(xmlGenericErrorContext,
52290c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		"Equal: by pointer\n");
52300c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
52312c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	xmlXPathFreeObject(arg1);
52320c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        return(1);
52330c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
52340c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
52350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
52360c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *If either argument is a nodeset, it's a 'special case'
52370c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
52380c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
52390c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
52400c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	/*
52410c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 *Hack it to assure arg1 is the nodeset
52420c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 */
52430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
52440c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		argtmp = arg2;
52450c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg2 = arg1;
52460c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg1 = argtmp;
52470c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
52480c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	switch (arg2->type) {
52490c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_UNDEFINED:
52500c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
52510c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlGenericError(xmlGenericErrorContext,
52520c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			"Equal: undefined\n");
52530c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
52540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
52550c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NODESET:
52560c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_XSLT_TREE:
52570c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSets(arg1, arg2, 0);
52580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
52590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_BOOLEAN:
52600c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if ((arg1->nodesetval == NULL) ||
52610c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		  (arg1->nodesetval->nodeNr == 0)) ret = 0;
52620c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		else
52630c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
52640c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = (ret == arg2->boolval);
52650c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
52660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NUMBER:
52670c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0);
52680c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
52690c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_STRING:
52700c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0);
52710c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
52720c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_USERS:
52730c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_POINT:
52740c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_RANGE:
52750c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_LOCATIONSET:
52760c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		TODO
52770c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
52780c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
52790c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg1);
52800c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg2);
52810c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	return(ret);
52820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
52830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
52840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return (xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
52850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack}
52860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
52870c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack/**
52880c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * xmlXPathNotEqualValues:
52890c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @ctxt:  the XPath Parser context
52900c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
52910c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal operation on XPath objects content: @arg1 == @arg2
52920c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
52930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Returns 0 or 1 depending on the results of the test.
52940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack */
52950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackint
52960c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
52970c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg1, arg2, argtmp;
52980c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    int ret = 0;
52990c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
53006128c01ca6a5c1d67970b44cd11aa95a392d8a2dDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
53010c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
53020c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg1 = valuePop(ctxt);
53030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
53040c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
53050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
53060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
53070c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
53080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	XP_ERROR0(XPATH_INVALID_OPERAND);
53090c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
53100c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
53110c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (arg1 == arg2) {
53120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
53130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        xmlGenericError(xmlGenericErrorContext,
53140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		"NotEqual: by pointer\n");
53150c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
53162c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	xmlXPathFreeObject(arg1);
53170c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        return(0);
53180c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
53190c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
53200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
53210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *If either argument is a nodeset, it's a 'special case'
53220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
53230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
53240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
53250c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	/*
53260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 *Hack it to assure arg1 is the nodeset
53270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 */
53280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
53290c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		argtmp = arg2;
53300c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg2 = arg1;
53310c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg1 = argtmp;
53320c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
53330c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	switch (arg2->type) {
53340c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_UNDEFINED:
53350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
53360c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlGenericError(xmlGenericErrorContext,
53370c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			"NotEqual: undefined\n");
53380c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
53390c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
53400c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NODESET:
53410c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_XSLT_TREE:
53420c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSets(arg1, arg2, 1);
53430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
53440c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_BOOLEAN:
53450c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if ((arg1->nodesetval == NULL) ||
53460c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		  (arg1->nodesetval->nodeNr == 0)) ret = 0;
53470c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		else
53480c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
5349ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		ret = (ret != arg2->boolval);
53500c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
53510c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NUMBER:
53520c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1);
53530c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
53540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_STRING:
53550c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1);
53560c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
53570c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_USERS:
53580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_POINT:
53590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_RANGE:
53600c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_LOCATIONSET:
53610c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		TODO
53620c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
53630c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
53640c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg1);
53650c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg2);
53660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	return(ret);
53670c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
53680c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
53690c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
53700c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack}
53713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
53733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareValues:
53743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
53753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
53763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
53773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation on XPath objects:
53793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 < @arg2    (1, 1, ...
53803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 <= @arg2   (1, 0, ...
53813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 > @arg2    (0, 1, ...
53823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 >= @arg2   (0, 0, ...
53833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * When neither object to be compared is a node-set and the operator is
53853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * <=, <, >=, >, then the objects are compared by converted both objects
53863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to numbers and comparing the numbers according to IEEE 754. The <
53873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * comparison will be true if and only if the first number is less than the
53883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * second number. The <= comparison will be true if and only if the first
53893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number is less than or equal to the second number. The > comparison
53903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if the first number is greater than the second
53913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number. The >= comparison will be true if and only if the first number
53923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is greater than or equal to the second number.
53933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5394cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if the comparison succeeded, 0 if it failed
53953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
53973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
5398d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard    int ret = 0, arg1i = 0, arg2i = 0;
53993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg1, arg2;
54003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54016128c01ca6a5c1d67970b44cd11aa95a392d8a2dDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
54020c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
54033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    arg1 = valuePop(ctxt);
54040c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
54050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
54060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
54070c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
54080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
54093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
54103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
54130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
5414d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	/*
5415d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	 * If either argument is a XPATH_NODESET or XPATH_XSLT_TREE the two arguments
5416d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	 * are not freed from within this routine; they will be freed from the
5417d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	 * called routine, e.g. xmlXPathCompareNodeSets or xmlXPathCompareNodeSetValue
5418d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	 */
54190c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) &&
54200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	  ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){
542156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    ret = xmlXPathCompareNodeSets(inf, strict, arg1, arg2);
54223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
54230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
54244af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard		ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
54254af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard			                          arg1, arg2);
54263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else {
54274af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard		ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict,
54284af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard			                          arg2, arg1);
54293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
54303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
54313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(ret);
54323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1->type != XPATH_NUMBER) {
54353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, arg1);
54363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathNumberFunction(ctxt, 1);
54373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	arg1 = valuePop(ctxt);
54383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1->type != XPATH_NUMBER) {
54403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
54413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
54423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
54433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2->type != XPATH_NUMBER) {
54453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, arg2);
54463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathNumberFunction(ctxt, 1);
54473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	arg2 = valuePop(ctxt);
54483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2->type != XPATH_NUMBER) {
54503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
54513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
54523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
54533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
54553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Add tests for infinity and nan
54563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * => feedback on 3.4 for Inf and NaN
54573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
5458d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard    /* Hand check NaN and Infinity comparisons */
545921458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
5460d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	ret=0;
546121458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    } else {
5462d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	arg1i=xmlXPathIsInf(arg1->floatval);
5463d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	arg2i=xmlXPathIsInf(arg2->floatval);
5464d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	if (inf && strict) {
5465d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if ((arg1i == -1 && arg2i != -1) ||
5466d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		(arg2i == 1 && arg1i != 1)) {
5467d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
5468d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
5469d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval < arg2->floatval);
5470d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
5471d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
5472d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
5473d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
5474d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (inf && !strict) {
5475d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if (arg1i == -1 || arg2i == 1) {
5476d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
5477d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
5478d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval <= arg2->floatval);
5479d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
5480d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
5481d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
5482d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
5483d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (!inf && strict) {
5484d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if ((arg1i == 1 && arg2i != 1) ||
5485d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		(arg2i == -1 && arg1i != -1)) {
5486d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
5487d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
5488d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval > arg2->floatval);
5489d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
5490d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
5491d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
5492d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
5493d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (!inf && !strict) {
5494d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if (arg1i == 1 || arg2i == -1) {
5495d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
5496d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
5497d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval >= arg2->floatval);
5498d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
5499d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
5500d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
5501d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
550221458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    }
55033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg1);
55043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg2);
55053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
55063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathValueFlipSign:
55103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the unary - operation on an XPath object
55133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
55143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
55153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
55173473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
5518a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return;
5519ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5520ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5521eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (xmlXPathIsNaN(ctxt->value->floatval))
5522eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathNAN;
5523eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (xmlXPathIsInf(ctxt->value->floatval) == 1)
5524eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathNINF;
5525eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (xmlXPathIsInf(ctxt->value->floatval) == -1)
5526eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathPINF;
5527eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (ctxt->value->floatval == 0) {
55285fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard        if (xmlXPathGetSign(ctxt->value->floatval) == 0)
55295fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNZERO;
55305fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else
55315fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = 0;
55325fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
55335fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else
55345fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard        ctxt->value->floatval = - ctxt->value->floatval;
55353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathAddValues:
55393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the add operation on XPath objects:
55423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
55433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
55443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
55463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
55473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
55483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
55493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5550ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5551ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5552ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5553ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
55543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
55553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5556ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5557ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5558ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval += val;
55593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubValues:
55633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5565cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Implement the subtraction operation on XPath objects:
55663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
55673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
55683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
55703473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
55713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
55723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
55733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5574ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5575ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5576ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5577ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
55783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
55793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5580ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5581ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5582ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval -= val;
55833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathMultValues:
55873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the multiply operation on XPath objects:
55903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
55913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
55923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
55943473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
55953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
55963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
55973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5598ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5599ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5600ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5601ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
56023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
56033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5604ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5605ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5606ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval *= val;
56073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
56083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
56103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathDivValues:
56113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
56123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the div operation on XPath objects @arg1 / @arg2:
56143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
56153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
56163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
56173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
56183473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
56193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
56203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
56213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5622ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5623ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5624ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5625ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
56263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
56273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5628ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5629ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5630eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (xmlXPathIsNaN(val) || xmlXPathIsNaN(ctxt->value->floatval))
5631eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard	ctxt->value->floatval = xmlXPathNAN;
5632eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (val == 0 && xmlXPathGetSign(val) != 0) {
56335fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (ctxt->value->floatval == 0)
56345fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNAN;
56355fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else if (ctxt->value->floatval > 0)
56365fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNINF;
56375fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else if (ctxt->value->floatval < 0)
56385fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathPINF;
56395fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
56405fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else if (val == 0) {
56415f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	if (ctxt->value->floatval == 0)
56425f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathNAN;
56435f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	else if (ctxt->value->floatval > 0)
56445f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathPINF;
56455f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	else if (ctxt->value->floatval < 0)
56465f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathNINF;
56475f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard    } else
56485f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	ctxt->value->floatval /= val;
56493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
56503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
56523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathModValues:
56533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
56543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the mod operation on XPath objects: @arg1 / @arg2
56563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
56573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
56583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
56593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
56603473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathModValues(xmlXPathParserContextPtr ctxt) {
56613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
5662fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    double arg1, arg2;
56633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5664ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5665ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5666ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
56675fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    arg2 = xmlXPathCastToNumber(arg);
56683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
56693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5670ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5671ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
56725fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    arg1 = ctxt->value->floatval;
5673268fd1bc97f79b43290041cfda2287fb0b0ef2d6Daniel Veillard    if (arg2 == 0)
5674268fd1bc97f79b43290041cfda2287fb0b0ef2d6Daniel Veillard	ctxt->value->floatval = xmlXPathNAN;
56755fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else {
5676fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	ctxt->value->floatval = fmod(arg1, arg2);
56775fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
56783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
56793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
56813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
56823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		The traversal functions					*
56833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
56843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
56853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
56873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A traversal function enumerates nodes along an axis.
56883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initially it must be called with NULL, and it indicates
56893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * termination on the axis by returning NULL.
56903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
56913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylortypedef xmlNodePtr (*xmlXPathTraversalFunction)
56923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    (xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
56933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
56953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextSelf:
56963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
56973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
56983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "self" direction
57003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The self axis contains just the context node itself
57013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
57033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57043473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
57053473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5706a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
57073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
57083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
57093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
57103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextChild:
57143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
57163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "child" direction
57183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The child axis contains the children of the context node in document order.
57193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
57213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57223473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
57233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5724a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
57253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
57263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
57273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
57283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
57293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
57303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
57313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
57323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
57333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
57343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
57353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
57363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DTD_NODE:
57373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->children);
57383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
57393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
57403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
57413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5742eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5743eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
57443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
57453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(((xmlDocPtr) ctxt->context->node)->children);
57463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
57473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
57483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
57493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE:
57503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_NAMESPACE_DECL:
57513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
57523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
57533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
57543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
57553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
57563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
57573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur->type == XML_DOCUMENT_NODE) ||
57583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        (cur->type == XML_HTML_DOCUMENT_NODE))
57593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
57603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->next);
57613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextDescendant:
57653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
57673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "descendant" direction
57693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the descendant axis contains the descendants of the context node in document
57703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * order; a descendant is a child or a child of a child and so on.
57713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
57733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
57753473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5776a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
57773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
57783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL)
57793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
57803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
57813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
57823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
57833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
57853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(ctxt->context->doc->children);
57863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->children);
57873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
57883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5789567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    if (cur->children != NULL) {
579068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	/*
579168e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	 * Do not descend on entities declarations
579268e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	 */
579368e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    	if (cur->children->type != XML_ENTITY_DECL) {
579468e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    cur = cur->children;
579568e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    /*
579668e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	     * Skip DTDs
579768e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	     */
579868e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    if (cur->type != XML_DTD_NODE)
579968e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard		return(cur);
580068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	}
5801567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    }
5802567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard
5803567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    if (cur == ctxt->context->node) return(NULL);
5804567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard
580568e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    while (cur->next != NULL) {
580668e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	cur = cur->next;
580768e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	if ((cur->type != XML_ENTITY_DECL) &&
580868e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    (cur->type != XML_DTD_NODE))
580968e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    return(cur);
581068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    }
58113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
58133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
581411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard	if (cur == NULL) break;
58153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == ctxt->context->node) return(NULL);
58163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->next != NULL) {
58173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur = cur->next;
58183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(cur);
58193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
58203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (cur != NULL);
58213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur);
58223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
58233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
58253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextDescendantOrSelf:
58263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
58273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
58283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "descendant-or-self" direction
58303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the descendant-or-self axis contains the context node and the descendants
58313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node in document order; thus the context node is the first
58323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node on the axis, and the first child of the context node is the second node
58333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * on the axis
58343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
58363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
58373473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
58383473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5839a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
58403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
58413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL)
58423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
58433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
58443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
58453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
58463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
58473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
58483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathNextDescendant(ctxt, cur));
58503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
58513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
58533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextParent:
58543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
58553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
58563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "parent" direction
58583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The parent axis contains the parent of the context node, if there is one.
58593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
58613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
58623473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
58633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5864a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
58653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
58663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * the parent of an attribute or namespace node is the element
58673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * to which the attribute or namespace node is attached
58683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Namespace handling !!!
58693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
58703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
58713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
58723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
58733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
58743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
58753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
58763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
58773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
58783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
58793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
58803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
58813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DTD_NODE:
58823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
58833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
58843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
58853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
58863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
58873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (ctxt->context->node->parent == NULL)
58883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return((xmlNodePtr) ctxt->context->doc);
58898e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
5890652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    ((ctxt->context->node->parent->name[0] == ' ') ||
5891652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		     (xmlStrEqual(ctxt->context->node->parent->name,
5892652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard				 BAD_CAST "fake node libxslt"))))
58938e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		    return(NULL);
58943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->parent);
58953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE: {
58963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
58973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(att->parent);
58993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
59003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
59013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
59023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
59033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5904eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5905eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
59063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
59073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5908044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    case XML_NAMESPACE_DECL: {
5909044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5910044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
5911044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns->next != NULL) &&
5912044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (ns->next->type != XML_NAMESPACE_DECL))
5913044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return((xmlNodePtr) ns->next);
59143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5915044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
59163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
59173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
59183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
59193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
59203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
59223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAncestor:
59233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
59243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
59253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "ancestor" direction
59273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the ancestor axis contains the ancestors of the context node; the ancestors
59283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node consist of the parent of context node and the parent's
59293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent and so on; the nodes are ordered in reverse document order; thus the
59303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent is the first node on the axis, and the parent's parent is the second
59313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node on the axis
59323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
59343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
59353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
59363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5937a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
59383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
59393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * the parent of an attribute or namespace node is the element
59403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * to which the attribute or namespace node is attached
59413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * !!!!!!!!!!!!!
59423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
59433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
59443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
59453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
59463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
59473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
59483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
59493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
59503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
59513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
59523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
59533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_DTD_NODE:
59543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
59553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
59563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
59573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
59583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
59593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
59603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (ctxt->context->node->parent == NULL)
59613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return((xmlNodePtr) ctxt->context->doc);
59628e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
5963652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    ((ctxt->context->node->parent->name[0] == ' ') ||
5964652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		     (xmlStrEqual(ctxt->context->node->parent->name,
5965652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard				 BAD_CAST "fake node libxslt"))))
59668e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		    return(NULL);
59673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->parent);
59683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE: {
596956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard		xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node;
59703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
597156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard		return(tmp->parent);
59723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
59733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
59743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
59753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
59763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5977eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5978eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
59793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
59803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5981044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    case XML_NAMESPACE_DECL: {
5982044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5983044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
5984044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns->next != NULL) &&
5985044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (ns->next->type != XML_NAMESPACE_DECL))
5986044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return((xmlNodePtr) ns->next);
5987081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		/* Bad, how did that namespace end up here ? */
59883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5989044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
59903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
59913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
59923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
59933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == ctxt->context->doc->children)
59943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return((xmlNodePtr) ctxt->context->doc);
59953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
59963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
59973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (cur->type) {
59983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
59993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_TEXT_NODE:
60003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_CDATA_SECTION_NODE:
60013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ENTITY_REF_NODE:
60023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ENTITY_NODE:
60033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_PI_NODE:
60043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_COMMENT_NODE:
60053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_NOTATION_NODE:
60063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DTD_NODE:
60073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ELEMENT_DECL:
60083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ATTRIBUTE_DECL:
60093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ENTITY_DECL:
60103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_XINCLUDE_START:
60113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_XINCLUDE_END:
60128e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard	    if (cur->parent == NULL)
60138e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		return(NULL);
60148e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard	    if ((cur->parent->type == XML_ELEMENT_NODE) &&
6015652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		((cur->parent->name[0] == ' ') ||
6016652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		 (xmlStrEqual(cur->parent->name,
6017652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard			      BAD_CAST "fake node libxslt"))))
60188e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		return(NULL);
60193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(cur->parent);
60203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE: {
60213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
60223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(att->parent);
60243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
6025dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	case XML_NAMESPACE_DECL: {
6026dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
6027dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin
6028dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    if ((ns->next != NULL) &&
6029dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	        (ns->next->type != XML_NAMESPACE_DECL))
6030dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	        return((xmlNodePtr) ns->next);
6031081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    /* Bad, how did that namespace end up here ? */
6032dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin            return(NULL);
6033dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	}
60343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_NODE:
60353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_TYPE_NODE:
60363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_FRAG_NODE:
60373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_HTML_DOCUMENT_NODE:
6038eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
6039eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	case XML_DOCB_DOCUMENT_NODE:
60403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
60413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
60423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
60443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
60473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAncestorOrSelf:
60483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
60493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
60503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "ancestor-or-self" direction
60523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * he ancestor-or-self axis contains the context node and ancestors of
60533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node in reverse document order; thus the context node is
60543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the first node on the axis, and the context node's parent the second;
60553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent here is defined the same as with the parent axis.
60563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
60583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
60593473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
60603473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6061a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
60623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
60633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
60643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathNextAncestor(ctxt, cur));
60653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
60683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextFollowingSibling:
60693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
60703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
60713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "following-sibling" direction
60733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The following-sibling axis contains the following siblings of the context
60743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node in document order.
60753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
60773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
60783473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
60793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6080a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
60813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
60823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->context->node->type == XML_NAMESPACE_DECL))
60833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
60843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
60853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
60863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
60873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->next);
60883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->next);
60893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
60923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextPrecedingSibling:
60933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
60943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
60953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "preceding-sibling" direction
60973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The preceding-sibling axis contains the preceding siblings of the context
60983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node in reverse document order; the first preceding sibling is first on the
60993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * axis; the sibling preceding that node is the second on the axis and so on.
61003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
61023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
61033473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
61043473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6105a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
61063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
61073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->context->node->type == XML_NAMESPACE_DECL))
61083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
61093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
61103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
61113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
61123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->prev);
6113f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
6114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
6115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (cur == NULL)
6116f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(ctxt->context->node->prev);
6117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
61183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->prev);
61193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
61203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
61223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextFollowing:
61233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
61243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
61253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "following" direction
61273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The following axis contains all nodes in the same document as the context
61283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node that are after the context node in document order, excluding any
61293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * descendants and excluding attribute nodes and namespace nodes; the nodes
61303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * are ordered in document order
61313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
61333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
61343473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
61353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6136a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
61373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur != NULL && cur->children != NULL)
61383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return cur->children ;
61393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) cur = ctxt->context->node;
61403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return(NULL) ; /* ERROR */
61413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->next != NULL) return(cur->next) ;
61423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
61433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
614411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard        if (cur == NULL) break;
61453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
61463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->next != NULL) return(cur->next);
61473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (cur != NULL);
61483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur);
61493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
61503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
61523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsAncestor:
61533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ancestor:  the ancestor node
61543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node:  the current node
61553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Check that @ancestor is a @node's ancestor
61573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
61593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
61603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int
61613473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
61623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ancestor == NULL) || (node == NULL)) return(0);
61633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* nodes need to be in the same document */
61643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ancestor->doc != node->doc) return(0);
61653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* avoid searching if ancestor or node is the root node */
61663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ancestor == (xmlNodePtr) node->doc) return(1);
61673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node == (xmlNodePtr) ancestor->doc) return(0);
61683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (node->parent != NULL) {
61693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (node->parent == ancestor)
61703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            return(1);
61713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node = node->parent;
61723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
61733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
61743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
61753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
61773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextPreceding:
61783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
61793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
61803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "preceding" direction
61823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the preceding axis contains all nodes in the same document as the context
61833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node that are before the context node in document order, excluding any
61843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ancestors and excluding attribute nodes and namespace nodes; the nodes are
61853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ordered in reverse document order
61863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
61883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
61893473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
6190f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
6191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
6192a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (cur == NULL)
6194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = ctxt->context->node;
61953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
6196f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return (NULL);
6197f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
6198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
61993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
62003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->prev != NULL) {
6201f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
6202f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (cur);
62033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
62043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
6206f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
6207f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
6208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == ctxt->context->doc->children)
6209f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
62103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (xmlXPathIsAncestor(cur, ctxt->context->node));
6211f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (cur);
6212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
6213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
6214f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
6215f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNextPrecedingInternal:
6216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath Parser context
6217f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @cur:  the current node in the traversal
6218f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
6219f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Traversal function for the "preceding" direction
6220f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * the preceding axis contains all nodes in the same document as the context
6221f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * node that are before the context node in document order, excluding any
6222f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * ancestors and excluding attribute nodes and namespace nodes; the nodes are
6223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * ordered in reverse document order
6224f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * This is a faster implementation but internal only since it requires a
6225f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * state kept in the parser context: ctxt->ancestor.
6226f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
6227f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the next element following that axis
6228f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
6229f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic xmlNodePtr
6230f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
6231f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlNodePtr cur)
6232f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
6233a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6234f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (cur == NULL) {
6235f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = ctxt->context->node;
6236f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
6237f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
623840c22b472b3d24ecc2f5b843aa3fffad6ed5cf5eWilliam M. Brack	if (cur->type == XML_NAMESPACE_DECL)
623940c22b472b3d24ecc2f5b843aa3fffad6ed5cf5eWilliam M. Brack	    cur = (xmlNodePtr)((xmlNsPtr)cur)->next;
6240f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->ancestor = cur->parent;
6241f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
6242f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
6243f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
6244f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (cur->prev == NULL) {
6245f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = cur->parent;
6246f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
6247f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
6248f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == ctxt->context->doc->children)
6249f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
6250f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur != ctxt->ancestor)
6251f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (cur);
6252f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->ancestor = cur->parent;
6253f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
6254f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    cur = cur->prev;
6255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (cur->last != NULL)
6256f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = cur->last;
6257f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (cur);
62583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
62593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
62613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextNamespace:
62623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
62633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current attribute in the traversal
62643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
62653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "namespace" direction
62663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the namespace axis contains the namespace nodes of the context node;
62673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the order of nodes on this axis is implementation-defined; the axis will
62683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * be empty unless the context node is an element
62693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
627020ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard * We keep the XML namespace node at the end of the list.
627120ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard *
62723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
62733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
62743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
62753473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6276a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
62773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
6278fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) {
62797d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard        if (ctxt->context->tmpNsList != NULL)
62807d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	    xmlFree(ctxt->context->tmpNsList);
62817d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsList =
62823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGetNsList(ctxt->context->doc, ctxt->context->node);
62837d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsNr = 0;
6284fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	if (ctxt->context->tmpNsList != NULL) {
6285fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
6286fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		ctxt->context->tmpNsNr++;
6287fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    }
6288fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	}
6289fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return((xmlNodePtr) xmlXPathXMLNamespace);
62907d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    }
6291fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    if (ctxt->context->tmpNsNr > 0) {
6292fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return (xmlNodePtr)ctxt->context->tmpNsList[--ctxt->context->tmpNsNr];
6293fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    } else {
6294fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	if (ctxt->context->tmpNsList != NULL)
6295fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlFree(ctxt->context->tmpNsList);
62967d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsList = NULL;
6297fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return(NULL);
62983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
62993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
63023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAttribute:
63033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current attribute in the traversal
63053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "attribute" direction
63073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * TODO: support DTD inherited default attributes
63083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
63103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
63113473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
63123473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6313a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6314e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard    if (ctxt->context->node == NULL)
6315e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard	return(NULL);
6316e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard    if (ctxt->context->node->type != XML_ELEMENT_NODE)
6317e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard	return(NULL);
63183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
63193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
63203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
63213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return((xmlNodePtr)ctxt->context->node->properties);
63223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((xmlNodePtr)cur->next);
63243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
63273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
63283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		NodeTest Functions					*
63293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
63303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
63313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_FUNCTION			200
63333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6334d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
6335d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/************************************************************************
6336d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
6337d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *		Implicit tree core function library			*
6338d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
6339d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard ************************************************************************/
6340d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
63413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
6342d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathRoot:
63433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
6345d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Initialize the context to the root of the document
63463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
6347d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
6348d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathRoot(xmlXPathParserContextPtr ctxt) {
6349a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return;
6350d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
6351d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
6352d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
63533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6354d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/************************************************************************
6355d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
6356d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *		The explicit core function library			*
6357d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib	*
6358d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
6359d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard ************************************************************************/
63603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6361d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
6362d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
6363d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathLastFunction:
6364d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
6365d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @nargs:  the number of arguments
6366d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
6367d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Implement the last() XPath function
6368d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *    number last()
6369d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * The last function returns the number of nodes in the context node list.
6370d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
6371d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
6372d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6373d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    CHECK_ARITY(0);
6374d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ctxt->context->contextSize >= 0) {
6375d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) ctxt->context->contextSize));
6376d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_EXPR
6377d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlGenericError(xmlGenericErrorContext,
6378d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		"last() : %d\n", ctxt->context->contextSize);
63793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
6380d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    } else {
6381d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	XP_ERROR(XPATH_INVALID_CTXT_SIZE);
63823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6383d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
63843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6385d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
6386d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathPositionFunction:
6387d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
6388d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @nargs:  the number of arguments
6389d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
6390d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Implement the position() XPath function
6391d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *    number position()
6392d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * The position function returns the position of the context node in the
6393cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * context node list. The first position is 1, and so the last position
6394d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * will be equal to last().
6395d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
6396d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
6397d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6398d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    CHECK_ARITY(0);
6399d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ctxt->context->proximityPosition >= 0) {
6400d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	valuePush(ctxt,
6401d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	      xmlXPathNewFloat((double) ctxt->context->proximityPosition));
6402d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_EXPR
6403d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "position() : %d\n",
6404d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		ctxt->context->proximityPosition);
64053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
6406d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    } else {
6407d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	XP_ERROR(XPATH_INVALID_CTXT_POSITION);
6408d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
6409d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
64103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
64123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCountFunction:
64133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
64143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
64153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
64163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the count() XPath function
64173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number count(node-set)
64183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
64193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
64203473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
64213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
64223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
64243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
64253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
64263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
64273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
64283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
64293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6430911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur == NULL) || (cur->nodesetval == NULL))
6431911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) 0));
64320c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    else if ((cur->type == XPATH_NODESET) || (cur->type == XPATH_XSLT_TREE)) {
6433911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) cur->nodesetval->nodeNr));
6434fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    } else {
6435fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	if ((cur->nodesetval->nodeNr != 1) ||
6436fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    (cur->nodesetval->nodeTab == NULL)) {
6437fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    valuePush(ctxt, xmlXPathNewFloat((double) 0));
6438fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	} else {
6439fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    xmlNodePtr tmp;
6440fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    int i = 0;
6441fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard
6442fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    tmp = cur->nodesetval->nodeTab[0];
6443fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    if (tmp != NULL) {
6444fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		tmp = tmp->children;
6445fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		while (tmp != NULL) {
6446fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		    tmp = tmp->next;
6447fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		    i++;
6448fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		}
6449fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    }
6450fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    valuePush(ctxt, xmlXPathNewFloat((double) i));
6451fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	}
6452fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    }
64533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
64543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
64553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
6457ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathGetElementsByIds:
6458ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @doc:  the document
6459ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ids:  a whitespace separated list of IDs
6460ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
6461ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Selects elements by their unique ID.
6462ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
6463ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a node-set of selected elements.
6464ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
6465ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardstatic xmlNodeSetPtr
6466ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
6467ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodeSetPtr ret;
6468ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    const xmlChar *cur = ids;
6469ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ID;
6470ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlAttrPtr attr;
6471ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodePtr elem = NULL;
6472ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
64737a985a18c2fee0aa9b490792dd990b75506e3740Daniel Veillard    if (ids == NULL) return(NULL);
64747a985a18c2fee0aa9b490792dd990b75506e3740Daniel Veillard
6475ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNodeSetCreate(NULL);
6476ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
647776e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*cur)) cur++;
6478ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    while (*cur != 0) {
647976e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((!IS_BLANK_CH(*cur)) && (*cur != 0))
6480e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	    cur++;
6481ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
6482ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        ID = xmlStrndup(ids, cur - ids);
6483e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	if (ID != NULL) {
648468cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	    /*
648568cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * We used to check the fact that the value passed
648668cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * was an NCName, but this generated much troubles for
648768cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * me and Aleksey Sanin, people blatantly violated that
648868cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * constaint, like Visa3D spec.
648968cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * if (xmlValidateNCName(ID, 1) == 0)
649068cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     */
649168cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	    attr = xmlGetID(doc, ID);
649268cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	    if (attr != NULL) {
649368cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		if (attr->type == XML_ATTRIBUTE_NODE)
649468cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		    elem = attr->parent;
649568cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		else if (attr->type == XML_ELEMENT_NODE)
649668cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		    elem = (xmlNodePtr) attr;
649768cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		else
649868cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		    elem = NULL;
649968cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		if (elem != NULL)
650068cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		    xmlXPathNodeSetAdd(ret, elem);
6501e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	    }
6502ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlFree(ID);
6503e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	}
6504ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
650576e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while (IS_BLANK_CH(*cur)) cur++;
6506ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ids = cur;
6507ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
6508ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
6509ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
6510ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
6511ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
65123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIdFunction:
65133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the id() XPath function
65173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    node-set id(object)
65183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The id function selects elements by their unique ID
65193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set,
65203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the result is the union of the result of applying id to the
65213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string value of each of the nodes in the argument node-set. When the
65223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument to id is of any other type, the argument is converted to a
65233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string as if by a call to the string function; the string is split
65243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * into a whitespace-separated list of tokens (whitespace is any sequence
65253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of characters matching the production S); the result is a node-set
65263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * containing the elements in the same document as the context node that
65273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * have a unique ID equal to any of the tokens in the list.
65283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65303473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6531ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *tokens;
6532ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodeSetPtr ret;
6533ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr obj;
65343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
65363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    obj = valuePop(ctxt);
65373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
65380c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
6539ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlNodeSetPtr ns;
65403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i;
65413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6542ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNodeSetCreate(NULL);
65433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6544911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	if (obj->nodesetval != NULL) {
6545911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
6546ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		tokens =
6547ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		    xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
6548ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
6549ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		ret = xmlXPathNodeSetMerge(ret, ns);
6550ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		xmlXPathFreeNodeSet(ns);
6551ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		if (tokens != NULL)
6552ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		    xmlFree(tokens);
6553911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    }
65543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
65553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(obj);
6557ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt, xmlXPathWrapNodeSet(ret));
65583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
65593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6560ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    obj = xmlXPathConvertString(obj);
65613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6562ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval);
6563ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
65643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(obj);
65663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return;
65673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
65683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathLocalNameFunction:
65713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the local-name() XPath function
65753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string local-name(node-set?)
65763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The local-name function returns a string containing the local part
65773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the name of the node in the argument node-set that is first in
65783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * document order. If the node-set is empty or the first node has no
65793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * name, an empty string is returned. If the argument is omitted it
65803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
65813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65833473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
65853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6586a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
6587a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
65883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
65893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
65903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs = 1;
65913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
65923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
65943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
65953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
65963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
65973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
65983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
65993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6600911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
66013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
66023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
66033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i = 0; /* Should be first in document order !!!!! */
66043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (cur->nodesetval->nodeTab[i]->type) {
66053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
66063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE:
66073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_PI_NODE:
6608652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	    if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
6609652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		valuePush(ctxt, xmlXPathNewCString(""));
6610652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	    else
6611652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		valuePush(ctxt,
66123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		      xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
66133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
66143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_NAMESPACE_DECL:
66153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewString(
66163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
66173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
66183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
66193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewCString(""));
66203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
66213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
66233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNamespaceURIFunction:
66273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
66283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
66293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
66303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the namespace-uri() XPath function
66313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string namespace-uri(node-set?)
66323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The namespace-uri function returns a string containing the
66333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace URI of the expanded name of the node in the argument
66343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node-set that is first in document order. If the node-set is empty,
66353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the first node has no name, or the expanded name has no namespace
66363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * URI, an empty string is returned. If the argument is omitted it
66373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
66383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
66393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
66403473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
66413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
66423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6643a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
6644a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
66453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
66463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
66473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs = 1;
66483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
66503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
66513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
66523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
66533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
66543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
66553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6656911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
66573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
66583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
66593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i = 0; /* Should be first in document order !!!!! */
66603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (cur->nodesetval->nodeTab[i]->type) {
66613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
66623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE:
66633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (cur->nodesetval->nodeTab[i]->ns == NULL)
66643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		valuePush(ctxt, xmlXPathNewCString(""));
66653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else
66663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		valuePush(ctxt, xmlXPathNewString(
66673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			  cur->nodesetval->nodeTab[i]->ns->href));
66683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
66693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
66703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewCString(""));
66713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
66723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
66743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNameFunction:
66783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
66793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
66803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
66813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the name() XPath function
66823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string name(node-set?)
66833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The name function returns a string containing a QName representing
6684cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * the name of the node in the argument node-set that is first in document
66853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * order. The QName must represent the name with respect to the namespace
66863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * declarations in effect on the node whose name is being represented.
66873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Typically, this will be the form in which the name occurred in the XML
66883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * source. This need not be the case if there are namespace declarations
66893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in effect on the node that associate multiple prefixes with the same
66903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace. However, an implementation may include information about
66913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the original prefix in its representation of nodes; in this case, an
66923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * implementation can ensure that the returned string is always the same
66933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * as the QName used in the XML source. If the argument it omitted it
66943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
66953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Libxml keep the original prefix so the "real qualified name" used is
66963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returned.
66973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
669856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
66990438375d2e6be47d0179826271081ae64df94f8bDaniel VeillardxmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
67000438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard{
67013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
67023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
67040438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
67050438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        nargs = 1;
67063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
67073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
67090438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard    if ((ctxt->value == NULL) ||
67100438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        ((ctxt->value->type != XPATH_NODESET) &&
67110438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard         (ctxt->value->type != XPATH_XSLT_TREE)))
67120438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        XP_ERROR(XPATH_INVALID_TYPE);
67133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
67143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6715911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
67160438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        valuePush(ctxt, xmlXPathNewCString(""));
67173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
67180438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        int i = 0;              /* Should be first in document order !!!!! */
67193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67200438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        switch (cur->nodesetval->nodeTab[i]->type) {
67210438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            case XML_ELEMENT_NODE:
67220438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            case XML_ATTRIBUTE_NODE:
6723652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
6724652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    valuePush(ctxt, xmlXPathNewCString(""));
6725652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
6726652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard                         (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
67270438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    valuePush(ctxt,
6728c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		        xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
67290438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard
6730652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		} else {
6731c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    xmlChar *fullname;
6732c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard
6733c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name,
6734c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard				     cur->nodesetval->nodeTab[i]->ns->prefix,
6735c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard				     NULL, 0);
6736c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    if (fullname == cur->nodesetval->nodeTab[i]->name)
6737c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard			fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
6738c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    if (fullname == NULL) {
6739c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard			XP_ERROR(XPATH_MEMORY_ERROR);
6740c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    }
6741c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard                    valuePush(ctxt, xmlXPathWrapString(fullname));
67420438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                }
67430438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                break;
67440438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            default:
67450438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                valuePush(ctxt,
67460438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                          xmlXPathNewNodeSet(cur->nodesetval->nodeTab[i]));
67470438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                xmlXPathLocalNameFunction(ctxt, 1);
67480438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        }
67493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
67503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
67513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
67523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6753fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
6754fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
67553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringFunction:
67563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
67573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
67583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
67593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the string() XPath function
67603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string string(object?)
6761081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * The string function converts an object to a string as follows:
67623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - A node-set is converted to a string by returning the value of
67633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      the node in the node-set that is first in document order.
67643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      If the node-set is empty, an empty string is returned.
67653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - A number is converted to a string as follows
67663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + NaN is converted to the string NaN
67673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + positive zero is converted to the string 0
67683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + negative zero is converted to the string 0
67693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + positive infinity is converted to the string Infinity
67703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + negative infinity is converted to the string -Infinity
67713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + if the number is an integer, the number is represented in
67723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        decimal form as a Number with no decimal point and no leading
67733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        zeros, preceded by a minus sign (-) if the number is negative
67743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + otherwise, the number is represented in decimal form as a
67753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        Number including a decimal point with at least one digit
67763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        before the decimal point and at least one digit after the
67773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        decimal point, preceded by a minus sign (-) if the number
67783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        is negative; there must be no leading zeros before the decimal
6779cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *        point apart possibly from the one required digit immediately
67803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        before the decimal point; beyond the one required digit
67813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        after the decimal point there must be as many, but only as
67823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        many, more digits as are needed to uniquely distinguish the
67833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        number from all other IEEE 754 numeric values.
67843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - The boolean false value is converted to the string false.
67853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      The boolean true value is converted to the string true.
67863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
67873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If the argument is omitted, it defaults to a node-set with the
67883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * context node as its only member.
67893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
67903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
67913473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
67923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
67933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6794a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
67953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
6796ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt,
6797ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		  xmlXPathWrapString(
6798ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard			xmlXPathCastNodeToString(ctxt->context->node)));
6799ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return;
68003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
68013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
68033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
68043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
6805fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertString(cur);
6806fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
68073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringLengthFunction:
68113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the string-length() XPath function
68153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number string-length(string?)
68163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The string-length returns the number of characters in the string
68173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (see [3.6 Strings]). If the argument is omitted, it defaults to
68183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node converted to a string, in other words the value
68193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node.
68203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
68223473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
68233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
68243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
6826a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard        if ((ctxt == NULL) || (ctxt->context == NULL))
6827a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard	    return;
68283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) {
68293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(0));
68303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
68313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlChar *content;
68323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6833ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    content = xmlXPathCastNodeToString(ctxt->context->node);
6834e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard	    valuePush(ctxt, xmlXPathNewFloat(xmlUTF8Strlen(content)));
68353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(content);
68363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
68373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
68383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
68393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
68403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
68413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
68423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
6843e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    valuePush(ctxt, xmlXPathNewFloat(xmlUTF8Strlen(cur->stringval)));
68443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
68453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathConcatFunction:
68493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the concat() XPath function
68533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string concat(string, string, string*)
68543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The concat function returns the concatenation of its arguments.
68553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
68573473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
68583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur, newobj;
68593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *tmp;
68603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6861a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
68623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs < 2) {
68633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(2);
68643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
68653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
68673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
68683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur == NULL) || (cur->type != XPATH_STRING)) {
68693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(cur);
68703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
68713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
68723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    nargs--;
68733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (nargs > 0) {
68753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CAST_TO_STRING;
68763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	newobj = valuePop(ctxt);
68773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((newobj == NULL) || (newobj->type != XPATH_STRING)) {
68783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(newobj);
68793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(cur);
68803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_INVALID_TYPE);
68813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
68823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	tmp = xmlStrcat(newobj->stringval, cur->stringval);
68833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	newobj->stringval = cur->stringval;
68843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->stringval = tmp;
68853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(newobj);
68873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs--;
68883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
68893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, cur);
68903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathContainsFunction:
68943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the contains() XPath function
68983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean contains(string, string)
68993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The contains function returns true if the first argument string
69003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * contains the second argument string, and otherwise returns false.
69013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
69033473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
69043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr hay, needle;
69053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(2);
69073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
69083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
69093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    needle = valuePop(ctxt);
69103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
69113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    hay = valuePop(ctxt);
69123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((hay == NULL) || (hay->type != XPATH_STRING)) {
69133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(hay);
69143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(needle);
69153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
69163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
69173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrstr(hay->stringval, needle->stringval))
69183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(1));
69193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
69203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(0));
69213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(hay);
69223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(needle);
69233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
69243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
69263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStartsWithFunction:
69273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
69293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the starts-with() XPath function
69313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean starts-with(string, string)
69323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The starts-with function returns true if the first argument string
69333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * starts with the second argument string, and otherwise returns false.
69343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
69363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
69373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr hay, needle;
69383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int n;
69393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(2);
69413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
69423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
69433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    needle = valuePop(ctxt);
69443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
69453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    hay = valuePop(ctxt);
69463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((hay == NULL) || (hay->type != XPATH_STRING)) {
69473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(hay);
69483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(needle);
69493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
69503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
69513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = xmlStrlen(needle->stringval);
69523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrncmp(hay->stringval, needle->stringval, n))
69533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(0));
69543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
69553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(1));
69563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(hay);
69573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(needle);
69583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
69593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
69613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringFunction:
69623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
69643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring() XPath function
69663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring(string, number, number?)
69673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring function returns the substring of the first argument
69683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * starting at the position specified in the second argument with
69693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * length specified in the third argument. For example,
69703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * substring("12345",2,3) returns "234". If the third argument is not
69713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * specified, it returns the substring starting at the position specified
69723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in the second argument and continuing to the end of the string. For
69733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * example, substring("12345",2) returns "2345".  More precisely, each
69743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character in the string (see [3.6 Strings]) is considered to have a
69753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * numeric position: the position of the first character is 1, the position
69763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the second character is 2 and so on. The returned substring contains
69773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * those characters for which the position of the character is greater than
69783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * or equal to the second argument and, if the third argument is specified,
69793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * less than the sum of the second and third arguments; the comparisons
69803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and addition used for the above follow the standard IEEE 754 rules. Thus:
69813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 1.5, 2.6) returns "234"
69823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 0, 3) returns "12"
69833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 0 div 0, 3) returns ""
69843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 1, 0 div 0) returns ""
69853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", -42, 1 div 0) returns "12345"
69863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", -1 div 0, 1 div 0) returns ""
69873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
69893473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
69903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr str, start, len;
699197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    double le=0, in;
699297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    int i, l, m;
69933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret;
69943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs < 2) {
69963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(2);
69973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
69983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs > 3) {
69993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(3);
70003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
700197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    /*
700297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     * take care of possible last (position) argument
700397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    */
70043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 3) {
70053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CAST_TO_NUMBER;
70063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_TYPE(XPATH_NUMBER);
70073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len = valuePop(ctxt);
70083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	le = len->floatval;
70093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(len);
70103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
701197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
70123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
70133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
70143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    start = valuePop(ctxt);
70153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    in = start->floatval;
70163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(start);
70173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
70183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
70193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    str = valuePop(ctxt);
702097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    m = xmlUTF8Strlen((const unsigned char *)str->stringval);
702197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
702297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    /*
702397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     * If last pos not present, calculate last position
702497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    */
70259e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    if (nargs != 3) {
70269e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	le = (double)m;
70279e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	if (in < 1.0)
70289e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    in = 1.0;
70299e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    }
703097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
70310eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    /* Need to check for the special cases where either
70320eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard     * the index is NaN, the length is NaN, or both
70330eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard     * arguments are infinity (relying on Inf + -Inf = NaN)
703497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     */
70359e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    if (!xmlXPathIsNaN(in + le) && !xmlXPathIsInf(in)) {
70360eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        /*
70379e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard         * To meet the requirements of the spec, the arguments
70389e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * must be converted to integer format before
70399e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * initial index calculations are done
70400eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard         *
70419e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard         * First we go to integer form, rounding up
70429e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * and checking for special cases
70430eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard         */
70440eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        i = (int) in;
70459e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (((double)i)+0.5 <= in) i++;
70469e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard
70479e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	if (xmlXPathIsInf(le) == 1) {
70489e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = m;
70499e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    if (i < 1)
70509e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard		i = 1;
70519e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	}
70529e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	else if (xmlXPathIsInf(le) == -1 || le < 0.0)
70539e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = 0;
70549e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	else {
70559e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = (int) le;
70569e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    if (((double)l)+0.5 <= le) l++;
70579e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	}
70580eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard
70599e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	/* Now we normalize inidices */
70609e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        i -= 1;
70619e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        l += i;
70629e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (i < 0)
70639e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard            i = 0;
70649e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (l > m)
70659e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard            l = m;
70663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70670eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        /* number of chars to copy */
70680eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        l -= i;
70693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70700eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        ret = xmlUTF8Strsub(str->stringval, i, l);
70710eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    }
70720eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    else {
70730eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        ret = NULL;
70740eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    }
70753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL)
70773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
70783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
70793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewString(ret));
70803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(ret);
70813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
708297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
70833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(str);
70843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
70853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
70873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringBeforeFunction:
70883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
70893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
70903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
70913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring-before() XPath function
70923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring-before(string, string)
70933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring-before function returns the substring of the first
70943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string that precedes the first occurrence of the second
70953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string in the first argument string, or the empty string
70963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if the first argument string does not contain the second argument
70973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, substring-before("1999/04/01","/") returns 1999.
70983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
70993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
71003473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
71013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr str;
71023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr find;
71033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
71043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  const xmlChar *point;
71053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  int offset;
71063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(2);
71083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
71093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  find = valuePop(ctxt);
71103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
71113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  str = valuePop(ctxt);
71123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
71143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target) {
71153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    point = xmlStrstr(str->stringval, find->stringval);
71163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (point) {
71173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      offset = (int)(point - str->stringval);
71183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      xmlBufferAdd(target, str->stringval, offset);
71193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
71203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
71213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
71223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
71233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(str);
71253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(find);
71263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
71273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
71293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringAfterFunction:
71303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
71313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
71323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring-after() XPath function
71343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring-after(string, string)
71353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring-after function returns the substring of the first
71363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string that follows the first occurrence of the second
71373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string in the first argument string, or the empty stringi
71383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if the first argument string does not contain the second argument
71393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, substring-after("1999/04/01","/") returns 04/01,
71403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and substring-after("1999/04/01","19") returns 99/04/01.
71413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
71423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
71433473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
71443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr str;
71453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr find;
71463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
71473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  const xmlChar *point;
71483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  int offset;
71493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(2);
71513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
71523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  find = valuePop(ctxt);
71533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
71543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  str = valuePop(ctxt);
71553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
71573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target) {
71583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    point = xmlStrstr(str->stringval, find->stringval);
71593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (point) {
71603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
71613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      xmlBufferAdd(target, &str->stringval[offset],
71623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   xmlStrlen(str->stringval) - offset);
71633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
71643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
71653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
71663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
71673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(str);
71693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(find);
71703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
71713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
71733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNormalizeFunction:
71743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
71753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
71763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the normalize-space() XPath function
71783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string normalize-space(string?)
71793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The normalize-space function returns the argument string with white
71803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * space normalized by stripping leading and trailing whitespace
71813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and replacing sequences of whitespace characters by a single
71823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * space. Whitespace characters are the same allowed by the S production
71833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in XML. If the argument is omitted, it defaults to the context
71843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node converted to a string, in other words the value of the context node.
71853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
71863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
71873473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
71883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr obj = NULL;
71893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlChar *source = NULL;
71903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
71913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlChar blank;
71923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7193a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard  if (ctxt == NULL) return;
71943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (nargs == 0) {
71953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Use current context node */
7196ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    valuePush(ctxt,
7197ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	      xmlXPathWrapString(
7198ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		  xmlXPathCastNodeToString(ctxt->context->node)));
71993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    nargs = 1;
72003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
72013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(1);
72033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
72043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_TYPE(XPATH_STRING);
72053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  obj = valuePop(ctxt);
72063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  source = obj->stringval;
72073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
72093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target && source) {
72103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Skip leading whitespaces */
721276e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*source))
72133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      source++;
72143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Collapse intermediate whitespaces, and skip trailing whitespaces */
72163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    blank = 0;
72173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (*source) {
721876e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack      if (IS_BLANK_CH(*source)) {
721997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	blank = 0x20;
72203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      } else {
72213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (blank) {
72223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	  xmlBufferAdd(target, &blank, 1);
72233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	  blank = 0;
72243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
72253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlBufferAdd(target, source, 1);
72263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      }
72273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      source++;
72283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
72293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
72313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
72323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
72333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(obj);
72343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
72353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
72373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathTranslateFunction:
72383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
72393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
72403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the translate() XPath function
72423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string translate(string, string, string)
72433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The translate function returns the first argument string with
72443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * occurrences of characters in the second argument string replaced
72453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by the character at the corresponding position in the third argument
72463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, translate("bar","abc","ABC") returns the string
72473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * BAr. If there is a character in the second argument string with no
72483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character at a corresponding position in the third argument string
72493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (because the second argument string is longer than the third argument
72503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string), then occurrences of that character in the first argument
72513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string are removed. For example, translate("--aaa--","abc-","ABC")
72523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns "AAA". If a character occurs more than once in second
72533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string, then the first occurrence determines the replacement
72543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character. If the third argument string is longer than the second
72553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string, then excess characters are ignored.
72563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
72573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
72583473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7259e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr str;
7260e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr from;
7261e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr to;
7262e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlBufferPtr target;
726397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    int offset, max;
7264e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlChar ch;
7265b031cef5b537d8eda30f508627f08bc642bbd31dWilliam M. Brack    const xmlChar *point;
726697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    xmlChar *cptr;
72673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7268e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CHECK_ARITY(3);
72693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7270e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
7271e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    to = valuePop(ctxt);
7272e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
7273e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    from = valuePop(ctxt);
7274e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
7275e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    str = valuePop(ctxt);
72763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7277e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    target = xmlBufferCreate();
7278e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    if (target) {
727997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	max = xmlUTF8Strlen(to->stringval);
728097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	for (cptr = str->stringval; (ch=*cptr); ) {
728197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    offset = xmlUTF8Strloc(from->stringval, cptr);
728297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    if (offset >= 0) {
728397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if (offset < max) {
728497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    point = xmlUTF8Strpos(to->stringval, offset);
728597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    if (point)
728697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1));
728797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		}
728897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    } else
728997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
729097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
729197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    /* Step to next character in input */
729297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    cptr++;
729397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    if ( ch & 0x80 ) {
729497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		/* if not simple ascii, verify proper format */
729597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if ( (ch & 0xc0) != 0xc0 ) {
729697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    xmlGenericError(xmlGenericErrorContext,
729797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			"xmlXPathTranslateFunction: Invalid UTF8 string\n");
729897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    break;
729997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		}
730097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		/* then skip over remaining bytes for this char */
730197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		while ( (ch <<= 1) & 0x80 )
730297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    if ( (*cptr++ & 0xc0) != 0x80 ) {
730397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			xmlGenericError(xmlGenericErrorContext,
730497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			    "xmlXPathTranslateFunction: Invalid UTF8 string\n");
730597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			break;
730697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    }
730797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if (ch & 0x80) /* must have had error encountered */
730897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    break;
730997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    }
7310e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard	}
73113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7312e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
7313e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlBufferFree(target);
7314e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(str);
7315e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(from);
7316e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(to);
73173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7320fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathBooleanFunction:
7321fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath Parser context
7322fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @nargs:  the number of arguments
7323fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7324fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Implement the boolean() XPath function
7325fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    boolean boolean(object)
7326081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * The boolean function converts its argument to a boolean as follows:
7327fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a number is true if and only if it is neither positive or
7328fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *      negative zero nor NaN
7329fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a node-set is true if and only if it is non-empty
7330fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a string is true if and only if its length is non-zero
7331fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
7332fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardvoid
7333fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7334fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    xmlXPathObjectPtr cur;
7335fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
7336fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    CHECK_ARITY(1);
7337fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = valuePop(ctxt);
7338fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
7339fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertBoolean(cur);
7340fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
73413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
73443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNotFunction:
73453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
73463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
73473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the not() XPath function
73493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean not(boolean)
73503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The not function returns true if its argument is false,
73513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and false otherwise.
73523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
73533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
73543473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
73553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
73563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_BOOLEAN;
73573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_BOOLEAN);
73583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->value->boolval = ! ctxt->value->boolval;
73593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
73623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathTrueFunction:
73633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
73643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
73653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the true() XPath function
73673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean true()
73683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
73693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
73703473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
73713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(0);
73723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(1));
73733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
73763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFalseFunction:
73773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
73783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
73793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the false() XPath function
73813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean false()
73823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
73833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
73843473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
73853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(0);
73863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(0));
73873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
73903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathLangFunction:
73913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
73923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
73933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the lang() XPath function
73953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean lang(string)
73963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The lang function returns true or false depending on whether the
73973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * language of the context node as specified by xml:lang attributes
73983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is the same as or is a sublanguage of the language specified by
73993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the argument string. The language of the context node is determined
74003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by the value of the xml:lang attribute on the context node, or, if
74013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node has no xml:lang attribute, by the value of the
74023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xml:lang attribute on the nearest ancestor of the context node that
74033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * has an xml:lang attribute. If there is no such attribute, then lang
74043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns false. If there is such an attribute, then lang returns
74053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * true if the attribute value is equal to the argument ignoring case,
74063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * or if there is some suffix starting with - such that the attribute
74073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * value is equal to the argument ignoring that suffix of the attribute
74083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * value and ignoring case.
74093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
74103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
74113473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
74124ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard    xmlXPathObjectPtr val = NULL;
74134ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard    const xmlChar *theLang = NULL;
74143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *lang;
74153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
74163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
74173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
74193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
74203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
74213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    val = valuePop(ctxt);
74223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    lang = val->stringval;
74233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    theLang = xmlNodeGetLang(ctxt->context->node);
74243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((theLang != NULL) && (lang != NULL)) {
74253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        for (i = 0;lang[i] != 0;i++)
74263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (toupper(lang[i]) != toupper(theLang[i]))
74273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        goto not_equal;
74284ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard	if ((theLang[i] == 0) || (theLang[i] == '-'))
74294ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard	    ret = 1;
74303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylornot_equal:
74324ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard    if (theLang != NULL)
74334ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard	xmlFree((void *)theLang);
74343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(val);
74353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(ret));
74363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
74373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
74393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNumberFunction:
74403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
74413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
74423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the number() XPath function
74443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number number(object?)
74453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
74463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
74473473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
74483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
74493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double res;
74503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7451a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
74523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
74533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) {
74543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(0.0));
74553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
74563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlChar* content = xmlNodeGetContent(ctxt->context->node);
74573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res = xmlXPathStringEvalNumber(content);
74593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(res));
74603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(content);
74613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
74623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
74633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
74663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
7467fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertNumber(cur);
7468fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
74693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
74703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
74723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSumFunction:
74733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
74743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
74753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the sum() XPath function
74773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number sum(node-set)
74783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The sum function returns the sum of the values of the nodes in
74793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the argument node-set.
74803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
74813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
74823473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
74833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
74843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
7485ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double res = 0.0;
74863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
74883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
74893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
74903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
74913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
74923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
74933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7494081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
7495ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	for (i = 0; i < cur->nodesetval->nodeNr; i++) {
7496ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]);
74973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
74983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7499081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    valuePush(ctxt, xmlXPathNewFloat(res));
75003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
75013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
75023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75033d426663629a53180f3f54282ba27f3d070eef24William M. Brack/*
75043d426663629a53180f3f54282ba27f3d070eef24William M. Brack * To assure working code on multiple platforms, we want to only depend
75053d426663629a53180f3f54282ba27f3d070eef24William M. Brack * upon the characteristic truncation of converting a floating point value
75063d426663629a53180f3f54282ba27f3d070eef24William M. Brack * to an integer.  Unfortunately, because of the different storage sizes
75073d426663629a53180f3f54282ba27f3d070eef24William M. Brack * of our internal floating point value (double) and integer (int), we
75083d426663629a53180f3f54282ba27f3d070eef24William M. Brack * can't directly convert (see bug 301162).  This macro is a messy
75093d426663629a53180f3f54282ba27f3d070eef24William M. Brack * 'workaround'
75103d426663629a53180f3f54282ba27f3d070eef24William M. Brack */
75113d426663629a53180f3f54282ba27f3d070eef24William M. Brack#define XTRUNC(f, v)            \
75123d426663629a53180f3f54282ba27f3d070eef24William M. Brack    f = fmod((v), INT_MAX);     \
75133d426663629a53180f3f54282ba27f3d070eef24William M. Brack    f = (v) - (f) + (double)((int)(f));
75143d426663629a53180f3f54282ba27f3d070eef24William M. Brack
75153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
75163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFloorFunction:
75173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
75183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
75193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the floor() XPath function
75213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number floor(number)
75223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The floor function returns the largest (closest to positive infinity)
75233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number that is not greater than the argument and that is an integer.
75243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
75253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
75263473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
752756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    double f;
752856cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard
75293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
75303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
75313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
753256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard
75333d426663629a53180f3f54282ba27f3d070eef24William M. Brack    XTRUNC(f, ctxt->value->floatval);
753456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (f != ctxt->value->floatval) {
753556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval > 0)
753656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
753756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
753856cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f - 1;
753956cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
75403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
75413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
75433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCeilingFunction:
75443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
75453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
75463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the ceiling() XPath function
75483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number ceiling(number)
75493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The ceiling function returns the smallest (closest to negative infinity)
75503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number that is not less than the argument and that is an integer.
75513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
75523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
75533473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
75543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double f;
75553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
75573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
75583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
75593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if 0
75613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->value->floatval = ceil(ctxt->value->floatval);
75623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else
75633d426663629a53180f3f54282ba27f3d070eef24William M. Brack    XTRUNC(f, ctxt->value->floatval);
756456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (f != ctxt->value->floatval) {
756556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval > 0)
756656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f + 1;
75675fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else {
75685fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    if (ctxt->value->floatval < 0 && f == 0)
75695fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	        ctxt->value->floatval = xmlXPathNZERO;
75705fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    else
75715fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	        ctxt->value->floatval = f;
75725fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	}
75735fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
757456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
75753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
75763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
75773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
75793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRoundFunction:
75803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
75813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
75823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the round() XPath function
75843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number round(number)
75853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The round function returns the number that is closest to the
75863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument and that is an integer. If there are two such numbers,
75873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the one that is even is returned.
75883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
75893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
75903473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
75913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double f;
75923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
75943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
75953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
75963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7597cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    if ((xmlXPathIsNaN(ctxt->value->floatval)) ||
7598cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	(xmlXPathIsInf(ctxt->value->floatval) == 1) ||
7599cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	(xmlXPathIsInf(ctxt->value->floatval) == -1) ||
76003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->value->floatval == 0.0))
76013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
76023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76033d426663629a53180f3f54282ba27f3d070eef24William M. Brack    XTRUNC(f, ctxt->value->floatval);
760456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (ctxt->value->floatval < 0) {
760556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval < f - 0.5)
760656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f - 1;
760756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
760856cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
76095fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (ctxt->value->floatval == 0)
76105fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNZERO;
761156cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    } else {
761256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval < f + 0.5)
761356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
761456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
761556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f + 1;
761656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
76173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
76183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
76203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
76213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			The Parser					*
76223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
76233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
76243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
7626081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * a few forward declarations since we use a recursive call based
76273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * implementation.
76283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7629afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt);
7630d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardstatic void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
7631afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
7632afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt);
76332156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillardstatic xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,
76342156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	                                  int qualified);
76353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
763761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * xmlXPathCurrentChar:
763861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @ctxt:  the XPath parser context
763961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @cur:  pointer to the beginning of the char
764061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @len:  pointer to the length of the char read
764161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard *
7642cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * The current char value, if using UTF-8 this may actually span multiple
764361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * bytes in the input buffer.
764461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard *
764560087f30f3b4cf21de48f39181736e7d71e7a661Daniel Veillard * Returns the current char value and its length
764661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard */
764761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
764861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardstatic int
764961d80a2822b2678dee885ac2850295cc96277c63Daniel VeillardxmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
765061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    unsigned char c;
765161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    unsigned int val;
765261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    const xmlChar *cur;
765361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
765461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (ctxt == NULL)
765561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(0);
765661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    cur = ctxt->cur;
765761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
765861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
765961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * We are supposed to handle UTF8, check it's valid
766061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * From rfc2044: encoding of the Unicode values on UTF-8:
766161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     *
766261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
766361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0000-0000 007F   0xxxxxxx
766461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
766561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
766661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     *
766761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Check for the 0x110000 limit too
766861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
766961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    c = *cur;
767061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (c & 0x80) {
767161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if ((cur[1] & 0xc0) != 0x80)
767261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    goto encoding_error;
767361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if ((c & 0xe0) == 0xe0) {
767461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
767561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if ((cur[2] & 0xc0) != 0x80)
767661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		goto encoding_error;
767761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if ((c & 0xf0) == 0xf0) {
767861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		if (((c & 0xf8) != 0xf0) ||
767961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    ((cur[3] & 0xc0) != 0x80))
768061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    goto encoding_error;
768161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		/* 4-byte code */
768261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		*len = 4;
768361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val = (cur[0] & 0x7) << 18;
768461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[1] & 0x3f) << 12;
768561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[2] & 0x3f) << 6;
768661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= cur[3] & 0x3f;
768761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    } else {
768861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	      /* 3-byte code */
768961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		*len = 3;
769061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val = (cur[0] & 0xf) << 12;
769161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[1] & 0x3f) << 6;
769261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= cur[2] & 0x3f;
769361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
769461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	} else {
769561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	  /* 2-byte code */
769661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    *len = 2;
769761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    val = (cur[0] & 0x1f) << 6;
769861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    val |= cur[1] & 0x3f;
769961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
770061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if (!IS_CHAR(val)) {
770161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    XP_ERROR0(XPATH_INVALID_CHAR_ERROR);
770261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
770361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(val);
770461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    } else {
770561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	/* 1-byte code */
770661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	*len = 1;
770761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return((int) *cur);
770861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
770961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardencoding_error:
771061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
7711081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * If we detect an UTF8 error that probably means that the
7712081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * input encoding didn't get properly advertised in the
771361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * declaration header. Report the error and switch the encoding
771461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * to ISO-Latin-1 (if you don't like this policy, just declare the
771561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * encoding !)
771661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
771742596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard    *len = 0;
771861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    XP_ERROR0(XPATH_ENCODING_ERROR);
771961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
772061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
772161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard/**
77223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseNCName:
77233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
77243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML namespace non qualified name.
77263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
77283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
77303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                       CombiningChar | Extender
77313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the namespace name or NULL
77333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
77343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
77363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
77372156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    const xmlChar *in;
77382156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    xmlChar *ret;
77392156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    int count = 0;
77403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7741a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
77422156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    /*
77432156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard     * Accelerator for simple ASCII names
77442156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard     */
77452156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    in = ctxt->cur;
77462156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    if (((*in >= 0x61) && (*in <= 0x7A)) ||
77472156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	((*in >= 0x41) && (*in <= 0x5A)) ||
77482156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	(*in == '_')) {
77492156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	in++;
77502156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	while (((*in >= 0x61) && (*in <= 0x7A)) ||
77512156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	       ((*in >= 0x41) && (*in <= 0x5A)) ||
77522156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	       ((*in >= 0x30) && (*in <= 0x39)) ||
77539a89a8ab80bc021deec9da7d79bda20995c4e78dDaniel Veillard	       (*in == '_') || (*in == '.') ||
77549a89a8ab80bc021deec9da7d79bda20995c4e78dDaniel Veillard	       (*in == '-'))
77552156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    in++;
77562156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	if ((*in == ' ') || (*in == '>') || (*in == '/') ||
77572156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard            (*in == '[') || (*in == ']') || (*in == ':') ||
77582156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard            (*in == '@') || (*in == '*')) {
77592156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    count = in - ctxt->cur;
77602156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (count == 0)
77612156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		return(NULL);
77622156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    ret = xmlStrndup(ctxt->cur, count);
77632156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    ctxt->cur = in;
77642156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    return(ret);
77652156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	}
77662156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    }
77672156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    return(xmlXPathParseNameComplex(ctxt, 0));
77683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
77693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77702156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard
77713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
77723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseQName:
77733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
77743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  a xmlChar **
77753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML qualified name
77773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 5] QName ::= (Prefix ':')? LocalPart
77793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 6] Prefix ::= NCName
77813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 7] LocalPart ::= NCName
77833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the function returns the local part, and prefix is updated
77853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   to get the Prefix if any.
77863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
77873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
778856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
77893473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
77903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret = NULL;
77913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *prefix = NULL;
77933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = xmlXPathParseNCName(ctxt);
77943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == ':') {
77953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        *prefix = ret;
77963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
77973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = xmlXPathParseNCName(ctxt);
77983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
78003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
78013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
78033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseName:
78043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
78053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML name
78073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
78093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  CombiningChar | Extender
78103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] Name ::= (Letter | '_' | ':') (NameChar)*
78123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the namespace name or NULL
78143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
78153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78163473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
78173473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseName(xmlXPathParserContextPtr ctxt) {
781861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    const xmlChar *in;
781961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    xmlChar *ret;
782061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int count = 0;
78213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7822a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
782361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
782461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Accelerator for simple ASCII names
782561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
782661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    in = ctxt->cur;
782761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (((*in >= 0x61) && (*in <= 0x7A)) ||
782861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	((*in >= 0x41) && (*in <= 0x5A)) ||
782961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	(*in == '_') || (*in == ':')) {
783061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	in++;
783161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	while (((*in >= 0x61) && (*in <= 0x7A)) ||
783261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	       ((*in >= 0x41) && (*in <= 0x5A)) ||
783361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	       ((*in >= 0x30) && (*in <= 0x39)) ||
783476d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	       (*in == '_') || (*in == '-') ||
783576d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	       (*in == ':') || (*in == '.'))
783661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    in++;
783776d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	if ((*in > 0) && (*in < 0x80)) {
783861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    count = in - ctxt->cur;
783961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    ret = xmlStrndup(ctxt->cur, count);
784061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    ctxt->cur = in;
784161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    return(ret);
784261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
784361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
78442156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    return(xmlXPathParseNameComplex(ctxt, 1));
784561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
78463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
784761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardstatic xmlChar *
78482156a56bcbf5d83fb3d694123be01beebf84d273Daniel VeillardxmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
784961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    xmlChar buf[XML_MAX_NAMELEN + 5];
785061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int len = 0, l;
785161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int c;
78523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
785361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
785461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Handler for more complex cases
785561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
785661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    c = CUR_CHAR(l);
785761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
78582156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard        (c == '[') || (c == ']') || (c == '@') || /* accelerators */
78592156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard        (c == '*') || /* accelerators */
786061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	(!IS_LETTER(c) && (c != '_') &&
78612156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard         ((qualified) && (c != ':')))) {
786261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(NULL);
786361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
78643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
786561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
786661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
786761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard            (c == '.') || (c == '-') ||
78682156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    (c == '_') || ((qualified) && (c == ':')) ||
786961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    (IS_COMBINING(c)) ||
787061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    (IS_EXTENDER(c)))) {
787161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	COPY_BUF(l,buf,len,c);
787261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	NEXTL(l);
787361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	c = CUR_CHAR(l);
787461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if (len >= XML_MAX_NAMELEN) {
787561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    /*
787661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     * Okay someone managed to make a huge name, so he's ready to pay
787761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     * for the processing speed.
787861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     */
787961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    xmlChar *buffer;
788061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    int max = len * 2;
788161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
78823c908dca479ed50dca24b8593bca90e40dbde6b8Daniel Veillard	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
788361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if (buffer == NULL) {
788424505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard		XP_ERRORNULL(XPATH_MEMORY_ERROR);
788561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
788661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    memcpy(buffer, buf, len);
788761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
788861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (c == '.') || (c == '-') ||
78892156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		   (c == '_') || ((qualified) && (c == ':')) ||
789061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (IS_COMBINING(c)) ||
789161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (IS_EXTENDER(c))) {
789261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		if (len + 10 > max) {
789361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    max *= 2;
789461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    buffer = (xmlChar *) xmlRealloc(buffer,
789561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard			                            max * sizeof(xmlChar));
789661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    if (buffer == NULL) {
789724505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard			XP_ERRORNULL(XPATH_MEMORY_ERROR);
789861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    }
789961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		}
790061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		COPY_BUF(l,buffer,len,c);
790161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		NEXTL(l);
790261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		c = CUR_CHAR(l);
790361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
790461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    buffer[len] = 0;
790561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    return(buffer);
790661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
790761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
79082156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    if (len == 0)
79092156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	return(NULL);
791061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    return(xmlStrndup(buf, len));
791161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
79123cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
79133cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard#define MAX_FRAC 20
79143cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
7915372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack/*
7916372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack * These are used as divisors for the fractional part of a number.
7917372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack * Since the table includes 1.0 (representing '0' fractional digits),
7918372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack * it must be dimensioned at MAX_FRAC+1 (bug 133921)
7919372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack */
7920372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brackstatic double my_pow10[MAX_FRAC+1] = {
79213cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1.0, 10.0, 100.0, 1000.0, 10000.0,
79223cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0,
79233cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,
79243cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    100000000000000.0,
79253cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1000000000000000.0, 10000000000000000.0, 100000000000000000.0,
7926372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack    1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0
79273cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard};
79283cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
79293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
79303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringEvalNumber:
79313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  A string to scan
79323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
793370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese *  [30a]  Float  ::= Number ('e' Digits?)?
793470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese *
79353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [30]   Number ::=   Digits ('.' Digits?)?
79363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | '.' Digits
79373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [31]   Digits ::=   [0-9]+
79383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7939afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Number in the string
79403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * In complement of the Number expression, this function also handles
79413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * negative values : '-' Number.
79423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the double value.
79443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
79453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble
79463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringEvalNumber(const xmlChar *str) {
79473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *cur = str;
79487b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double ret;
7949b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    int ok = 0;
79503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int isneg = 0;
795170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int exponent = 0;
795270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int is_exponent_negative = 0;
7953b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#ifdef __GNUC__
7954b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    unsigned long tmp = 0;
79557b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double temp;
7956b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#endif
7957eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (cur == NULL) return(0);
795876e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*cur)) cur++;
79593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) {
79603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(xmlXPathNAN);
79613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
79623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == '-') {
79633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	isneg = 1;
79643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur++;
79653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7966b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard
7967b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#ifdef __GNUC__
7968d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard    /*
79697b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * tmp/temp is a workaround against a gcc compiler bug
79707b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * http://veillard.com/gcc.bug
7971d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard     */
79727b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
79733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((*cur >= '0') && (*cur <= '9')) {
79747b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10;
79757b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	tmp = (*cur - '0');
79763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ok = 1;
79773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur++;
79787b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	temp = (double) tmp;
79797b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret + temp;
79803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7981b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#else
79827b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
7983b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    while ((*cur >= '0') && (*cur <= '9')) {
7984b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	ret = ret * 10 + (*cur - '0');
7985b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	ok = 1;
7986b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	cur++;
7987b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    }
7988b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#endif
7989d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard
79903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == '.') {
79913cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	int v, frac = 0;
79923cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	double fraction = 0;
79933cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
79943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur++;
79953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (((*cur < '0') || (*cur > '9')) && (!ok)) {
79963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathNAN);
79973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
79983cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	while (((*cur >= '0') && (*cur <= '9')) && (frac < MAX_FRAC)) {
79993cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    v = (*cur - '0');
80003cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    fraction = fraction * 10 + v;
80013cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    frac = frac + 1;
80023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur++;
80033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
80043cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	fraction /= my_pow10[frac];
80053cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	ret = ret + fraction;
80063cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	while ((*cur >= '0') && (*cur <= '9'))
80073cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    cur++;
80083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
800970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if ((*cur == 'e') || (*cur == 'E')) {
801070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      cur++;
801170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      if (*cur == '-') {
801270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	is_exponent_negative = 1;
801370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	cur++;
80149912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack      } else if (*cur == '+') {
80159912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack        cur++;
801670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      }
801770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      while ((*cur >= '0') && (*cur <= '9')) {
801870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	exponent = exponent * 10 + (*cur - '0');
801970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	cur++;
802070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      }
802170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    }
802276e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*cur)) cur++;
80233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur != 0) return(xmlXPathNAN);
80243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (isneg) ret = -ret;
802570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if (is_exponent_negative) exponent = -exponent;
802670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    ret *= pow(10.0, (double)exponent);
80273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
80283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
80293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8031afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompNumber:
80323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
80333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [30]   Number ::=   Digits ('.' Digits?)?
80353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | '.' Digits
80363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [31]   Digits ::=   [0-9]+
80373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8038afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Number, then push it on the stack
80393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8041afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8042d79bcd1b36412a7996ace1900ab613e38a609b60Daniel VeillardxmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
8043d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard{
80443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double ret = 0.0;
80453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double mult = 1;
80467b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    int ok = 0;
804770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int exponent = 0;
804870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int is_exponent_negative = 0;
80497b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#ifdef __GNUC__
80507b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    unsigned long tmp = 0;
80517b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double temp;
80527b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#endif
80533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
80553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
80563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        XP_ERROR(XPATH_NUMBER_ERROR);
80573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80587b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#ifdef __GNUC__
8059d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard    /*
80607b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * tmp/temp is a workaround against a gcc compiler bug
80617b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * http://veillard.com/gcc.bug
8062d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard     */
80637b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
80643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR >= '0') && (CUR <= '9')) {
80657b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10;
80667b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	tmp = (CUR - '0');
8067d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        ok = 1;
8068d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        NEXT;
80697b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	temp = (double) tmp;
80707b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret + temp;
80713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80727b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#else
80737b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
80747b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    while ((CUR >= '0') && (CUR <= '9')) {
80757b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10 + (CUR - '0');
80767b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ok = 1;
80777b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	NEXT;
80787b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    }
80797b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#endif
80803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '.') {
80813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
8082d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (((CUR < '0') || (CUR > '9')) && (!ok)) {
8083d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            XP_ERROR(XPATH_NUMBER_ERROR);
8084d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
8085d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        while ((CUR >= '0') && (CUR <= '9')) {
8086d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            mult /= 10;
8087d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            ret = ret + (CUR - '0') * mult;
8088d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
8089d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
80903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
809170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if ((CUR == 'e') || (CUR == 'E')) {
8092d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        NEXT;
8093d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (CUR == '-') {
8094d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            is_exponent_negative = 1;
8095d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
80969912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack        } else if (CUR == '+') {
80979912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack	    NEXT;
80989912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack	}
8099d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        while ((CUR >= '0') && (CUR <= '9')) {
8100d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            exponent = exponent * 10 + (CUR - '0');
8101d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
8102d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
8103d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (is_exponent_negative)
8104d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            exponent = -exponent;
8105d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        ret *= pow(10.0, (double) exponent);
810670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    }
81079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0,
8108d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard                   xmlXPathNewFloat(ret), NULL);
81093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
81103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8112fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathParseLiteral:
8113fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath Parser context
8114fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
8115fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Parse a Literal
8116fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
8117fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *  [29]   Literal ::=   '"' [^"]* '"'
8118fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *                    | "'" [^']* "'"
8119fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
8120fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Returns the value found or NULL in case of error
8121fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
8122fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardstatic xmlChar *
8123fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
8124fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    const xmlChar *q;
8125fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    xmlChar *ret = NULL;
8126fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
8127fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (CUR == '"') {
8128fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        NEXT;
8129fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	q = CUR_PTR;
813076e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
8131fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
813276e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	if (!IS_CHAR_CH(CUR)) {
813324505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard	    XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
8134fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	} else {
8135fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    ret = xmlStrndup(q, CUR_PTR - q);
8136fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
8137fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        }
8138fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    } else if (CUR == '\'') {
8139fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        NEXT;
8140fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	q = CUR_PTR;
814176e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
8142fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
814376e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	if (!IS_CHAR_CH(CUR)) {
814424505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard	    XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
8145fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	} else {
8146fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    ret = xmlStrndup(q, CUR_PTR - q);
8147fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
8148fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        }
8149fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    } else {
815024505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard	XP_ERRORNULL(XPATH_START_LITERAL_ERROR);
8151fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    }
8152fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    return(ret);
8153fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard}
8154fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
8155fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
8156afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompLiteral:
81573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
81583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Parse a Literal and push it on the stack.
81603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [29]   Literal ::=   '"' [^"]* '"'
81623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | "'" [^']* "'"
81633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8164afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * TODO: xmlXPathCompLiteral memory allocation could be improved.
81653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8166afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8167afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
81683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *q;
81693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret = NULL;
81703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '"') {
81723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
81733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	q = CUR_PTR;
817476e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
81753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
817676e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	if (!IS_CHAR_CH(CUR)) {
81773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
81783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
81793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlStrndup(q, CUR_PTR - q);
81803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
81813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
81823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '\'') {
81833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
81843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	q = CUR_PTR;
818576e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
81863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
818776e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	if (!IS_CHAR_CH(CUR)) {
81883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
81893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
81903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlStrndup(q, CUR_PTR - q);
81913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
81923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
81933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
81943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_START_LITERAL_ERROR);
81953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
81963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) return;
81979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0,
81989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           xmlXPathNewString(ret), NULL);
81993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ret);
82003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
82013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8203afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompVariableReference:
82043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
82053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Parse a VariableReference, evaluate it and push it on the stack.
82073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The variable bindings consist of a mapping from variable names
8209081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * to variable values. The value of a variable is an object, which can be
82103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of any of the types that are possible for the value of an expression,
82113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and may also be of additional types not specified here.
82123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Early evaluation is possible since:
82143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The variable bindings [...] used to evaluate a subexpression are
82153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * always the same as those used to evaluate the containing expression.
82163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [36]   VariableReference ::=   '$' QName
82183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8219afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8220afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
82213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name;
82223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *prefix;
82233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
82253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '$') {
82263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
82273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
82283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
82293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    name = xmlXPathParseQName(ctxt, &prefix);
82303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
82313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
82323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8233fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    ctxt->comp->last = -1;
82349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
82359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           name, prefix);
82363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
8237b3d1491b69060f8a67516b9a3ef12617adf88954Daniel Veillard    if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
8238b3d1491b69060f8a67516b9a3ef12617adf88954Daniel Veillard	XP_ERROR(XPATH_UNDEF_VARIABLE_ERROR);
8239b3d1491b69060f8a67516b9a3ef12617adf88954Daniel Veillard    }
82403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
82413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
82433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsNodeType:
82443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  a name string
82453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Is the name given a NodeType one.
82473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [38]   NodeType ::=   'comment'
82493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'text'
82503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'processing-instruction'
82513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'node'
82523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 1 if true 0 otherwise
82543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
82553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
82563473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsNodeType(const xmlChar *name) {
82573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
82583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
82593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82601971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "node"))
82613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
82623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrEqual(name, BAD_CAST "text"))
82633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
82641971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "comment"))
82653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
82661971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
82673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
82683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
82693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
82703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8272afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompFunctionCall:
82733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
82743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [16]   FunctionCall ::=   FunctionName '(' ( Argument ( ',' Argument)*)? ')'
82763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [17]   Argument ::=   Expr
82773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8278afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a function call, the evaluation of all arguments are
82793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * pushed on the stack
82803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8281afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8282afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
82833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name;
82843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *prefix;
82853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int nbargs = 0;
82863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    name = xmlXPathParseQName(ctxt, &prefix);
82883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
82893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_EXPR_ERROR);
82903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
82913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
82923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
82933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
82943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Calling function %s\n",
82953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			name);
82963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
82973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n",
82983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			prefix, name);
82993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
83003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '(') {
83023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_EXPR_ERROR);
83033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
83053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
83063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt->comp->last = -1;
830871f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard    if (CUR != ')') {
830971f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	while (CUR != 0) {
831071f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    int op1 = ctxt->comp->last;
831171f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    ctxt->comp->last = -1;
831271f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    xmlXPathCompileExpr(ctxt);
831371f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    CHECK_ERROR;
831471f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
831571f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    nbargs++;
831671f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    if (CUR == ')') break;
831771f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    if (CUR != ',') {
831871f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard		XP_ERROR(XPATH_EXPR_ERROR);
831971f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    }
832071f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    NEXT;
832171f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    SKIP_BLANKS;
83223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
83233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0,
83259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           name, prefix);
83263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
83273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
83283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
83293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8331afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPrimaryExpr:
83323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
83333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [15]   PrimaryExpr ::=   VariableReference
83353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | '(' Expr ')'
83363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | Literal
83373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | Number
83383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | FunctionCall
83393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8340afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a primary expression.
83413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8342afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8343afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) {
83443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
8345afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    if (CUR == '$') xmlXPathCompVariableReference(ctxt);
83463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (CUR == '(') {
83473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
83483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8349afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompileExpr(ctxt);
835050fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	CHECK_ERROR;
83513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ')') {
83523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
83533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
83543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
83553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8356d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack    } else if (IS_ASCII_DIGIT(CUR) || (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
8357afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompNumber(ctxt);
83583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if ((CUR == '\'') || (CUR == '"')) {
8359afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompLiteral(ctxt);
83603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
8361afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompFunctionCall(ctxt);
83623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
83643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
83653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8367afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompFilterExpr:
83683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
83693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [20]   FilterExpr ::=   PrimaryExpr
83713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr Predicate
83723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8373afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a filter expression.
83743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Square brackets are used to filter expressions in the same way that
83753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * they are used in location paths. It is an error if the expression to
83763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * be filtered does not evaluate to a node-set. The context node list
83773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * used for evaluating the expression in square brackets is the node-set
83783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be filtered listed in document order.
83793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
83803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8381afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8382afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
8383afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompPrimaryExpr(ctxt);
83843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
83853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
83863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '[') {
8388d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlXPathCompPredicate(ctxt, 1);
83893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
83903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
83943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
83963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathScanName:
83973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
83983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Trickery: parse an XML name but without consuming the input flow
84003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Needed to avoid insanity in the parser state.
84013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
84033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  CombiningChar | Extender
84043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] Name ::= (Letter | '_' | ':') (NameChar)*
84063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [6] Names ::= Name (S Name)*
84083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the Name parsed or NULL
84103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
84113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
841256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
84133473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathScanName(xmlXPathParserContextPtr ctxt) {
8414032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    int len = 0, l;
8415032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    int c;
8416032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    const xmlChar *cur;
8417032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    xmlChar *ret;
84183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8419032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    cur = ctxt->cur;
8420032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard
8421032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    c = CUR_CHAR(l);
8422032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
8423032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	(!IS_LETTER(c) && (c != '_') &&
8424032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard         (c != ':'))) {
84253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
84263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
84273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8428032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
8429032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
8430032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard            (c == '.') || (c == '-') ||
8431032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	    (c == '_') || (c == ':') ||
8432032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	    (IS_COMBINING(c)) ||
8433032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	    (IS_EXTENDER(c)))) {
8434032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	len += l;
8435032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	NEXTL(l);
8436032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	c = CUR_CHAR(l);
84373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8438032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    ret = xmlStrndup(cur, ctxt->cur - cur);
8439032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    ctxt->cur = cur;
8440032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    return(ret);
84413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
84423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8444afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPathExpr:
84453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
84463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [19]   PathExpr ::=   LocationPath
84483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr
84493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr '/' RelativeLocationPath
84503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr '//' RelativeLocationPath
84513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8452afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a path expression.
84533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The / operator and // operators combine an arbitrary expression
84543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and a relative location path. It is an error if the expression
84553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * does not evaluate to a node-set.
84563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The / operator does composition in the same way as when / is
84573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * used in a location path. As in location paths, // is short for
84583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * /descendant-or-self::node()/.
84593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
84603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8461afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8462afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
84633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int lc = 1;           /* Should we branch to LocationPath ?         */
84643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name = NULL; /* we may have to preparse a name to find out */
84653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
8467d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack    if ((CUR == '$') || (CUR == '(') ||
8468d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack    	(IS_ASCII_DIGIT(CUR)) ||
8469d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack        (CUR == '\'') || (CUR == '"') ||
8470d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack	(CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
84713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 0;
84723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '*') {
84733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative or absolute location path */
84743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
84753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '/') {
84763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative or absolute location path */
84773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
84783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '@') {
84793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative abbreviated attribute location path */
84803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
84813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '.') {
84823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative abbreviated attribute location path */
84833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
84843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
84853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
84863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * Problem is finding if we have a name here whether it's:
84873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a nodetype
84883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a function call in which case it's followed by '('
84893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - an axis in which case it's followed by ':'
84903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a element name
84913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * We do an a priori analysis here rather than having to
84923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * maintain parsed token content through the recursive function
8493081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	 * calls. This looks uglier but makes the code easier to
84943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * read/write/debug.
84953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
84963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
84973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathScanName(ctxt);
84983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
84993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
85003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
85013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "PathExpr: Axis\n");
85023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
85033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    lc = 1;
85043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
85053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (name != NULL) {
85063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int len =xmlStrlen(name);
85073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
85083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
85093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (NXT(len) != 0) {
85103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (NXT(len) == '/') {
85113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* element name */
85123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
85133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
85143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
85153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
85163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
85173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
851876e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack		} else if (IS_BLANK_CH(NXT(len))) {
851978637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack		    /* ignore blanks */
852078637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack		    ;
85213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if (NXT(len) == ':') {
85223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
85233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
85243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
85253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
85263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
85273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
85283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '(')) {
85293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* Note Type or Function */
85303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if (xmlXPathIsNodeType(name)) {
85313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
85323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		        xmlGenericError(xmlGenericErrorContext,
85333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"PathExpr: Type search\n");
85343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
85353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			lc = 1;
85363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    } else {
85373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
85383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		        xmlGenericError(xmlGenericErrorContext,
85393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"PathExpr: function call\n");
85403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
85413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			lc = 0;
85423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    }
85433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    break;
85443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '[')) {
85453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* element name */
85463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
85473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
85483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
85493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
85503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
85513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
85523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '<') || (NXT(len) == '>') ||
85533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   (NXT(len) == '=')) {
85543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
85553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
85563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
85573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
85583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
85593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
85603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		len++;
85613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
85623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (NXT(len) == 0) {
85633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
85643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlGenericError(xmlGenericErrorContext,
85653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			"PathExpr: AbbrRelLocation\n");
85663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
85673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		/* element name */
85683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		lc = 1;
85693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
85703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
85713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
8572081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    /* make sure all cases are covered explicitly */
85733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
85743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
85753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
85763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
85773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (lc) {
85789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (CUR == '/') {
85799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0);
85809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	} else {
85819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
85823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8583afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompLocationPath(ctxt);
85843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
8585afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompFilterExpr(ctxt);
85863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
85873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((CUR == '/') && (NXT(1) == '/')) {
85883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(2);
85893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
85909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
85919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
85929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
85939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_RESET, ctxt->comp->last, 1, 0);
85949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8595afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompRelativeLocationPath(ctxt);
85963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == '/') {
8597afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompRelativeLocationPath(ctxt);
85983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
85993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
86003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
86013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
86023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8604afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompUnionExpr:
86053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
86063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
86073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [18]   UnionExpr ::=   PathExpr
86083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | UnionExpr '|' PathExpr
86093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8610afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an union expression.
86113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
86123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8613afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8614afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) {
8615afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompPathExpr(ctxt);
86163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
86173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
86183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '|') {
86199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
86209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
86213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
86233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8624afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompPathExpr(ctxt);
86253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0);
86279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
86283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
86293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
86303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
86313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8633afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompUnaryExpr:
86343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
86353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
86363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [27]   UnaryExpr ::=   UnionExpr
86373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | '-' UnaryExpr
86383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8639afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an unary expression.
86403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
86413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8642afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8643afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) {
86443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int minus = 0;
86459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int found = 0;
86463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
864868d7b67ada0941ad7e1d02602f48de4015a67af3Daniel Veillard    while (CUR == '-') {
864968d7b67ada0941ad7e1d02602f48de4015a67af3Daniel Veillard        minus = 1 - minus;
86509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	found = 1;
86513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
86523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
86533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
86549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8655afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompUnionExpr(ctxt);
86563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
86579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (found) {
86589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (minus)
86599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0);
86609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	else
86619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0);
86623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
86633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
86643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8666afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompMultiplicativeExpr:
86673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
86683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
86693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [26]   MultiplicativeExpr ::=   UnaryExpr
86703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr MultiplyOperator UnaryExpr
86713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr 'div' UnaryExpr
86723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr 'mod' UnaryExpr
86733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [34]   MultiplyOperator ::=   '*'
86743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8675afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Additive expression.
86763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
86773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8678afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8679afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) {
8680afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompUnaryExpr(ctxt);
86813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
86823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
86833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '*') ||
86843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) ||
86853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) {
86863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int op = -1;
86879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
86883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '*') {
86903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 0;
86913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
86923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == 'd') {
86933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 1;
86943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(3);
86953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == 'm') {
86963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 2;
86973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(3);
86983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
86993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8700afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompUnaryExpr(ctxt);
87013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
87029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0);
87033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
87043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
87053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
87063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8708afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompAdditiveExpr:
87093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
87103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [25]   AdditiveExpr ::=   MultiplicativeExpr
87123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | AdditiveExpr '+' MultiplicativeExpr
87133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | AdditiveExpr '-' MultiplicativeExpr
87143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8715afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Additive expression.
87163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
87173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8718afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8719afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) {
87209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8721afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompMultiplicativeExpr(ctxt);
87223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
87233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
87243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '+') || (CUR == '-')) {
87253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int plus;
87269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
87273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '+') plus = 1;
87293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else plus = 0;
87303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
87313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8732afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompMultiplicativeExpr(ctxt);
87333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
87349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0);
87353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
87363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
87373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
87383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8740afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompRelationalExpr:
87413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
87423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [24]   RelationalExpr ::=   AdditiveExpr
87443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '<' AdditiveExpr
87453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '>' AdditiveExpr
87463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '<=' AdditiveExpr
87473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '>=' AdditiveExpr
87483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  A <= B > C is allowed ? Answer from James, yes with
87503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (AdditiveExpr <= AdditiveExpr) > AdditiveExpr
87513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  which is basically what got implemented.
87523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8753afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Relational expression, then push the result
87543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * on the stack
87553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
87563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8757afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8758afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) {
8759afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompAdditiveExpr(ctxt);
87603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
87613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
87623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '<') ||
87633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           (CUR == '>') ||
87643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == '<') && (NXT(1) == '=')) ||
87653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == '>') && (NXT(1) == '='))) {
87669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int inf, strict;
87679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
87683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '<') inf = 1;
87703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else inf = 0;
87713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (NXT(1) == '=') strict = 0;
87723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else strict = 1;
87733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
87743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!strict) NEXT;
87753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8776afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompAdditiveExpr(ctxt);
87773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
87789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict);
87793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
87803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
87813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
87823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8784afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompEqualityExpr:
87853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
87863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [23]   EqualityExpr ::=   RelationalExpr
87883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | EqualityExpr '=' RelationalExpr
87893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | EqualityExpr '!=' RelationalExpr
87903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  A != B != C is allowed ? Answer from James, yes with
87923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (RelationalExpr = RelationalExpr) = RelationalExpr
87933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (RelationalExpr != RelationalExpr) != RelationalExpr
87943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  which is basically what got implemented.
87953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8796afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Equality expression.
87973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8799afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8800afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) {
8801afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompRelationalExpr(ctxt);
88023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
88033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
88043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) {
88059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int eq;
88069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
88073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
88083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '=') eq = 1;
88093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else eq = 0;
88103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
88113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!eq) NEXT;
88123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8813afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompRelationalExpr(ctxt);
88143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
88159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0);
88163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
88173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
88183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
88193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
88203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8821afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompAndExpr:
88223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
88233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [22]   AndExpr ::=   EqualityExpr
88253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | AndExpr 'and' EqualityExpr
88263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8827afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an AND expression.
88283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8830afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8831afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) {
8832afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompEqualityExpr(ctxt);
88333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
88343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
88353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
88369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
88373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        SKIP(3);
88383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8839afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompEqualityExpr(ctxt);
88403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
88419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0);
88423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
88433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
88443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
88453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
88463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8847591b4be0fe1986b5e71d54c5c063493987ef4285Daniel Veillard * xmlXPathCompileExpr:
88483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
88493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [14]   Expr ::=   OrExpr
88513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [21]   OrExpr ::=   AndExpr
88523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | OrExpr 'or' AndExpr
88533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8854afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Parse and compile an expression
88553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8856afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8857afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompileExpr(xmlXPathParserContextPtr ctxt) {
8858afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompAndExpr(ctxt);
88593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
88603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
88613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == 'o') && (NXT(1) == 'r')) {
88629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
88633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        SKIP(2);
88643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8865afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompAndExpr(ctxt);
88663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
88679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0);
88689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	op1 = ctxt->comp->nbStep;
88693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
88703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
88719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE) {
88729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	/* more ops could be optimized too */
88739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0);
88749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
88753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
88763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
88773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8878afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPredicate:
88793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
8880d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @filter:  act as a filter
88813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [8]   Predicate ::=   '[' PredicateExpr ']'
88833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [9]   PredicateExpr ::=   Expr
88843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8885afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a predicate expression
88869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
8887afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8888d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
88899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int op1 = ctxt->comp->last;
88909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
88919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
88929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (CUR != '[') {
88939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
88949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
88959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NEXT;
88969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
88979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
88989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt->comp->last = -1;
8899afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompileExpr(ctxt);
89009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    CHECK_ERROR;
89019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
89029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (CUR != ']') {
89039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
89049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
89059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8906d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (filter)
8907d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
8908d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    else
8909d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
89109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
89119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NEXT;
89129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
89139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
89149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
89159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
8916afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompNodeTest:
89173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
89183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @test:  pointer to a xmlXPathTestVal
89193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @type:  pointer to a xmlXPathTypeVal
89203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  placeholder for a possible name prefix
89213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
89223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [7] NodeTest ::=   NameTest
89233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | NodeType '(' ')'
89243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | 'processing-instruction' '(' Literal ')'
89253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
89263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [37] NameTest ::=  '*'
89273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | NCName ':' '*'
89283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | QName
89293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [38] NodeType ::= 'comment'
89303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'text'
89313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'processing-instruction'
89323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'node'
89333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8934081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the name found and updates @test, @type and @prefix appropriately
89353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
893656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
8937afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
8938afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	             xmlXPathTypeVal *type, const xmlChar **prefix,
8939afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		     xmlChar *name) {
89403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int blanks;
89413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
89433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	STRANGE;
89443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
89453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
894678637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    *type = (xmlXPathTypeVal) 0;
894778637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    *test = (xmlXPathTestVal) 0;
89483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *prefix = NULL;
89493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
89503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((name == NULL) && (CUR == '*')) {
89523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
89533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * All elements
89543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
89553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
89563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*test = NODE_TEST_ALL;
89573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
89583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
89593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
89613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathParseNCName(ctxt);
89623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
896324505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard	XP_ERRORNULL(XPATH_EXPR_ERROR);
89643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
89653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
896676e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    blanks = IS_BLANK_CH(CUR);
89673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
89683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '(') {
89693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
89703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
89713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * NodeType or PI search
89723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
89733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (xmlStrEqual(name, BAD_CAST "comment"))
89743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_COMMENT;
89753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "node"))
89763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_NODE;
89773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
89783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_PI;
89793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "text"))
89803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_TEXT;
89813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else {
89823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
89833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
898424505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard	    XP_ERRORNULL(XPATH_EXPR_ERROR);
89853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
89863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*test = NODE_TEST_TYPE;
89883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
89903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*type == NODE_TYPE_PI) {
89913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /*
89923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     * Specific case: search a PI by name.
89933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     */
89943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
89953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
899682e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    name = NULL;
899782e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    if (CUR != ')') {
899882e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		name = xmlXPathParseLiteral(ctxt);
899924505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard		CHECK_ERROR NULL;
9000ed23b7dc73f6c1146701ece20ed3f03d68366516Daniel Veillard		*test = NODE_TEST_PI;
900182e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		SKIP_BLANKS;
900282e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    }
90033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
90043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ')') {
90053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
90063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
900724505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard	    XP_ERRORNULL(XPATH_UNCLOSED_ERROR);
90083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
90093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
90103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(name);
90113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
90123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *test = NODE_TEST_NAME;
90133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((!blanks) && (CUR == ':')) {
90143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
90153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
90163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
9017fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * Since currently the parser context don't have a
9018fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * namespace list associated:
9019fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * The namespace name for this prefix can be computed
9020fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * only at evaluation time. The compilation is done
9021fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * outside of any context.
90223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
9023fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#if 0
90243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*prefix = xmlXPathNsLookup(ctxt->context, name);
90253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (name != NULL)
90263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
90273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*prefix == NULL) {
90283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
90293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
9030fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#else
9031fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	*prefix = name;
9032fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#endif
90333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
90343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR == '*') {
90353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /*
90363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     * All elements
90373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     */
90383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
90393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *test = NODE_TEST_ALL;
90403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
90413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
90423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
90433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathParseNCName(ctxt);
90443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (name == NULL) {
904524505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard	    XP_ERRORNULL(XPATH_EXPR_ERROR);
90463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
90473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
90483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(name);
90493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
90503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
90513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
90523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsAxisName:
90533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  a preparsed name token
90543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
90553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [6] AxisName ::=   'ancestor'
90563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'ancestor-or-self'
90573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'attribute'
90583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'child'
90593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'descendant'
90603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'descendant-or-self'
90613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'following'
90623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'following-sibling'
90633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'namespace'
90643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'parent'
90653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'preceding'
90663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'preceding-sibling'
90673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'self'
90683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
90693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the axis or 0
90703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
907156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathAxisVal
90723473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsAxisName(const xmlChar *name) {
907378637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal ret = (xmlXPathAxisVal) 0;
90743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (name[0]) {
90753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'a':
90763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "ancestor"))
90773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ANCESTOR;
90783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "ancestor-or-self"))
90793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ANCESTOR_OR_SELF;
90803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "attribute"))
90813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ATTRIBUTE;
90823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
90833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'c':
90843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "child"))
90853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_CHILD;
90863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
90873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'd':
90883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "descendant"))
90893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_DESCENDANT;
90903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "descendant-or-self"))
90913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_DESCENDANT_OR_SELF;
90923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
90933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'f':
90943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "following"))
90953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_FOLLOWING;
90963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "following-sibling"))
90973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_FOLLOWING_SIBLING;
90983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
90993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'n':
91003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "namespace"))
91013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_NAMESPACE;
91023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
91033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'p':
91043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "parent"))
91053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PARENT;
91063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "preceding"))
91073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PRECEDING;
91083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "preceding-sibling"))
91093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PRECEDING_SIBLING;
91103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
91113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 's':
91123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "self"))
91133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_SELF;
91143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
91153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
91163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
91173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
91183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
91193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
9120afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompStep:
91213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
91223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
91233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] Step ::=   AxisSpecifier NodeTest Predicate*
91243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | AbbreviatedStep
91253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
91263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [12] AbbreviatedStep ::=   '.' | '..'
91273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
91283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] AxisSpecifier ::= AxisName '::'
91293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | AbbreviatedAxisSpecifier
91303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
91313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [13] AbbreviatedAxisSpecifier ::= '@'?
91323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
91333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Modified for XPtr range support as:
91343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
91353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
91363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedStep
91373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | 'range-to' '(' Expr ')' Predicate*
91383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9139afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile one step in a Location Path
91403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A location step of . is short for self::node(). This is
91413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * particularly useful in conjunction with //. For example, the
91423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * location path .//para is short for
91433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * self::node()/descendant-or-self::node()/child::para
91443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and so will select all para descendant elements of the context
91453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node.
91463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Similarly, a location step of .. is short for parent::node().
91473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * For example, ../title is short for parent::node()/child::title
91483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and so will select the title children of the parent of the context
91493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node.
91503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
9151afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
9152afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
9153fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
9154fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    int rangeto = 0;
9155fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    int op2 = -1;
9156fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
9157fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard
91583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
91593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '.') && (NXT(1) == '.')) {
91603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP(2);
91613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
91629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT,
91639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
91643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '.') {
91653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
91663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
91673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
91683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlChar *name = NULL;
91693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	const xmlChar *prefix = NULL;
9170aac7c68e87d00732b319698723de1ec43252fb01Daniel Veillard	xmlXPathTestVal test = (xmlXPathTestVal) 0;
917178637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
9172aac7c68e87d00732b319698723de1ec43252fb01Daniel Veillard	xmlXPathTypeVal type = (xmlXPathTypeVal) 0;
9173d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	int op1;
91743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
91753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
91763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * The modification needed for XPointer change to the production
91773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
91783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
9179fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	if (ctxt->xptr) {
91803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    name = xmlXPathParseNCName(ctxt);
91813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
9182fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard                op2 = ctxt->comp->last;
91833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
91843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
91853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (CUR != '(') {
91863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    XP_ERROR(XPATH_EXPR_ERROR);
91873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
91883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
91893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
91903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9191afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		xmlXPathCompileExpr(ctxt);
9192fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		/* PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, ctxt->comp->last, 0, 0); */
91933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		CHECK_ERROR;
91943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
91953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
91963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (CUR != ')') {
91973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    XP_ERROR(XPATH_EXPR_ERROR);
91983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
91993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
9200fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		rangeto = 1;
92013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		goto eval_predicates;
92023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
92033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
92043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
92052156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	if (CUR == '*') {
92062156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    axis = AXIS_CHILD;
92072156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	} else {
92082156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (name == NULL)
92092156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		name = xmlXPathParseNCName(ctxt);
92102156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (name != NULL) {
92112156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = xmlXPathIsAxisName(name);
92122156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		if (axis != 0) {
92132156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    SKIP_BLANKS;
92142156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    if ((CUR == ':') && (NXT(1) == ':')) {
92152156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			SKIP(2);
92162156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			xmlFree(name);
92172156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			name = NULL;
92182156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    } else {
92192156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			/* an element name can conflict with an axis one :-\ */
92202156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			axis = AXIS_CHILD;
92212156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    }
92223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
92233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    axis = AXIS_CHILD;
92243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
92252156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    } else if (CUR == '@') {
92262156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		NEXT;
92272156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = AXIS_ATTRIBUTE;
92283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else {
92292156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = AXIS_CHILD;
92303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
92313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
92323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
92333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
92343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9235afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
92363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (test == 0)
92373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
92383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9239ed6c54971fdb7fa37c183b1a36c2e581c750984bDaniel Veillard        if ((prefix != NULL) && (ctxt->context != NULL) &&
9240ed6c54971fdb7fa37c183b1a36c2e581c750984bDaniel Veillard	    (ctxt->context->flags & XML_XPATH_CHECKNS)) {
9241ed6c54971fdb7fa37c183b1a36c2e581c750984bDaniel Veillard	    if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) {
9242ed6c54971fdb7fa37c183b1a36c2e581c750984bDaniel Veillard		xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR);
9243ed6c54971fdb7fa37c183b1a36c2e581c750984bDaniel Veillard	    }
9244ed6c54971fdb7fa37c183b1a36c2e581c750984bDaniel Veillard	}
92453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
92463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
92473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"Basis : computing new set\n");
92483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
92499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
92503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
92513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Basis : ");
9252fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	if (ctxt->value == NULL)
9253fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "no value\n");
9254fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	else if (ctxt->value->nodesetval == NULL)
9255fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "Empty\n");
9256fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	else
9257fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval);
92583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
92593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
92605bb9ccd56a812b65e94e71477389be7826203649Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
92613473f88a7abdf4e585e267288fb77e898c580d2bOwen Tayloreval_predicates:
92625bb9ccd56a812b65e94e71477389be7826203649Daniel Veillard#endif
9263d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	op1 = ctxt->comp->last;
9264d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	ctxt->comp->last = -1;
9265d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
92663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
92673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (CUR == '[') {
9268d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    xmlXPathCompPredicate(ctxt, 0);
92693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
9270d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9271fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
9272fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	if (rangeto) {
9273fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0);
9274fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	} else
9275fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
9276fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
9277fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard			   test, type, (void *)prefix, (void *)name);
9278d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
92793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
92803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
92813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext, "Step : ");
9282fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    if (ctxt->value == NULL)
9283fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "no value\n");
9284fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    else if (ctxt->value->nodesetval == NULL)
9285fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "Empty\n");
9286fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    else
9287fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericErrorContextNodeSet(xmlGenericErrorContext,
9288fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		ctxt->value->nodesetval);
92893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
92903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
92913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
92923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
9293afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompRelativeLocationPath:
92943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
92953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
92963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [3]   RelativeLocationPath ::=   Step
92973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | RelativeLocationPath '/' Step
92983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedRelativeLocationPath
92993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [11]  AbbreviatedRelativeLocationPath ::=   RelativeLocationPath '//' Step
93003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9301afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a relative location path.
93023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
9303afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
9304afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelativeLocationPath
93053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor(xmlXPathParserContextPtr ctxt) {
93063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
93073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '/') && (NXT(1) == '/')) {
93083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP(2);
93093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
93109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
93119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		         NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
93123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '/') {
93133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
93143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
93153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
9316afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompStep(ctxt);
93173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
93183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '/') {
93193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((CUR == '/') && (NXT(1) == '/')) {
93203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(2);
93213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
93229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
93233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9324afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompStep(ctxt);
93253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == '/') {
93263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
93273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
9328afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompStep(ctxt);
93293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
93303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
93313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
93323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
93333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
93343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
9335afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompLocationPath:
93363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
93373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
93383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [1]   LocationPath ::=   RelativeLocationPath
93393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbsoluteLocationPath
93403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [2]   AbsoluteLocationPath ::=   '/' RelativeLocationPath?
93413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedAbsoluteLocationPath
93423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [10]   AbbreviatedAbsoluteLocationPath ::=
93433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                           '//' RelativeLocationPath
93443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9345afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a location path
9346afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
93473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * // is short for /descendant-or-self::node()/. For example,
93483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * //para is short for /descendant-or-self::node()/child::para and
93493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * so will select any para element in the document (even a para element
93503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * that is a document element will be selected by //para since the
93513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * document element node is a child of the root node); div//para is
93523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * short for div/descendant-or-self::node()/child::para and so will
93533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * select all para descendants of div children.
93543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
9355afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
9356afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
93573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
93583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '/') {
9359afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompRelativeLocationPath(ctxt);
93603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
93613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (CUR == '/') {
93623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((CUR == '/') && (NXT(1) == '/')) {
93633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP(2);
93643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
93659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
93669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9367afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		xmlXPathCompRelativeLocationPath(ctxt);
93683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else if (CUR == '/') {
93693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
9370608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		SKIP_BLANKS;
9371608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		if ((CUR != 0 ) &&
9372d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack		    ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') ||
9373608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		     (CUR == '@') || (CUR == '*')))
9374afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		    xmlXPathCompRelativeLocationPath(ctxt);
93753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
93763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
93773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
93783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
93793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
93809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
93819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *									*
93829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 		XPath precompiled expression evaluation			*
93839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *									*
93849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
93859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9387d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
9388d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
93899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
9390d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathNodeCollectAndTest:
9391d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
9392d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @op:  the XPath precompiled step operation
9393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  pointer to the first element in document order
9394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  pointer to the last element in document order
93959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
9396d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * This is the function implementing a step: based on the current list
9397d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * of nodes, it builds up a new list, looking at all nodes under that
9398081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * axis and selecting them. It also does the predicate filtering
9399d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
9400d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Pushes the new NodeSet resulting from the search.
9401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9402081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the number of nodes traversed
94039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
9404f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9405d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
9406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                           xmlXPathStepOpPtr op,
9407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard			   xmlNodePtr * first, xmlNodePtr * last)
9408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
940978637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
941078637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
941178637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
9412d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    const xmlChar *prefix = op->value4;
9413d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    const xmlChar *name = op->value5;
9414e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    const xmlChar *URI = NULL;
94159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9416d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9417f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int n = 0;
9418d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9419f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int i, t = 0;
9420d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodeSetPtr ret, list;
9421d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathTraversalFunction next = NULL;
9422f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
942375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    xmlNodeSetPtr (*mergeNodeSet) (xmlNodeSetPtr, xmlNodeSetPtr);
9424d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodePtr cur = NULL;
9425d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathObjectPtr obj;
9426d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodeSetPtr nodelist;
9427d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodePtr tmp;
9428d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    CHECK_TYPE0(XPATH_NODESET);
9430d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    obj = valuePop(ctxt);
9431d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    addNode = xmlXPathNodeSetAdd;
943275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    mergeNodeSet = xmlXPathNodeSetMerge;
9433e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    if (prefix != NULL) {
9434f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        URI = xmlXPathNsLookup(ctxt->context, prefix);
94352c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack        if (URI == NULL) {
94362c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	    xmlXPathFreeObject(obj);
9437f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
94382c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	}
9439e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    }
9440d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9441f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "new step : ");
9442d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9443d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (axis) {
9444d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ANCESTOR:
9445d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9446f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
9447d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestor;
9450f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9451d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ANCESTOR_OR_SELF:
9452d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9453f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9454f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'ancestors-or-self' ");
9455d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9456f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9457f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestorOrSelf;
9458f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9459d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ATTRIBUTE:
9460d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9461f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
9462d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9463f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9464f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9465f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAttribute;
946675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
9467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9468d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_CHILD:
9469d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
9471d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9472f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9473f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextChild;
947475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
9475f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9476d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_DESCENDANT:
9477d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
9479d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9480f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9481f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendant;
9482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9483d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_DESCENDANT_OR_SELF:
9484d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9485f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'descendant-or-self' ");
9487d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9488f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9489f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendantOrSelf;
9490f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9491d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_FOLLOWING:
9492d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9493f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
9494d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9495f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9496f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowing;
9497f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9498d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_FOLLOWING_SIBLING:
9499d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9500f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9501f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'following-siblings' ");
9502d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowingSibling;
9505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9506d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_NAMESPACE:
9507d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9508f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
9509d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9510f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9511f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9512f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
951375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
9514f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9515d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PARENT:
9516d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9517f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
9518d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9519f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9520f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextParent;
9521f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9522d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PRECEDING:
9523d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9524f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
9525d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9526f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9527f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingInternal;
9528f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9529d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PRECEDING_SIBLING:
9530d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9532f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'preceding-sibling' ");
9533d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9534f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9535f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingSibling;
9536f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9537d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_SELF:
9538d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9539f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
9540d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9541f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9542f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9543f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextSelf;
954475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
9545f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9546d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
95472c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack    if (next == NULL) {
95482c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	xmlXPathFreeObject(obj);
9549f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
95502c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack    }
9551d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9552d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    nodelist = obj->nodesetval;
9553d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (nodelist == NULL) {
9554f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlXPathFreeObject(obj);
9555f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
9556f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
9557d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
9558d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    addNode = xmlXPathNodeSetAddUnique;
9559d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ret = NULL;
9560d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9561d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9562f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    " context contains %d nodes\n", nodelist->nodeNr);
9563d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (test) {
9564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NONE:
9565f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for none !!!\n");
9567f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9568f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_TYPE:
9569f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9570f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for type %d\n", type);
9571f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9572f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_PI:
9573f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9574f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for PI !!!\n");
9575f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9576f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_ALL:
9577f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9578f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for *\n");
9579f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9580f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NS:
9581f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9582f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for namespace %s\n",
9583f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            prefix);
9584f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9585f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NAME:
9586f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9587f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for name %s\n", name);
9588f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (prefix != NULL)
9589f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlGenericError(xmlGenericErrorContext,
9590f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                "           with namespace %s\n", prefix);
9591f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9592d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
9593d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "Testing : ");
9594d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9595d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    /*
9596d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * 2.3 Node Tests
9597d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For the attribute axis, the principal node type is attribute.
9598d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For the namespace axis, the principal node type is namespace.
9599d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For other axes, the principal node type is element.
9600d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *
9601d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * A node test * is true for any node of the
9602cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard     * principal node type. For example, child::* will
9603d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * select all element children of the context node
9604d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     */
9605d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    tmp = ctxt->context->node;
9606f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < nodelist->nodeNr; i++) {
9607d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        ctxt->context->node = nodelist->nodeTab[i];
9608d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9609f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = NULL;
9610f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        list = xmlXPathNodeSetCreate(NULL);
9611f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        do {
9612f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur = next(ctxt, cur);
9613f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (cur == NULL)
9614f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9615f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((first != NULL) && (*first == cur))
9616f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9617f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9618f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (first != NULL) && (*first != NULL) &&
9619f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(*first, cur) >= 0))
9620f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9621f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((last != NULL) && (*last == cur))
9622f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9623f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9624f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(last != NULL) && (*last != NULL) &&
9625f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(cur, *last) >= 0))
9626f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9627d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard            t++;
9628f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP
9629d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard            xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
9630d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9631f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            switch (test) {
9632d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_NONE:
9633f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = tmp;
96342c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack		    xmlXPathFreeObject(obj);
9635f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    STRANGE return(t);
9636d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_TYPE:
9637f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((cur->type == type) ||
9638f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ((type == NODE_TYPE_NODE) &&
9639f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         ((cur->type == XML_DOCUMENT_NODE) ||
9640f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_HTML_DOCUMENT_NODE) ||
9641f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_ELEMENT_NODE) ||
9642f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Sanin                          (cur->type == XML_NAMESPACE_DECL) ||
9643f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Sanin                          (cur->type == XML_ATTRIBUTE_NODE) ||
9644f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_PI_NODE) ||
9645f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_COMMENT_NODE) ||
9646f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_CDATA_SECTION_NODE) ||
96477583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard                          (cur->type == XML_TEXT_NODE))) ||
96487583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard			((type == NODE_TYPE_TEXT) &&
96497583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard			 (cur->type == XML_CDATA_SECTION_NODE))) {
9650d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9651d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                        n++;
9652d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9653f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        addNode(list, cur);
9654f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9655f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9656d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_PI:
9657f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (cur->type == XML_PI_NODE) {
9658f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((name != NULL) &&
9659f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (!xmlStrEqual(name, cur->name)))
9660f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9661d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9662f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9663d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        addNode(list, cur);
9665f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9666f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9667d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_ALL:
9668f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (axis == AXIS_ATTRIBUTE) {
9669f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ATTRIBUTE_NODE) {
9670d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9671f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9672d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9673f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9674f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9675f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else if (axis == AXIS_NAMESPACE) {
9676f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_NAMESPACE_DECL) {
9677d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9678f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9679d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9680044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard                            xmlXPathNodeSetAddNs(list, ctxt->context->node,
9681044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				                 (xmlNsPtr) cur);
9682f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9683f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else {
9684f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ELEMENT_NODE) {
9685f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (prefix == NULL) {
9686d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9687f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9688d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9689f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9690f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            } else if ((cur->ns != NULL) &&
9691f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                       (xmlStrEqual(URI, cur->ns->href))) {
9692d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9693f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9694d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9695f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9696f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9697f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9698f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9699f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9700f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NS:{
9701f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        TODO;
9702f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        break;
9703f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9704d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_NAME:
9705f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    switch (cur->type) {
9706f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ELEMENT_NODE:
9707f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (xmlStrEqual(name, cur->name)) {
9708f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (prefix == NULL) {
9709f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (cur->ns == NULL) {
9710d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9711f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9712d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9713f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        addNode(list, cur);
9714f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9715f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                } else {
9716f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if ((cur->ns != NULL) &&
9717f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        (xmlStrEqual(URI,
9718f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     cur->ns->href))) {
9719d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9720f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9721d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9722f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        addNode(list, cur);
9723f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9724f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9725f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9726f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9727f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ATTRIBUTE_NODE:{
9728f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlAttrPtr attr = (xmlAttrPtr) cur;
9729f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9730f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (xmlStrEqual(name, attr->name)) {
9731f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (prefix == NULL) {
9732f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns == NULL) ||
9733f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (attr->ns->prefix == NULL)) {
9734d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9735f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9736d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9737f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list,
9738f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    (xmlNodePtr) attr);
9739f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9740f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    } else {
9741f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns != NULL) &&
9742f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (xmlStrEqual(URI,
9743f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         attr->ns->
9744f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         href))) {
9745d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9746f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9747d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9748f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list,
9749f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    (xmlNodePtr) attr);
9750f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9751f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9752f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9753f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                break;
9754f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9755f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_NAMESPACE_DECL:
9756f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (cur->type == XML_NAMESPACE_DECL) {
9757f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlNsPtr ns = (xmlNsPtr) cur;
9758f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9759f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if ((ns->prefix != NULL) && (name != NULL)
9760f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    && (xmlStrEqual(ns->prefix, name))) {
97618b8d2254fa1604efd37b3ba92eaeb2e40b2909a8Daniel Veillard#ifdef DEBUG_STEP
9762f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    n++;
97638b8d2254fa1604efd37b3ba92eaeb2e40b2909a8Daniel Veillard#endif
9764044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				    xmlXPathNodeSetAddNs(list,
9765044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					ctxt->context->node, (xmlNsPtr) cur);
9766f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9767f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9768f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9769f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        default:
9770f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9771f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9772f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9773f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9774f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9775f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } while (cur != NULL);
9776f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9777f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        /*
9778f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard         * If there is some predicate filtering do it now
9779f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard         */
97806fbcf42aa301dca50737c65fb738752328ca3a4cDaniel Veillard        if ((op->ch2 != -1) && (list != NULL) && (list->nodeNr > 0)) {
9781f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathObjectPtr obj2;
9782f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9783f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathWrapNodeSet(list));
9784f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch2]);
9785f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9786f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            obj2 = valuePop(ctxt);
9787f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            list = obj2->nodesetval;
9788f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            obj2->nodesetval = NULL;
9789f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(obj2);
97902c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	    if (ctxt->error != XPATH_EXPRESSION_OK) {
97912c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack		xmlXPathFreeObject(obj);
97922c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack		xmlXPathFreeNodeSet(list);
97932c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack		return(0);
97942c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	    }
9795f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
9796f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (ret == NULL) {
9797f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ret = list;
9798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } else {
979975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard            ret = mergeNodeSet(ret, list);
9800f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeNodeSet(list);
9801f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
9802d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
9803d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ctxt->context->node = tmp;
9804d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9805d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "\nExamined %d nodes, found %d nodes at that step\n",
9807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    t, n);
9808d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9809d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
98100ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->boolval) && (obj->user != NULL)) {
98110ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->boolval = 1;
98120ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->user = obj->user;
98130ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->user = NULL;
98140ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->boolval = 0;
98150ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    }
98160ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    xmlXPathFreeObject(obj);
9817f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(t);
9818d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
9819d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9820d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
9821f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNodeCollectAndTestNth:
9822f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath Parser context
9823f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  the XPath precompiled step operation
9824f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @indx:  the index to collect
9825f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  pointer to the first element in document order
9826f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  pointer to the last element in document order
9827f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9828f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * This is the function implementing a step: based on the current list
9829f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * of nodes, it builds up a new list, looking at all nodes under that
9830081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * axis and selecting them. It also does the predicate filtering
9831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9832f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Pushes the new NodeSet resulting from the search.
9833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
9834f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
9835f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9836f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNodeCollectAndTestNth(xmlXPathParserContextPtr ctxt,
9837f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlXPathStepOpPtr op, int indx,
9838f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlNodePtr * first, xmlNodePtr * last)
9839f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
984078637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
984178637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
984278637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
9843f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *prefix = op->value4;
9844f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *name = op->value5;
9845f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *URI = NULL;
9846f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int n = 0, t = 0;
9847f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9848f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int i;
9849f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodeSetPtr list;
9850f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathTraversalFunction next = NULL;
9851f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
9852f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr cur = NULL;
9853f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr obj;
9854f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodeSetPtr nodelist;
9855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr tmp;
9856f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9857f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    CHECK_TYPE0(XPATH_NODESET);
9858f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    obj = valuePop(ctxt);
9859f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    addNode = xmlXPathNodeSetAdd;
9860f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (prefix != NULL) {
9861f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        URI = xmlXPathNsLookup(ctxt->context, prefix);
98622c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack        if (URI == NULL) {
98632c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	    xmlXPathFreeObject(obj);
9864f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
98652c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	}
9866f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9867f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9868f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "new step : ");
9869f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (first != NULL) {
9870f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (*first != NULL)
9871f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "first = %s ",
9872f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    (*first)->name);
9873f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	else
9874f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "first = NULL ");
9875f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9876f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (last != NULL) {
9877f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (*last != NULL)
9878f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "last = %s ",
9879f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    (*last)->name);
9880f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	else
9881f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "last = NULL ");
9882f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9883f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9884f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (axis) {
9885f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ANCESTOR:
9886f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9887f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
9888f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9889f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9890f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestor;
9891f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9892f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ANCESTOR_OR_SELF:
9893f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9894f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9895f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'ancestors-or-self' ");
9896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9898f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestorOrSelf;
9899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ATTRIBUTE:
9901f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
9903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9905f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAttribute;
9907f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_CHILD:
9909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9910f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
9911f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9912f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9913f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextChild;
9914f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9915f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_DESCENDANT:
9916f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9917f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
9918f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9919f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9920f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendant;
9921f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9922f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_DESCENDANT_OR_SELF:
9923f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9924f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9925f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'descendant-or-self' ");
9926f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9928f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendantOrSelf;
9929f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9930f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_FOLLOWING:
9931f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
9933f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9934f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9935f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowing;
9936f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9937f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_FOLLOWING_SIBLING:
9938f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9939f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9940f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'following-siblings' ");
9941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9942f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowingSibling;
9944f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9945f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_NAMESPACE:
9946f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9947f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
9948f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9949f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9950f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9951f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
9952f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9953f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PARENT:
9954f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9955f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
9956f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9957f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextParent;
9959f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PRECEDING:
9961f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9962f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
9963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9964f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9965f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingInternal;
9966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9967f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PRECEDING_SIBLING:
9968f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9970f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'preceding-sibling' ");
9971f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9972f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9973f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingSibling;
9974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9975f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_SELF:
9976f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9977f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
9978f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9979f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9980f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9981f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextSelf;
9982f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9983f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
99842c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack    if (next == NULL) {
99852c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	xmlXPathFreeObject(obj);
9986f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
99872c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack    }
9988f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9989f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    nodelist = obj->nodesetval;
9990f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (nodelist == NULL) {
9991f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlXPathFreeObject(obj);
9992f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
9993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
9994f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9995f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    addNode = xmlXPathNodeSetAddUnique;
9996f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9997f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9998f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    " context contains %d nodes\n", nodelist->nodeNr);
9999f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (test) {
10000f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NONE:
10001f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
10002f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for none !!!\n");
10003f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
10004f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_TYPE:
10005f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
10006f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for type %d\n", type);
10007f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
10008f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_PI:
10009f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
10010f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for PI !!!\n");
10011f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
10012f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_ALL:
10013f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
10014f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for *\n");
10015f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
10016f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NS:
10017f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
10018f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for namespace %s\n",
10019f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            prefix);
10020f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
10021f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NAME:
10022f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
10023f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for name %s\n", name);
10024f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (prefix != NULL)
10025f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlGenericError(xmlGenericErrorContext,
10026f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                "           with namespace %s\n", prefix);
10027f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
10028f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10029f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "Testing : ");
10030f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
10031f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    /*
10032f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * 2.3 Node Tests
10033f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For the attribute axis, the principal node type is attribute.
10034f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For the namespace axis, the principal node type is namespace.
10035f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For other axes, the principal node type is element.
10036f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *
10037f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * A node test * is true for any node of the
10038cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard     * principal node type. For example, child::* will
10039f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * select all element children of the context node
10040f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     */
10041f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    tmp = ctxt->context->node;
10042f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    list = xmlXPathNodeSetCreate(NULL);
10043f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < nodelist->nodeNr; i++) {
10044f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->context->node = nodelist->nodeTab[i];
10045f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10046f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = NULL;
10047f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        n = 0;
10048f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        do {
10049f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur = next(ctxt, cur);
10050f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (cur == NULL)
10051f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
10052f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((first != NULL) && (*first == cur))
10053f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
10054f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
10055f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (first != NULL) && (*first != NULL) &&
10056f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(*first, cur) >= 0))
10057f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
10058f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((last != NULL) && (*last == cur))
10059f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
10060f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
10061f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (last != NULL) && (*last != NULL) &&
10062f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(cur, *last) >= 0))
10063f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
10064f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            t++;
10065f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            switch (test) {
10066f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NONE:
10067f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = tmp;
10068f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    STRANGE return(0);
10069f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_TYPE:
10070f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((cur->type == type) ||
10071f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ((type == NODE_TYPE_NODE) &&
10072f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         ((cur->type == XML_DOCUMENT_NODE) ||
10073f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_HTML_DOCUMENT_NODE) ||
10074f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_ELEMENT_NODE) ||
10075f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_PI_NODE) ||
10076f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_COMMENT_NODE) ||
10077f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_CDATA_SECTION_NODE) ||
100788606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard                          (cur->type == XML_TEXT_NODE))) ||
100798606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard			((type == NODE_TYPE_TEXT) &&
100808606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard			 (cur->type == XML_CDATA_SECTION_NODE))) {
10081f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
10082f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (n == indx)
10083f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
10084f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10085f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
10086f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_PI:
10087f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (cur->type == XML_PI_NODE) {
10088f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((name != NULL) &&
10089f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (!xmlStrEqual(name, cur->name)))
10090f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
10091f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
10092f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (n == indx)
10093f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
10094f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10095f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
10096f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_ALL:
10097f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (axis == AXIS_ATTRIBUTE) {
10098f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ATTRIBUTE_NODE) {
10099f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
10100f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (n == indx)
10101f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
10102f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10103f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else if (axis == AXIS_NAMESPACE) {
10104f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_NAMESPACE_DECL) {
10105f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
10106f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (n == indx)
10107044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				xmlXPathNodeSetAddNs(list, ctxt->context->node,
10108044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard						     (xmlNsPtr) cur);
10109f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else {
10111f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ELEMENT_NODE) {
10112f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (prefix == NULL) {
10113f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
10114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (n == indx)
10115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    addNode(list, cur);
10116f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            } else if ((cur->ns != NULL) &&
10117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                       (xmlStrEqual(URI, cur->ns->href))) {
10118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
10119f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (n == indx)
10120f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    addNode(list, cur);
10121f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
10122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10123f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10124f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
10125f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NS:{
10126f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        TODO;
10127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        break;
10128f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10129f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NAME:
10130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    switch (cur->type) {
10131f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ELEMENT_NODE:
10132f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (xmlStrEqual(name, cur->name)) {
10133f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (prefix == NULL) {
10134f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (cur->ns == NULL) {
10135f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
10136f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if (n == indx)
10137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list, cur);
10138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
10139f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                } else {
10140f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if ((cur->ns != NULL) &&
10141f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        (xmlStrEqual(URI,
10142f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     cur->ns->href))) {
10143f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
10144f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if (n == indx)
10145f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list, cur);
10146f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
10147f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
10148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
10149f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
10150f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ATTRIBUTE_NODE:{
10151f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlAttrPtr attr = (xmlAttrPtr) cur;
10152f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10153f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (xmlStrEqual(name, attr->name)) {
10154f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (prefix == NULL) {
10155f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns == NULL) ||
10156f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (attr->ns->prefix == NULL)) {
10157f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
10158f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            if (n == indx)
10159f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                addNode(list, cur);
10160f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
10161f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    } else {
10162f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns != NULL) &&
10163f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (xmlStrEqual(URI,
10164f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         attr->ns->
10165f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         href))) {
10166f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
10167f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            if (n == indx)
10168f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                addNode(list, cur);
10169f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
10170f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
10171f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
10172f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                break;
10173f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
10174f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_NAMESPACE_DECL:
10175f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (cur->type == XML_NAMESPACE_DECL) {
10176f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlNsPtr ns = (xmlNsPtr) cur;
10177f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10178f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if ((ns->prefix != NULL) && (name != NULL)
10179f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    && (xmlStrEqual(ns->prefix, name))) {
10180f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    n++;
10181f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (n == indx)
10182044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					xmlXPathNodeSetAddNs(list,
10183044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					   ctxt->context->node, (xmlNsPtr) cur);
10184f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
10185f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
10186f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
10187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        default:
10188f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
10189f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10190f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
10191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
10192f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } while (n < indx);
10194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    ctxt->context->node = tmp;
10196f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
10197f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
10198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "\nExamined %d nodes, found %d nodes at that step\n",
10199f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    t, list->nodeNr);
10200f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
10201f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(list));
102020ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->boolval) && (obj->user != NULL)) {
102030ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->boolval = 1;
102040ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->user = obj->user;
102050ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->user = NULL;
102060ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->boolval = 0;
102070ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    }
102080ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    xmlXPathFreeObject(obj);
10209f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(t);
10210f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
10211f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
10213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEvalFirst:
10214d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
10215d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @op:  an XPath compiled operation
10216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  the first elem found so far
10217d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
10218f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation searching only the first
10219f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * element in document order
10220f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
10221f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of examined objects.
10222d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
10223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
10224f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
10225f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathStepOpPtr op, xmlNodePtr * first)
10226f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
10227f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0, cur;
10228d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathCompExprPtr comp;
10229d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
10230d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
10231556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
10232d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    comp = ctxt->comp;
10233d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (op->op) {
10234f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
10235f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10236f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
10237f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total =
10238f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
10239f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        first);
10240556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10241f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10242f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10243f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
10244f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
10245f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10246f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * limit tree traversing to first node in the result
10247f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10248f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10249f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                *first = ctxt->value->nodesetval->nodeTab[0];
10250f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10251f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur =
10252f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
10253f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        first);
10254556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10256f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
10257f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10258f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10259f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10260f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10261f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
10262f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
10263f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10264f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10265f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            /* optimizer */
10266f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (total > cur)
10267f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		xmlXPathCompSwap(op);
10268f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total + cur);
10269f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
10270f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
10271f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10272f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
10273f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10274f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10275556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10276f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10277f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10278556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10279f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
10280f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10281f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
10282f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10283f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10284556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10285f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10286f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10287556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10288f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
10289f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10290f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
10291f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
10292f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10293f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10294f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10295556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10296f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10297f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10298f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
10299f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10300f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
10301f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
10302f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
10303f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
10304f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
10305f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
10306f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10307f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10308f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
10309f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
10310f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
10311f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10312f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
10313f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathNodeCollectAndTestNth(ctxt, op, indx,
10314f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                          first, NULL);
10315f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10316f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10317f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10318f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL);
10320f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
10323f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
10324f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
10325f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10326f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
10327f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10328f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total +=
10329f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
10330f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            first);
10331556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10332f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10333f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10334f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL))
10335f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10336f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10337f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        default:
10338f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (xmlXPathCompOpEval(ctxt, op));
10339f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10340f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
1034142596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard
10342f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
10343f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEvalLast:
10344f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
10345f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  an XPath compiled operation
10346f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  the last elem found so far
10347f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
10348f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation searching only the last
10349f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * element in document order
10350f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
10351081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the number of nodes traversed
10352f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
10353f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
10354f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
10355f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                       xmlNodePtr * last)
10356f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
10357f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0, cur;
10358f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathCompExprPtr comp;
10359f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
10360ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack    xmlNodePtr bak;
10361ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack    xmlDocPtr bakd;
10362ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack    int pp;
10363ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack    int cs;
103649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10365556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
10366f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp = ctxt->comp;
10367f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (op->op) {
10368f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
10369f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10370f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
10371ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    bakd = ctxt->context->doc;
10372ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    bak = ctxt->context->node;
10373ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    pp = ctxt->context->proximityPosition;
10374ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    cs = ctxt->context->contextSize;
10375f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total =
10376f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
10377556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10378f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10379f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10380f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
10381f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
10382f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10383f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * limit tree traversing to first node in the result
10384f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10385f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                *last =
10387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->value->nodesetval->nodeTab[ctxt->value->
10388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     nodesetval->nodeNr -
10389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     1];
10390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10391ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    ctxt->context->doc = bakd;
10392ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    ctxt->context->node = bak;
10393ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    ctxt->context->proximityPosition = pp;
10394ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    ctxt->context->contextSize = cs;
10395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur =
10396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
10397556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10399f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10400f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
10401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
10402f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10403f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10404f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
10405f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10409f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
10410f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
10411f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10412f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10413f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            /* optimizer */
10414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (total > cur)
10415f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		xmlXPathCompSwap(op);
10416f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total + cur);
10417f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
10418f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
10419f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10420f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
10421f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10422f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10423556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10424f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10425f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10426556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10427f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
10428f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
10430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10432556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10433f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10434f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10435556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10436f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
10437f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10438f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
10439f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
10440f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (0);
10441f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10442f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10443556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10444f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10445f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10446f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
10447f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
10449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
10450f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
10451f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
10452f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
10453f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
10454f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10455f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10456f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
10457f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
10458f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
10459f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10460f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
10461f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10462f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathNodeCollectAndTestNth(ctxt, op,
10463f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              indx, NULL,
10464f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              last);
10465f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10466f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10469f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last);
10470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10471f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10472f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
10473f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
10474f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
10475f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10476f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
10477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total +=
10479f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1],
10480f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                           last);
10481556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10483f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10484f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL))
10485f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10487f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        default:
10488f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (xmlXPathCompOpEval(ctxt, op));
10489f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10490f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
104919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10492f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
10493f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEval:
10494f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
10495f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  an XPath compiled operation
10496f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
10497f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation
10498081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the number of nodes traversed
10499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
10500f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
10501f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
10502f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
10503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0;
10504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int equal, ret;
10505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathCompExprPtr comp;
10506f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
105077089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard    xmlNodePtr bak;
105087089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard    xmlDocPtr bakd;
105096000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack    int pp;
10510692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack    int cs;
105119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10512556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
10513f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp = ctxt->comp;
10514f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (op->op) {
10515f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
10516f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10517f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_AND:
105187089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
105197089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
105206000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10521692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10522f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10523556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10524f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
10525f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
10526f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10527f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
105287089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
105297089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
105306000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10531692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10532f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10533556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    if (ctxt->error) {
10534556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathFreeObject(arg2);
10535556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		return(0);
10536556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    }
10537f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
10538f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10539f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->boolval &= arg2->boolval;
10540f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10541f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10542f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10543f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_OR:
105447089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
105457089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
105466000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10547692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10548f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10549556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10550f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
10551f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
10552f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10553f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
105547089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
105557089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
105566000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10557692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10558f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10559556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    if (ctxt->error) {
10560556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathFreeObject(arg2);
10561556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		return(0);
10562556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    }
10563f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
10564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10565f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->boolval |= arg2->boolval;
10566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10567f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10568f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10569f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_EQUAL:
105707089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
105717089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
105726000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10573692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10574f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10575556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
105767089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
105777089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
105786000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10579692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10580f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10581556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
105820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (op->value)
105830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        	equal = xmlXPathEqualValues(ctxt);
105840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    else
105850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		equal = xmlXPathNotEqualValues(ctxt);
105860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    valuePush(ctxt, xmlXPathNewBoolean(equal));
10587f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10588f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_CMP:
105897089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
105907089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
105916000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10592692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10593f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10594556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
105957089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
105967089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
105976000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10598692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10599f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10600556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10601f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
10602f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewBoolean(ret));
10603f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10604f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_PLUS:
106057089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
106067089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
106076000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10608692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10609f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10610556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
106117089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard            if (op->ch2 != -1) {
106127089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard		ctxt->context->doc = bakd;
106137089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard		ctxt->context->node = bak;
106146000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack		ctxt->context->proximityPosition = pp;
10615692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack		ctxt->context->contextSize = cs;
10616f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
106177089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    }
10618556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10619f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value == 0)
10620f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathSubValues(ctxt);
10621f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 1)
10622f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathAddValues(ctxt);
10623f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 2)
10624f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathValueFlipSign(ctxt);
10625f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 3) {
10626f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CAST_TO_NUMBER;
10627f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NUMBER);
10628f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10629f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10630f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_MULT:
106317089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
106327089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
106336000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10634692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10635f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10636556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
106377089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
106387089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
106396000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10640692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10641f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10642556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10643f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value == 0)
10644f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathMultValues(ctxt);
10645f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 1)
10646f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathDivValues(ctxt);
10647f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 2)
10648f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathModValues(ctxt);
10649f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10650f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
106517089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
106527089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
106536000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10654692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10655f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10656556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
106577089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
106587089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
106596000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10660692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10661f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10662556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10663f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
10665f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10666f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10667f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10668f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10669f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
10670f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
10671f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10672f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10673f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10674f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
10675f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
10676f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10677f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
10678f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10679f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10680556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10681f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10682f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10683556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10684f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
10685f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10686f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
10687f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10688f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10689556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10690f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10691f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10692556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10693f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
10694f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10695f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
10696f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
10697f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10698f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10699f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10700556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10701f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10702f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10703f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
10704f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10705f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
10706f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
10707f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
10708f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
10709f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
10710f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
10711f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10712f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10713f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
10714f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
10715f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
10716f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10717f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
10718f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10719f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathNodeCollectAndTestNth(ctxt, op,
10720f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              indx, NULL,
10721f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              NULL);
10722f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10723f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10724f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10725f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10726f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL);
10727f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10728f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10729f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
10730f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
10731f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
10732f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10733f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VARIABLE:{
10734556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathObjectPtr val;
10735556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard
10736f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10737f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10738f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10739556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                if (op->value5 == NULL) {
10740556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    val = xmlXPathVariableLookup(ctxt->context, op->value4);
10741556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (val == NULL) {
10742556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
10743556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return(0);
10744556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10745556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                    valuePush(ctxt, val);
10746556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		} else {
10747f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    const xmlChar *URI;
10748f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10749f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    URI = xmlXPathNsLookup(ctxt->context, op->value5);
10750f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (URI == NULL) {
10751f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlGenericError(xmlGenericErrorContext,
10752cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                        "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
10753f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        op->value4, op->value5);
10754f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10755f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10756556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    val = xmlXPathVariableLookupNS(ctxt->context,
10757556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                                                       op->value4, URI);
10758556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (val == NULL) {
10759556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
10760556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return(0);
10761556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10762556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                    valuePush(ctxt, val);
10763f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10764f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10765f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10766f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_FUNCTION:{
10767f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFunction func;
10768f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                const xmlChar *oldFunc, *oldFuncURI;
10769556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		int i;
10770f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10771f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10772f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10773f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10774556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		if (ctxt->valueNr < op->value) {
10775556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    xmlGenericError(xmlGenericErrorContext,
10776cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard			    "xmlXPathCompOpEval: parameter error\n");
10777556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    ctxt->error = XPATH_INVALID_OPERAND;
10778556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    return (total);
10779556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		}
10780556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		for (i = 0; i < op->value; i++)
10781556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
10782556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			xmlGenericError(xmlGenericErrorContext,
10783cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard				"xmlXPathCompOpEval: parameter error\n");
10784556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_INVALID_OPERAND;
10785556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return (total);
10786556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10787f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->cache != NULL)
10788ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack                    XML_CAST_FPTR(func) = op->cache;
10789f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                else {
10790f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    const xmlChar *URI = NULL;
10791f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10792f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (op->value5 == NULL)
10793f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        func =
10794f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFunctionLookup(ctxt->context,
10795f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   op->value4);
10796f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    else {
10797f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        URI = xmlXPathNsLookup(ctxt->context, op->value5);
10798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (URI == NULL) {
10799f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlGenericError(xmlGenericErrorContext,
10800cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                            "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
10801f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            op->value4, op->value5);
10802f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10803f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10804f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        func = xmlXPathFunctionLookupNS(ctxt->context,
10805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                        op->value4, URI);
10806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (func == NULL) {
10808f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlGenericError(xmlGenericErrorContext,
10809cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                        "xmlXPathCompOpEval: function %s not found\n",
10810f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        op->value4);
10811f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
10812f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10813ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack                    op->cache = XML_CAST_FPTR(func);
10814f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    op->cacheURI = (void *) URI;
10815f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10816f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldFunc = ctxt->context->function;
10817f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldFuncURI = ctxt->context->functionURI;
10818f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->function = op->value4;
10819f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->functionURI = op->cacheURI;
10820f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                func(ctxt, op->value);
10821f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->function = oldFunc;
10822f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->functionURI = oldFuncURI;
10823f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10824f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10825f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ARG:
10826088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    bakd = ctxt->context->doc;
10827088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    bak = ctxt->context->node;
10828645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    pp = ctxt->context->proximityPosition;
10829645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    cs = ctxt->context->contextSize;
10830f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10832645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    ctxt->context->contextSize = cs;
10833645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    ctxt->context->proximityPosition = pp;
10834088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->node = bak;
10835645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    ctxt->context->doc = bakd;
10836556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
1083772ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack            if (op->ch2 != -1) {
10838f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
1083972ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack	        ctxt->context->doc = bakd;
1084072ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack	        ctxt->context->node = bak;
1084172ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack	        CHECK_ERROR0;
1084272ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack	    }
10843f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10844f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_PREDICATE:
10845f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_FILTER:{
10846f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr res;
10847f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr obj, tmp;
10848f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr newset = NULL;
10849f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr oldset;
10850f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodePtr oldnode;
108513794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		xmlDocPtr oldDoc;
10852f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                int i;
10853f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10854f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for ()[1] selection i.e. the first elem
10856f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10857f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch1 != -1) && (op->ch2 != -1) &&
10858f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
10859f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_VALUE)) {
10860f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10861f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10862f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[op->ch2].value4;
10863f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER) &&
10864f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (val->floatval == 1.0)) {
10865f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlNodePtr first = NULL;
10866f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10867f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10868f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEvalFirst(ctxt,
10869f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    &comp->steps[op->ch1],
10870f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    &first);
10871556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			CHECK_ERROR0;
10872f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10873f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The nodeset should be in document order,
10874f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Keep only the first value
10875f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10876f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((ctxt->value != NULL) &&
10877f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->type == XPATH_NODESET) &&
10878f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval != NULL) &&
10879f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeNr > 1))
10880f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeNr = 1;
10881f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10882f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10883f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10884f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10885f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for ()[last()] selection i.e. the last elem
10886f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10887f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch1 != -1) && (op->ch2 != -1) &&
10888f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
10889f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
10890f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    int f = comp->steps[op->ch2].ch1;
10891f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10892f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((f != -1) &&
10893f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].op == XPATH_OP_FUNCTION) &&
10894f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value5 == NULL) &&
10895f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value == 0) &&
10896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value4 != NULL) &&
10897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (xmlStrEqual
10898f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         (comp->steps[f].value4, BAD_CAST "last"))) {
10899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlNodePtr last = NULL;
10900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10901f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEvalLast(ctxt,
10903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch1],
10904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &last);
10905556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			CHECK_ERROR0;
10906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10907f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The nodeset should be in document order,
10908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Keep only the last value
10909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10910f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((ctxt->value != NULL) &&
10911f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->type == XPATH_NODESET) &&
10912f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval != NULL) &&
10913f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeTab != NULL) &&
10914f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeNr > 1)) {
10915f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeTab[0] =
10916f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                ctxt->value->nodesetval->nodeTab[ctxt->
10917f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 value->
10918f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 nodesetval->
10919f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 nodeNr -
10920f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 1];
10921f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeNr = 1;
10922f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10923f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10924f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10925f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10926f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10928f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10929f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10930556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10931f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch2 == -1)
10932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10933f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (ctxt->value == NULL)
10934f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10935f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10936f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldnode = ctxt->context->node;
109379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10938f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
10939f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10940f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Hum are we filtering the result of an XPointer expression
10941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10942f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (ctxt->value->type == XPATH_LOCATIONSET) {
10943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlLocationSetPtr newlocset = NULL;
10944f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlLocationSetPtr oldlocset;
10945f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10946f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10947f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * Extract the old locset, and then evaluate the result of the
10948f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * expression for all the element in the locset. use it to grow
10949f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * up a new locset.
10950f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10951f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    CHECK_TYPE0(XPATH_LOCATIONSET);
10952f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    obj = valuePop(ctxt);
10953f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    oldlocset = obj->user;
10954f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10955f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10956f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
10957f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = 0;
10958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = 0;
10959f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10961f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10962f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10964f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10965f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, obj);
10967f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10968f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10970f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    newlocset = xmlXPtrLocationSetCreate(NULL);
10971f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10972f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldlocset->locNr; i++) {
10973f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of a
10975f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * single item in the nodelocset.
10976f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10977f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldlocset->locTab[i]->user;
10978f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = oldlocset->locNr;
10979f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = i + 1;
10980f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10981f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        valuePush(ctxt, tmp);
10982f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10983f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10984f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10985f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10986f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
109872c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			if (ctxt->error != XPATH_EXPRESSION_OK) {
109882c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    xmlXPathFreeObject(obj);
109892c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    return(0);
109902c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			}
10991f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10992f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The result of the evaluation need to be tested to
10994f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * decided whether the filter succeeded or not
10995f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10996f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10997f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
10998f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPtrLocationSetAdd(newlocset,
10999f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                  xmlXPathObjectCopy
11000f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                  (oldlocset->locTab[i]));
11001f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
11002f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11003f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
11004f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
11005f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
11006f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
11007f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
11008f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
11009f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
11010f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
11011f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
11012f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11013f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
11014f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
11015f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11016f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
11017f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * The result is used as the new evaluation locset.
11018f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
11019f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathFreeObject(obj);
11020f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
11021f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = -1;
11022f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = -1;
11023f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
11024f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = oldnode;
11025f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
11026f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
110279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
110289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11029f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
11030f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Extract the old set, and then evaluate the result of the
11031f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * expression for all the element in the set. use it to grow
11032f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * up a new set.
11033f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
11034f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NODESET);
11035f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                obj = valuePop(ctxt);
11036f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldset = obj->nodesetval;
11037f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11038f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldnode = ctxt->context->node;
110393794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		oldDoc = ctxt->context->doc;
11040f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
11041f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11042f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((oldset == NULL) || (oldset->nodeNr == 0)) {
11043f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = 0;
11044f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = 0;
110458fad8bff2c2e0b064a6d48d4eeb663804de5545fWilliam M. Brack/*
11046f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (op->ch2 != -1)
11047f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
11048f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEval(ctxt,
11049f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                               &comp->steps[op->ch2]);
11050556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    CHECK_ERROR0;
11051f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    res = valuePop(ctxt);
11052f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (res != NULL)
11053f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathFreeObject(res);
110548fad8bff2c2e0b064a6d48d4eeb663804de5545fWilliam M. Brack*/
11055f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, obj);
11056f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = oldnode;
11057f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    CHECK_ERROR0;
11058f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                } else {
11059f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
11060f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * Initialize the new set.
110613794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		     * Also set the xpath document in case things like
110623794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		     * key() evaluation are attempted on the predicate
11063f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
11064f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    newset = xmlXPathNodeSetCreate(NULL);
11065f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11066f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldset->nodeNr; i++) {
11067f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
11068f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of
11069f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * a single item in the nodeset.
11070f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
11071f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldset->nodeTab[i];
110723794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack			if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) &&
110733794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack			    (oldset->nodeTab[i]->doc != NULL))
110743794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		            ctxt->context->doc = oldset->nodeTab[i]->doc;
11075f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
11076f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
11077f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = oldset->nodeNr;
11078f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = i + 1;
11079f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11080f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
11081f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
11082f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
11083f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
110842c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			if (ctxt->error != XPATH_EXPRESSION_OK) {
110852c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    xmlXPathFreeNodeSet(newset);
110862c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    xmlXPathFreeObject(obj);
110872c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    return(0);
110882c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			}
11089f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11090f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
11091081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                         * The result of the evaluation needs to be tested to
11092081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                         * decide whether the filter succeeded or not
11093f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
11094f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
11095f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
11096f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
11097f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
11098f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11099f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
11100f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
11101f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
11102f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
11103f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
11104f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
11105f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
11106f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
11107f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
11108f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11109f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
11110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
11111f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11112f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
11113f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * The result is used as the new evaluation set.
11114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
11115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathFreeObject(obj);
11116f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
11117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = -1;
11118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = -1;
111193794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		    /* may want to move this past the '}' later */
111203794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		    ctxt->context->doc = oldDoc;
11121f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, xmlXPathWrapNodeSet(newset));
11122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
11123f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = oldnode;
11124f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
11125f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
11126f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
11127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
11128f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11129556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
11130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL) &&
11131f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                (ctxt->value->type == XPATH_NODESET) &&
11132f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                (ctxt->value->nodesetval != NULL))
11133f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
11134f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
111359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#ifdef LIBXML_XPTR_ENABLED
11136f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RANGETO:{
11137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr range;
11138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr res, obj;
11139f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr tmp;
11140081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                xmlLocationSetPtr newlocset = NULL;
11141081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    xmlLocationSetPtr oldlocset;
11142f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr oldset;
1114372ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack                int i, j;
11144f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11145f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
11146f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
11147f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch2 == -1)
11149f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
11150f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11151081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                if (ctxt->value->type == XPATH_LOCATIONSET) {
11152081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    /*
11153081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                     * Extract the old locset, and then evaluate the result of the
11154081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                     * expression for all the element in the locset. use it to grow
11155081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                     * up a new locset.
11156081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                     */
11157081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    CHECK_TYPE0(XPATH_LOCATIONSET);
11158081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    obj = valuePop(ctxt);
11159081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    oldlocset = obj->user;
11160f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11161081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
1116272ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack		        ctxt->context->node = NULL;
11163081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        ctxt->context->contextSize = 0;
11164081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        ctxt->context->proximityPosition = 0;
11165081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        total += xmlXPathCompOpEval(ctxt,&comp->steps[op->ch2]);
11166081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        res = valuePop(ctxt);
11167081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        if (res != NULL)
11168081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            xmlXPathFreeObject(res);
11169081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        valuePush(ctxt, obj);
11170081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        CHECK_ERROR0;
11171081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        return (total);
11172081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    }
11173081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    newlocset = xmlXPtrLocationSetCreate(NULL);
11174f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11175081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    for (i = 0; i < oldlocset->locNr; i++) {
11176f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
11177081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                         * Run the evaluation with a node list made of a
11178081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                         * single item in the nodelocset.
11179f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
11180f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        ctxt->context->node = oldlocset->locTab[i]->user;
11181f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        ctxt->context->contextSize = oldlocset->locNr;
11182f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        ctxt->context->proximityPosition = i + 1;
11183f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
11184f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
11185f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11186f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
11187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
11188f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
11189f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
111902c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			if (ctxt->error != XPATH_EXPRESSION_OK) {
111912c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    xmlXPathFreeObject(obj);
111922c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    return(0);
111932c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			}
11194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
1119672ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			if (res->type == XPATH_LOCATIONSET) {
1119772ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    xmlLocationSetPtr rloc =
1119872ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			        (xmlLocationSetPtr)res->user;
1119972ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    for (j=0; j<rloc->locNr; j++) {
1120072ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			        range = xmlXPtrNewRange(
1120172ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				  oldlocset->locTab[i]->user,
1120272ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				  oldlocset->locTab[i]->index,
1120372ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				  rloc->locTab[j]->user2,
1120472ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				  rloc->locTab[j]->index2);
1120572ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				if (range != NULL) {
1120672ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				    xmlXPtrLocationSetAdd(newlocset, range);
1120772ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				}
1120872ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    }
1120972ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			} else {
1121072ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    range = xmlXPtrNewRangeNodeObject(
1121172ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				(xmlNodePtr)oldlocset->locTab[i]->user, res);
1121272ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack                            if (range != NULL) {
1121372ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack                                xmlXPtrLocationSetAdd(newlocset,range);
1121472ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    }
11215f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
11216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11217f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
11218f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
11219f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
11220f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
11221f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
11222f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
11223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
11224f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
11225f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
11226f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11227f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
11228f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
1122972ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack		} else {	/* Not a location set */
11230081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    CHECK_TYPE0(XPATH_NODESET);
11231081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    obj = valuePop(ctxt);
11232081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    oldset = obj->nodesetval;
11233081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    ctxt->context->node = NULL;
11234081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
11235081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    newlocset = xmlXPtrLocationSetCreate(NULL);
11236081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
11237081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    if (oldset != NULL) {
11238081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        for (i = 0; i < oldset->nodeNr; i++) {
11239081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            /*
11240081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             * Run the evaluation with a node list made of a single item
11241081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             * in the nodeset.
11242081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             */
11243081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            ctxt->context->node = oldset->nodeTab[i];
11244081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            tmp = xmlXPathNewNodeSet(ctxt->context->node);
11245081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            valuePush(ctxt, tmp);
11246081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
11247081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            if (op->ch2 != -1)
11248081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                total +=
11249081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                    xmlXPathCompOpEval(ctxt,
11250081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                                   &comp->steps[op->ch2]);
112512c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    if (ctxt->error != XPATH_EXPRESSION_OK) {
112522c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack				xmlXPathFreeObject(obj);
112532c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack				return(0);
112542c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    }
11255081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
11256081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            res = valuePop(ctxt);
11257081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            range =
11258081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                xmlXPtrNewRangeNodeObject(oldset->nodeTab[i],
11259081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                                      res);
11260081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            if (range != NULL) {
11261081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                xmlXPtrLocationSetAdd(newlocset, range);
11262081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            }
11263081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
11264081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            /*
11265081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             * Cleanup
11266081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             */
11267081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            if (res != NULL)
11268081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                xmlXPathFreeObject(res);
11269081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            if (ctxt->value == tmp) {
11270081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                res = valuePop(ctxt);
11271081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                xmlXPathFreeObject(res);
11272081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            }
11273081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
11274081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            ctxt->context->node = NULL;
11275081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        }
11276081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    }
11277f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
11278f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
11279f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
11280f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * The result is used as the new evaluation set.
11281f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
11282f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFreeObject(obj);
11283f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
11284f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->contextSize = -1;
11285f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->proximityPosition = -1;
11286081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
11287f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
11288f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
112899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
112909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
112919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlGenericError(xmlGenericErrorContext,
11292f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "XPath: unknown precompiled operation %d\n", op->op);
11293f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (total);
112949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
112959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1129656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1129756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard/**
1129856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * xmlXPathRunStreamEval:
1129956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @ctxt:  the XPath parser context with the compiled expression
1130056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
1130156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Evaluate the Precompiled Streamable XPath expression in the given context.
1130256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard */
1130356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardstatic xmlXPathObjectPtr
1130456de87ee0d147d04a041eb1ec95048566375bc3fDaniel VeillardxmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp) {
11305f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    int max_depth, min_depth;
1130697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    int from_root;
1130756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int ret, depth;
1130897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#ifdef XP_PATTERN_TO_ANY_NODE_ENABLED
1130997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    int eval_all_nodes;
1131097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#endif
1131112d37ab63441baf9e03db70168cc1d0d6f1c2373William M. Brack    xmlNodePtr cur = NULL, limit = NULL;
1131256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlXPathObjectPtr retval;
1131356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlStreamCtxtPtr patstream;
1131497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
1131597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    int nb_nodes = 0;
1131656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1131756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if ((ctxt == NULL) || (comp == NULL))
1131856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(NULL);
1131956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    max_depth = xmlPatternMaxDepth(comp);
1132056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (max_depth == -1)
1132156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(NULL);
1132256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (max_depth == -2)
1132356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        max_depth = 10000;
11324f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    min_depth = xmlPatternMinDepth(comp);
11325f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    if (min_depth == -1)
11326f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard        return(NULL);
1132756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    from_root = xmlPatternFromRoot(comp);
1132856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (from_root < 0)
1132956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(NULL);
11330fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#if 0
11331fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    printf("stream eval: depth %d from root %d\n", max_depth, from_root);
11332fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#endif
1133356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1133456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    retval = xmlXPathNewNodeSet(NULL);
1133556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (retval == NULL)
1133656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(NULL);
1133756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11338f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    /*
11339f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard     * handle the special cases of / amd . being matched
11340f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard     */
11341f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    if (min_depth == 0) {
11342f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	if (from_root) {
11343f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	    xmlXPathNodeSetAddUnique(retval->nodesetval, (xmlNodePtr) ctxt->doc);
11344f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	} else {
11345f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	    xmlXPathNodeSetAddUnique(retval->nodesetval, ctxt->node);
11346f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	}
11347f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    }
11348f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    if (max_depth == 0) {
1134956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	return(retval);
1135056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
11351f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard
1135256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (from_root) {
1135312d37ab63441baf9e03db70168cc1d0d6f1c2373William M. Brack        cur = (xmlNodePtr)ctxt->doc;
1135456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } else if (ctxt->node != NULL) {
1135556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        switch (ctxt->node->type) {
1135656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ELEMENT_NODE:
1135756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DOCUMENT_NODE:
1135856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DOCUMENT_FRAG_NODE:
1135956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_HTML_DOCUMENT_NODE:
1136056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
1136156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DOCB_DOCUMENT_NODE:
1136256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1136356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	        cur = ctxt->node;
1136456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		break;
1136556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ATTRIBUTE_NODE:
1136656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_TEXT_NODE:
1136756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_CDATA_SECTION_NODE:
1136856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ENTITY_REF_NODE:
1136956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ENTITY_NODE:
1137056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_PI_NODE:
1137156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_COMMENT_NODE:
1137256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_NOTATION_NODE:
1137356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DTD_NODE:
1137456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DOCUMENT_TYPE_NODE:
1137556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ELEMENT_DECL:
1137656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ATTRIBUTE_DECL:
1137756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ENTITY_DECL:
1137856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_NAMESPACE_DECL:
1137956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_XINCLUDE_START:
1138056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_XINCLUDE_END:
1138156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		break;
1138256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1138356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	limit = cur;
1138456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1138556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (cur == NULL)
1138656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(retval);
1138756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1138856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    patstream = xmlPatternGetStreamCtxt(comp);
1138956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (patstream == NULL) {
1139056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(retval);
1139156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1139256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1139397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#ifdef XP_PATTERN_TO_ANY_NODE_ENABLED
1139497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    eval_all_nodes = xmlStreamWantsAnyNode(patstream);
1139597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#endif
1139697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
1139756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (from_root) {
1139856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	ret = xmlStreamPush(patstream, NULL, NULL);
1139956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ret < 0) {
1140056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	} else if (ret == 1) {
1140156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    xmlXPathNodeSetAddUnique(retval->nodesetval, cur);
1140256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1140356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1140456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    depth = 0;
1140556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    goto scan_children;
1140656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardnext_node:
11407d3ff7ef6d3247872b1231718bdf1773c16d88806Daniel Veillard    do {
1140856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        nb_nodes++;
1140997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
1141097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	switch (cur->type) {
1141197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    case XML_ELEMENT_NODE:
1141297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#ifdef XP_PATTERN_TO_ANY_NODE_ENABLED
1141397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    case XML_TEXT_NODE:
1141497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    case XML_CDATA_SECTION_NODE:
1141597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    case XML_COMMENT_NODE:
1141697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    case XML_PI_NODE:
1141797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#endif
1141897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if (cur->type == XML_ELEMENT_NODE) {
1141997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    ret = xmlStreamPush(patstream, cur->name,
1142056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard				(cur->ns ? cur->ns->href : NULL));
11421fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack		}
1142297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#ifdef XP_PATTERN_TO_ANY_NODE_ENABLED
1142397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		else if (eval_all_nodes)
1142497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type);
1142597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		else
1142697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    break;
1142797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#endif
1142897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
1142997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if (ret < 0) {
1143097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    /* NOP. */
1143197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		} else if (ret == 1) {
1143297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    xmlXPathNodeSetAddUnique(retval->nodesetval, cur);
1143397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		}
1143497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if ((cur->children == NULL) || (depth >= max_depth)) {
1143597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    ret = xmlStreamPop(patstream);
1143697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    while (cur->next != NULL) {
1143797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			cur = cur->next;
1143897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			if ((cur->type != XML_ENTITY_DECL) &&
1143997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			    (cur->type != XML_DTD_NODE))
1144097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			    goto next_node;
1144197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    }
1144297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		}
1144397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    default:
1144497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		break;
1144597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	}
1144656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1144756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardscan_children:
1144856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if ((cur->children != NULL) && (depth < max_depth)) {
1144956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    /*
1145097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	     * Do not descend on entities declarations
1145156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	     */
1145256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (cur->children->type != XML_ENTITY_DECL) {
1145356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		cur = cur->children;
1145456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		depth++;
1145556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		/*
1145656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		 * Skip DTDs
1145756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		 */
1145856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		if (cur->type != XML_DTD_NODE)
1145956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    continue;
1146056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1146156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1146256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1146356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (cur == limit)
1146456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    break;
1146556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1146656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	while (cur->next != NULL) {
1146756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    cur = cur->next;
1146856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if ((cur->type != XML_ENTITY_DECL) &&
1146956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		(cur->type != XML_DTD_NODE))
1147056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		goto next_node;
1147156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1147256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1147356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	do {
1147456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    cur = cur->parent;
1147556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    depth--;
1147656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if ((cur == NULL) || (cur == limit))
1147756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	        goto done;
1147897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    if (cur->type == XML_ELEMENT_NODE) {
1147997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		ret = xmlStreamPop(patstream);
1148097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    }
1148197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#ifdef XP_PATTERN_TO_ANY_NODE_ENABLED
1148297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    else if ((eval_all_nodes) &&
1148397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		((cur->type == XML_TEXT_NODE) ||
1148497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		 (cur->type == XML_CDATA_SECTION_NODE) ||
1148597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		 (cur->type == XML_COMMENT_NODE) ||
1148697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		 (cur->type == XML_PI_NODE)))
1148797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    {
1148897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		ret = xmlStreamPop(patstream);
1148997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    }
1149097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#endif
1149156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (cur->next != NULL) {
1149256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		cur = cur->next;
1149356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		break;
1149456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1149556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	} while (cur != NULL);
1149656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1149756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } while ((cur != NULL) && (depth >= 0));
1149856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillarddone:
11499fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#if 0
11500fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    printf("stream eval: checked %d nodes selected %d\n",
11501fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard           nb_nodes, retval->nodesetval->nodeNr);
11502fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#endif
1150356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlFreeStreamCtxt(patstream);
1150456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    return(retval);
1150556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard}
1150656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif /* XPATH_STREAMING */
1150756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
115089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
115099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathRunEval:
115109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctxt:  the XPath parser context with the compiled expression
115119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
115129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Evaluate the Precompiled XPath expression in the given context.
115139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
11514fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardstatic void
115159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathRunEval(xmlXPathParserContextPtr ctxt) {
115169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprPtr comp;
115179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
115189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((ctxt == NULL) || (ctxt->comp == NULL))
115199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
115209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
115219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->valueTab == NULL) {
115229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	/* Allocate the value stack */
115239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueTab = (xmlXPathObjectPtr *)
115249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
115259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (ctxt->valueTab == NULL) {
11526d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathPErrMemory(ctxt, "creating evaluation context\n");
115279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlFree(ctxt);
115289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
115299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueNr = 0;
115309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueMax = 10;
115319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->value = NULL;
115329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
1153356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1153456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (ctxt->comp->stream) {
1153556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        xmlXPathObjectPtr ret;
1153656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        ret = xmlXPathRunStreamEval(ctxt->context, ctxt->comp->stream);
1153756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ret != NULL) {
1153856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    valuePush(ctxt, ret);
1153956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return;
1154056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1154156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1154256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
115439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp = ctxt->comp;
1154429b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin    if(comp->last < 0) {
1154529b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	xmlGenericError(xmlGenericErrorContext,
1154629b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	    "xmlXPathRunEval: last is less than zero\n");
1154729b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	return;
1154829b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin    }
115499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
115509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
115519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11552afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/************************************************************************
11553afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *									*
11554afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * 			Public interfaces				*
11555afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *									*
11556afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard ************************************************************************/
11557afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
11558afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
11559fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathEvalPredicate:
11560fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath context
11561fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @res:  the Predicate Expression evaluation result
11562fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
11563fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Evaluate a predicate result for the current node.
11564fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * A PredicateExpr is evaluated by evaluating the Expr and converting
11565fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * the result to a boolean. If the result is a number, the result will
11566fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * be converted to true if the number is equal to the position of the
11567fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * context node in the context node list (as returned by the position
11568fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * function) and will be converted to false otherwise; if the result
11569fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * is not a number, then the result will be converted as if by a call
11570fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * to the boolean function.
11571fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
11572cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if predicate is true, 0 otherwise
11573fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
11574fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardint
11575fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
11576ce682bc24b79f1dd29b781d4c17f9bf169ce7e32Daniel Veillard    if ((ctxt == NULL) || (res == NULL)) return(0);
11577fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    switch (res->type) {
11578fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_BOOLEAN:
11579fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->boolval);
11580fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_NUMBER:
11581fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->floatval == ctxt->proximityPosition);
11582fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_NODESET:
11583fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_XSLT_TREE:
11584d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    if (res->nodesetval == NULL)
11585d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		return(0);
11586fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->nodesetval->nodeNr != 0);
11587fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_STRING:
11588fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return((res->stringval != NULL) &&
11589fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	           (xmlStrlen(res->stringval) != 0));
11590fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        default:
11591fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    STRANGE
11592fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    }
11593fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    return(0);
11594fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard}
11595fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
11596fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
11597afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathEvaluatePredicateResult:
11598afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @ctxt:  the XPath Parser context
11599afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @res:  the Predicate Expression evaluation result
11600afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11601afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Evaluate a predicate result for the current node.
11602afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * A PredicateExpr is evaluated by evaluating the Expr and converting
11603afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * the result to a boolean. If the result is a number, the result will
11604afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * be converted to true if the number is equal to the position of the
11605afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * context node in the context node list (as returned by the position
11606afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * function) and will be converted to false otherwise; if the result
11607afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * is not a number, then the result will be converted as if by a call
11608afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * to the boolean function.
11609afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11610cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if predicate is true, 0 otherwise
11611afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
11612afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardint
11613afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
11614afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard                                xmlXPathObjectPtr res) {
11615ce682bc24b79f1dd29b781d4c17f9bf169ce7e32Daniel Veillard    if ((ctxt == NULL) || (res == NULL)) return(0);
11616afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    switch (res->type) {
11617afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_BOOLEAN:
11618afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->boolval);
11619afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_NUMBER:
116209ea6231ecef04c848b688355b8f7532dd5e4c6f8Daniel Veillard#if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200))
116217c4eb63bb01d754b17860cd7dc2ab2fef81f6a08Daniel Veillard	    return((res->floatval == ctxt->context->proximityPosition) &&
116227c4eb63bb01d754b17860cd7dc2ab2fef81f6a08Daniel Veillard	           (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/
116232582a338bff77569b5aadbba8f40e1f3862d090dDaniel Veillard#else
11624afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->floatval == ctxt->context->proximityPosition);
116252582a338bff77569b5aadbba8f40e1f3862d090dDaniel Veillard#endif
11626afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_NODESET:
11627afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_XSLT_TREE:
1162873639a73c5a51c3739595f54c338bb531c1319c2Daniel Veillard	    if (res->nodesetval == NULL)
11629911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		return(0);
11630afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->nodesetval->nodeNr != 0);
11631afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_STRING:
11632afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return((res->stringval != NULL) &&
11633afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	           (xmlStrlen(res->stringval) != 0));
11634081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack#ifdef LIBXML_XPTR_ENABLED
11635081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	case XPATH_LOCATIONSET:{
11636081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    xmlLocationSetPtr ptr = res->user;
11637081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    if (ptr == NULL)
11638081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	        return(0);
11639081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    return (ptr->locNr != 0);
11640081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    }
11641081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack#endif
11642afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        default:
11643afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    STRANGE
11644afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    }
11645afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    return(0);
11646afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
11647afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
1164856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1164956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard/**
1165056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * xmlXPathTryStreamCompile:
1165156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @ctxt: an XPath context
1165256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @str:  the XPath expression
1165356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
1165456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Try to compile the XPath expression as a streamable subset.
1165556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
1165656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Returns the compiled expression or NULL if failed to compile.
1165756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard */
1165856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardstatic xmlXPathCompExprPtr
1165956de87ee0d147d04a041eb1ec95048566375bc3fDaniel VeillardxmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
1166056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    /*
1166156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     * Optimization: use streaming patterns when the XPath expression can
1166256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     * be compiled to a stream lookup
1166356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     */
1166456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlPatternPtr stream;
1166556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlXPathCompExprPtr comp;
1166656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlDictPtr dict = NULL;
1166756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    const xmlChar **namespaces = NULL;
1166856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlNsPtr ns;
1166956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int i, j;
1167056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1167156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) &&
1167256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        (!xmlStrchr(str, '@'))) {
116731f33c4d61f3cc9820643ef726b373ec3044bcac3Daniel Veillard	const xmlChar *tmp;
116741f33c4d61f3cc9820643ef726b373ec3044bcac3Daniel Veillard
116751f33c4d61f3cc9820643ef726b373ec3044bcac3Daniel Veillard	/*
116766ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	 * We don't try to handle expressions using the verbose axis
116776ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	 * specifiers ("::"), just the simplied form at this point.
116786ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	 * Additionally, if there is no list of namespaces available and
116796ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	 *  there's a ":" in the expression, indicating a prefixed QName,
116806ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	 *  then we won't try to compile either. xmlPatterncompile() needs
116816ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	 *  to have a list of namespaces at compilation time in order to
116826ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	 *  compile prefixed name tests.
116831f33c4d61f3cc9820643ef726b373ec3044bcac3Daniel Veillard	 */
116841f33c4d61f3cc9820643ef726b373ec3044bcac3Daniel Veillard	tmp = xmlStrchr(str, ':');
116856ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	if ((tmp != NULL) &&
116866ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    ((ctxt == NULL) || (ctxt->nsNr == 0) || (tmp[1] == ':')))
116876ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    return(NULL);
116881f33c4d61f3cc9820643ef726b373ec3044bcac3Daniel Veillard
1168956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ctxt != NULL) {
1169056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    dict = ctxt->dict;
1169156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (ctxt->nsNr > 0) {
11692dbfe05aff4d242e31fcd7621a4901a6fa10b988eDaniel Veillard		namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*));
1169356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		if (namespaces == NULL) {
1169456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    xmlXPathErrMemory(ctxt, "allocating namespaces array\n");
1169556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    return(NULL);
1169656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		}
1169756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		for (i = 0, j = 0; (j < ctxt->nsNr); j++) {
1169856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    ns = ctxt->namespaces[j];
1169956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    namespaces[i++] = ns->href;
1170056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    namespaces[i++] = ns->prefix;
1170156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		}
1170256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		namespaces[i++] = NULL;
1170356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		namespaces[i++] = NULL;
1170456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1170556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1170656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11707ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH,
11708ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack			&namespaces[0]);
117096ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	if (namespaces != NULL) {
117106ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    xmlFree((xmlChar **)namespaces);
117116ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik 	}
1171256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) {
1171356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp = xmlXPathNewCompExpr();
1171456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (comp == NULL) {
1171556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		xmlXPathErrMemory(ctxt, "allocating streamable expression\n");
1171656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		return(NULL);
1171756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1171856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp->stream = stream;
1171956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp->dict = dict;
1172056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (comp->dict)
1172156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		xmlDictReference(comp->dict);
1172256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return(comp);
1172356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1172456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	xmlFreePattern(stream);
1172556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1172656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    return(NULL);
1172756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard}
1172856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif /* XPATH_STREAMING */
1172956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11730afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
117314773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * xmlXPathCtxtCompile:
117324773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * @ctxt: an XPath context
11733afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @str:  the XPath expression
11734afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11735afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an XPath expression
11736afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11737591b4be0fe1986b5e71d54c5c063493987ef4285Daniel Veillard * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
11738afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *         the caller has to free the object.
11739afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
11740afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompExprPtr
117414773df2a58be83e1b9b1b55840371acf37386820Daniel VeillardxmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
117424773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    xmlXPathParserContextPtr pctxt;
11743afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompExprPtr comp;
11744afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
1174556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1174656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    comp = xmlXPathTryStreamCompile(ctxt, str);
1174756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp != NULL)
1174856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(comp);
1174956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1175056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11751afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathInit();
11752afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
117534773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    pctxt = xmlXPathNewParserContext(str, ctxt);
117544773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    xmlXPathCompileExpr(pctxt);
11755ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard
117564773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if( pctxt->error != XPATH_EXPRESSION_OK )
11757ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard    {
117584773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        xmlXPathFreeParserContext(pctxt);
1175924505b0f5c872c5afb6da5093565e5a6e09ca541Daniel Veillard        return(NULL);
11760ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard    }
11761ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard
117624773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if (*pctxt->cur != 0) {
1176350fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	/*
1176450fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * aleksey: in some cases this line prints *second* error message
1176550fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * (see bug #78858) and probably this should be fixed.
1176650fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * However, we are not sure that all error messages are printed
1176750fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * out in other places. It's not critical so we leave it as-is for now
1176850fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 */
117694773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
1177040af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	comp = NULL;
1177140af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    } else {
117724773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	comp = pctxt->comp;
117734773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	pctxt->comp = NULL;
1177440af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    }
117754773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    xmlXPathFreeParserContext(pctxt);
11776f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (comp != NULL) {
11777ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard	comp->expr = xmlStrdup(str);
11778ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
11779f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->string = xmlStrdup(str);
11780f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->nb = 0;
11781f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
11782ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard    }
11783afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    return(comp);
11784afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
11785afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
117869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
117874773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * xmlXPathCompile:
117884773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * @str:  the XPath expression
117894773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard *
117904773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * Compile an XPath expression
117914773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard *
117924773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
117934773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard *         the caller has to free the object.
117944773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard */
117954773df2a58be83e1b9b1b55840371acf37386820Daniel VeillardxmlXPathCompExprPtr
117964773df2a58be83e1b9b1b55840371acf37386820Daniel VeillardxmlXPathCompile(const xmlChar *str) {
117974773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    return(xmlXPathCtxtCompile(NULL, str));
117984773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard}
117994773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard
118004773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard/**
118019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompiledEval:
118029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the compiled XPath expression
118039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctx:  the XPath context
118049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
118059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Evaluate the Precompiled XPath expression in the given context.
118069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
11807cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
118089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *         the caller has to free the object.
118099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
118109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathObjectPtr
118119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx) {
118129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathParserContextPtr ctxt;
118139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathObjectPtr res, tmp, init = NULL;
118149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int stack = 0;
118158146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
118168146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    static int reentance = 0;
118178146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
118189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11819f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    CHECK_CTXT(ctx)
11820f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack
11821f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    if (comp == NULL)
118229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
118239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathInit();
118249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
118258146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
118268146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    reentance++;
118278146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    if (reentance > 1)
118288146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard	xmlXPathDisableOptimizer = 1;
118298146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
118308146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard
11831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
11832f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp->nb++;
11833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((comp->string != NULL) && (comp->nb > 100)) {
11834f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	fprintf(stderr, "100 x %s\n", comp->string);
11835f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->nb = 0;
11836f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
11837f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
118389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt = xmlXPathCompParserContext(comp, ctx);
118399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathRunEval(ctxt);
118409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
118419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->value == NULL) {
118429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlGenericError(xmlGenericErrorContext,
11843cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompiledEval: evaluation failed\n");
118449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = NULL;
118459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    } else {
118469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = valuePop(ctxt);
118479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
118489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11849f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
118509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    do {
118519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        tmp = valuePop(ctxt);
118529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (tmp != NULL) {
118539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (tmp != init)
118549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		stack++;
118559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathFreeObject(tmp);
118569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        }
118579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    } while (tmp != NULL);
118589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((stack != 0) && (res != NULL)) {
118599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlGenericError(xmlGenericErrorContext,
11860cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompiledEval: %d object left on the stack\n",
118619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	        stack);
118629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
118639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->error != XPATH_EXPRESSION_OK) {
118649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathFreeObject(res);
118659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = NULL;
118669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
118679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
118689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11869afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    ctxt->comp = NULL;
118709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathFreeParserContext(ctxt);
118718146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
118728146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    reentance--;
118738146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
118749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(res);
118759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
118769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11877afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
11878afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathEvalExpr:
11879afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @ctxt:  the XPath Parser context
11880afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11881afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Parse and evaluate an XPath expression in the given context,
11882afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * then push the result on the context stack
11883afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
11884afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardvoid
11885afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
1188656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1188756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlXPathCompExprPtr comp;
1188856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1188956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11890a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
1189156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1189256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1189356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base);
1189456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp != NULL) {
1189556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        if (ctxt->comp != NULL)
1189656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    xmlXPathFreeCompExpr(ctxt->comp);
1189756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        ctxt->comp = comp;
1189856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ctxt->cur != NULL)
1189956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    while (*ctxt->cur != 0) ctxt->cur++;
1190056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } else
1190156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1190256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    {
1190356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	xmlXPathCompileExpr(ctxt);
1190456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1190550fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin    CHECK_ERROR;
11906afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathRunEval(ctxt);
11907afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
119089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
119093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
119103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEval:
119113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
119123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctx:  the XPath context
119133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
119143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Evaluate the XPath Location Path in the given context.
119153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
11916cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
119173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         the caller has to free the object.
119183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
119193473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
119203473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
119213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr ctxt;
119223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr res, tmp, init = NULL;
119233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int stack = 0;
119243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11925f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    CHECK_CTXT(ctx)
119263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11927f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    xmlXPathInit();
119283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
119293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt = xmlXPathNewParserContext(str, ctx);
119303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathEvalExpr(ctxt);
119313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
119323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->value == NULL) {
119333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
119343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEval: evaluation failed\n");
119353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
1193656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } else if ((*ctxt->cur != 0) && (ctxt->comp != NULL)
1193756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1193856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            && (ctxt->comp->stream == NULL)
1193956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1194056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	      ) {
119413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
119423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
119433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
119443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = valuePop(ctxt);
119453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
119463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
119473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
119483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        tmp = valuePop(ctxt);
119493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (tmp != NULL) {
119503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (tmp != init)
119513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		stack++;
119523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(tmp);
119533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
119543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (tmp != NULL);
119553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((stack != 0) && (res != NULL)) {
119563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
119573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEval: %d object left on the stack\n",
119583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        stack);
119593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
119603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->error != XPATH_EXPRESSION_OK) {
119613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(res);
119623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
119633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
119649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
119653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeParserContext(ctxt);
119663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(res);
119673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
119683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
119693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
119703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEvalExpression:
119713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
119723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
119733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
119743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Evaluate the XPath expression in the given context.
119753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
119763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
119773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         the caller has to free the object.
119783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
119793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
119803473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
119813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr pctxt;
119823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr res, tmp;
119833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int stack = 0;
119843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11985f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    CHECK_CTXT(ctxt)
119863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11987f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    xmlXPathInit();
119883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
119893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    pctxt = xmlXPathNewParserContext(str, ctxt);
119903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathEvalExpr(pctxt);
119913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
119923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*pctxt->cur != 0) {
119933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
119943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
119953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
119963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = valuePop(pctxt);
119973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
119983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
119993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        tmp = valuePop(pctxt);
120003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (tmp != NULL) {
120013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(tmp);
120023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    stack++;
120033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
120043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (tmp != NULL);
120053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((stack != 0) && (res != NULL)) {
120063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
120073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEvalExpression: %d object left on the stack\n",
120083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        stack);
120093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
120103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeParserContext(pctxt);
120113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(res);
120123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
120133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1201442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard/************************************************************************
1201542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *									*
1201642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *	Extra functions not pertaining to the XPath spec		*
1201742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *									*
1201842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard ************************************************************************/
1201942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard/**
1202042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * xmlXPathEscapeUriFunction:
1202142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * @ctxt:  the XPath Parser context
1202242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * @nargs:  the number of arguments
1202342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1202442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Implement the escape-uri() XPath function
1202542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *    string escape-uri(string $str, bool $escape-reserved)
1202642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1202742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * This function applies the URI escaping rules defined in section 2 of [RFC
1202842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * 2396] to the string supplied as $uri-part, which typically represents all
1202942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * or part of a URI. The effect of the function is to replace any special
1203042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * character in the string by an escape sequence of the form %xx%yy...,
1203142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * where xxyy... is the hexadecimal representation of the octets used to
1203242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * represent the character in UTF-8.
1203342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1203442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * The set of characters that are escaped depends on the setting of the
1203542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * boolean argument $escape-reserved.
1203642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1203742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * If $escape-reserved is true, all characters are escaped other than lower
1203842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * case letters a-z, upper case letters A-Z, digits 0-9, and the characters
1203942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!"
1204042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only
1204142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and
1204242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * A-F).
1204342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1204442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * If $escape-reserved is false, the behavior differs in that characters
1204542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * referred to in [RFC 2396] as reserved characters are not escaped. These
1204642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",".
1204742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1204842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * [RFC 2396] does not define whether escaped URIs should use lower case or
1204942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * upper case for hexadecimal digits. To ensure that escaped URIs can be
1205042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * compared using string comparison functions, this function must always use
1205142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * the upper-case letters A-F.
1205242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1205342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Generally, $escape-reserved should be set to true when escaping a string
1205442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * that is to form a single part of a URI, and to false when escaping an
1205542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * entire URI or URI reference.
1205642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1205742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * In the case of non-ascii characters, the string is encoded according to
1205842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * utf-8 and then converted according to RFC 2396.
1205942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1206042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Examples
1206142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), true())
1206242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%2FLos%20Angeles%23ocean"
1206342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), false())
1206442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles%23ocean"
1206542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1206642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard */
12067118aed78f360f51d182770e62b251ef324707aa2Daniel Veillardstatic void
1206842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel VeillardxmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1206942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathObjectPtr str;
1207042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    int escape_reserved;
1207142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlBufferPtr target;
1207242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlChar *cptr;
1207342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlChar escape[4];
1207442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1207542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    CHECK_ARITY(2);
1207642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1207742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape_reserved = xmlXPathPopBoolean(ctxt);
1207842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1207942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    CAST_TO_STRING;
1208042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    str = valuePop(ctxt);
1208142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1208242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    target = xmlBufferCreate();
1208342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1208442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape[0] = '%';
1208542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape[3] = 0;
1208642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1208742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    if (target) {
1208842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	for (cptr = str->stringval; *cptr; cptr++) {
1208942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    if ((*cptr >= 'A' && *cptr <= 'Z') ||
1209042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr >= 'a' && *cptr <= 'z') ||
1209142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr >= '0' && *cptr <= '9') ||
1209242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '-' || *cptr == '_' || *cptr == '.' ||
1209342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '!' || *cptr == '~' || *cptr == '*' ||
1209442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '\''|| *cptr == '(' || *cptr == ')' ||
1209542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr == '%' &&
1209642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 ((cptr[1] >= 'A' && cptr[1] <= 'F') ||
1209742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[1] >= 'a' && cptr[1] <= 'f') ||
1209842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[1] >= '0' && cptr[1] <= '9')) &&
1209942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 ((cptr[2] >= 'A' && cptr[2] <= 'F') ||
1210042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[2] >= 'a' && cptr[2] <= 'f') ||
1210142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[2] >= '0' && cptr[2] <= '9'))) ||
1210242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(!escape_reserved &&
1210342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 (*cptr == ';' || *cptr == '/' || *cptr == '?' ||
1210442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == ':' || *cptr == '@' || *cptr == '&' ||
1210542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == '=' || *cptr == '+' || *cptr == '$' ||
1210642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == ','))) {
1210742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		xmlBufferAdd(target, cptr, 1);
1210842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    } else {
1210942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		if ((*cptr >> 4) < 10)
1211042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[1] = '0' + (*cptr >> 4);
1211142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		else
1211242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[1] = 'A' - 10 + (*cptr >> 4);
1211342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		if ((*cptr & 0xF) < 10)
1211442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[2] = '0' + (*cptr & 0xF);
1211542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		else
1211642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[2] = 'A' - 10 + (*cptr & 0xF);
1211742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1211842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		xmlBufferAdd(target, &escape[0], 3);
1211942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    }
1212042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	}
1212142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    }
1212242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
1212342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlBufferFree(target);
1212442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathFreeObject(str);
1212542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard}
1212642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
121273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
121283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterAllFunctions:
121293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
121303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
121313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Registers all default XPath functions in this context
121323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
121333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
121343473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
121353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor{
121363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
121373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathBooleanFunction);
121383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
121393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathCeilingFunction);
121403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
121413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathCountFunction);
121423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
121433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathConcatFunction);
121443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
121453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathContainsFunction);
121463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
121473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathIdFunction);
121483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
121493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathFalseFunction);
121503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
121513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathFloorFunction);
121523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
121533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLastFunction);
121543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
121553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLangFunction);
121563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
121573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLocalNameFunction);
121583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
121593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNotFunction);
121603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
121613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNameFunction);
121623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
121633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNamespaceURIFunction);
121643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
121653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNormalizeFunction);
121663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
121673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNumberFunction);
121683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
121693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathPositionFunction);
121703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
121713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathRoundFunction);
121723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
121733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStringFunction);
121743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
121753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStringLengthFunction);
121763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
121773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStartsWithFunction);
121783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
121793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringFunction);
121803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
121813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringBeforeFunction);
121823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
121833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringAfterFunction);
121843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
121853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSumFunction);
121863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
121873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathTrueFunction);
121883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
121893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathTranslateFunction);
1219042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1219142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
1219242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
1219342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard                         xmlXPathEscapeUriFunction);
121943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
121953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
121963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* LIBXML_XPATH_ENABLED */
121975d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#define bottom_xpath
121985d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#include "elfgcchack.h"
12199