xpath.c revision 4432df239b7aba6bff86c838e0be11d08f283b76
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>
543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
554432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#if defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XPATH_ENABLED)
569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Floating point stuff				*
599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
62c0631a608f62902eca453096f0b2fc5b449b0b0aDaniel Veillard#ifndef TRIO_REPLACE_STDIO
63cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard#define TRIO_PUBLIC static
64c0631a608f62902eca453096f0b2fc5b449b0b0aDaniel Veillard#endif
65cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard#include "trionan.c"
66cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The lack of portability of this section of the libc is annoying !
693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathNAN = 0;
713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathPINF = 1;
723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathNINF = -1;
735fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillarddouble xmlXPathNZERO = 0;
7420ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillardstatic int xmlXPathInitialized = 0;
753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathInit:
783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initialize the XPath environment
803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
823473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathInit(void) {
8320ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    if (xmlXPathInitialized) return;
843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
85450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathPINF = trio_pinf();
86450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathNINF = trio_ninf();
87450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathNAN = trio_nan();
885fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    xmlXPathNZERO = trio_nzero();
893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9020ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    xmlXPathInitialized = 1;
913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
93cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard/**
94cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * xmlXPathIsNaN:
95cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * @val:  a double value
96cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
97cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Provides a portable isnan() function to detect whether a double
98cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * is a NotaNumber. Based on trio code
99cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * http://sourceforge.net/projects/ctrio/
100cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
101cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Returns 1 if the value is a NaN, 0 otherwise
102cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard */
103cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillardint
104cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel VeillardxmlXPathIsNaN(double val) {
105cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    return(trio_isnan(val));
106cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard}
107cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
108cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard/**
109cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * xmlXPathIsInf:
110cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * @val:  a double value
111cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
112cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Provides a portable isinf() function to detect whether a double
113cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * is a +Infinite or -Infinite. Based on trio code
114cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * http://sourceforge.net/projects/ctrio/
115cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
116cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise
117cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard */
118cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillardint
119cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel VeillardxmlXPathIsInf(double val) {
120cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    return(trio_isinf(val));
121cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard}
122cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
1234432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#endif /* SCHEMAS or XPATH */
1244432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#ifdef LIBXML_XPATH_ENABLED
1255fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard/**
1265fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * xmlXPathGetSign:
1275fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * @val:  a double value
1285fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard *
1295fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Provides a portable function to detect the sign of a double
1305fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Modified from trio code
1315fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * http://sourceforge.net/projects/ctrio/
1325fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard *
1335fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Returns 1 if the value is Negative, 0 if positive
1345fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard */
13521458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillardstatic int
1365fc1f0893af6ffe76453ac16817204a866bdeab2Daniel VeillardxmlXPathGetSign(double val) {
13721458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    return(trio_signbit(val));
1385fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard}
1395fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
1405fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
141d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/*
142d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * TODO: when compatibility allows remove all "fake node libxslt" strings
143d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard *       the test should just be name[0] = ' '
144d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard */
145d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG */
146d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_STEP */
147d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_STEP_NTH */
148d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_EXPR */
149d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_EVAL_COUNTS */
150d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard
151d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic xmlNs xmlXPathXMLNamespaceStruct = {
152d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    NULL,
153d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    XML_NAMESPACE_DECL,
154d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    XML_XML_NAMESPACE,
155d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    BAD_CAST "xml",
156d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    NULL
157d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard};
158d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
159d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard#ifndef LIBXML_THREAD_ENABLED
160d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/*
161d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * Optimizer is disabled only when threaded apps are detected while
162d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * the library ain't compiled for thread safety.
163d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard */
164d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic int xmlXPathDisableOptimizer = 0;
165d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard#endif
166d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard
1673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
1689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
1699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Parser Types					*
1709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
1719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
1729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/*
1749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Types are private:
1759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
1769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
1789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_END=0,
1799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_AND,
1809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_OR,
1819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_EQUAL,
1829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_CMP,
1839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_PLUS,
1849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_MULT,
1859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_UNION,
1869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_ROOT,
1879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_NODE,
1889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_RESET,
1899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_COLLECT,
1909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_VALUE,
1919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_VARIABLE,
1929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_FUNCTION,
1939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_ARG,
1949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_PREDICATE,
195d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    XPATH_OP_FILTER,
1969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_SORT
1979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#ifdef LIBXML_XPTR_ENABLED
1989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ,XPATH_OP_RANGETO
1999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif
2009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathOp;
2019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
2039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ANCESTOR = 1,
2049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ANCESTOR_OR_SELF,
2059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ATTRIBUTE,
2069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_CHILD,
2079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_DESCENDANT,
2089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_DESCENDANT_OR_SELF,
2099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_FOLLOWING,
2109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_FOLLOWING_SIBLING,
2119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_NAMESPACE,
2129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PARENT,
2139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PRECEDING,
2149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PRECEDING_SIBLING,
2159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_SELF
2169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathAxisVal;
2179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
2199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NONE = 0,
2209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_TYPE = 1,
2219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_PI = 2,
2229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_ALL = 3,
2239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NS = 4,
2249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NAME = 5
2259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathTestVal;
2269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
2289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_NODE = 0,
2299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_COMMENT = XML_COMMENT_NODE,
2309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_TEXT = XML_TEXT_NODE,
2319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_PI = XML_PI_NODE
2329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathTypeVal;
2339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef struct _xmlXPathStepOp xmlXPathStepOp;
2369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef xmlXPathStepOp *xmlXPathStepOpPtr;
2379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardstruct _xmlXPathStepOp {
2389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathOp op;
2399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int ch1;
2409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int ch2;
2419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value;
2429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value2;
2439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value3;
2449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    void *value4;
2459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    void *value5;
246e39a93d0d3df9907cf3538cd3f1fbbe4106e893dDaniel Veillard    void *cache;
24742596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard    void *cacheURI;
2489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard};
2499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardstruct _xmlXPathCompExpr {
2519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int nbStep;
2529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int maxStep;
2539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathStepOp *steps;        /* ops for computation */
2549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int last;
255118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    xmlChar *expr;
256f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
257f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int nb;
258f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlChar *string;
259f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
2609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard};
2619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
2639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
2649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Parser Type functions 				*
2659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
2669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
2679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
2699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathNewCompExpr:
2709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
2719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Create a new Xpath component
2729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
2739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error
2749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
27556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathCompExprPtr
2769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathNewCompExpr(void) {
2779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprPtr cur;
2789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
2799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
2809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (cur == NULL) {
2819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
2829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		"xmlXPathNewCompExpr : malloc failed\n");
2839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
2849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
2859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(cur, 0, sizeof(xmlXPathCompExpr));
2869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->maxStep = 10;
2879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->nbStep = 0;
2889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
2899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                                   sizeof(xmlXPathStepOp));
2909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (cur->steps == NULL) {
2919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
2929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		"xmlXPathNewCompExpr : malloc failed\n");
2939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(cur);
2949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
2959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
2969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
2979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->last = -1;
298f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
299f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    cur->nb = 0;
300f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
3019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(cur);
3029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
3039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
3059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathFreeCompExpr:
3069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  an XPATH comp
3079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
3089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Free up the memory allocated by @comp
3099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
3109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardvoid
311f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
312f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
3139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathStepOpPtr op;
3149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
3159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp == NULL)
317f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return;
318f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < comp->nbStep; i++) {
319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        op = &comp->steps[i];
320f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (op->value4 != NULL) {
321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->op == XPATH_OP_VALUE)
322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFreeObject(op->value4);
323f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else
324f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(op->value4);
325f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
326f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (op->value5 != NULL)
327f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlFree(op->value5);
3289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
3299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp->steps != NULL) {
330f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlFree(comp->steps);
3319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
332f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
333f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (comp->string != NULL) {
334f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlFree(comp->string);
335f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
336f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
337118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    if (comp->expr != NULL) {
338118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard        xmlFree(comp->expr);
339118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    }
340f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlFree(comp);
3429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
3439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
3459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompExprAdd:
3469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the compiled expression
3479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ch1: first child index
3489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ch2: second child index
3499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @op:  an op
3509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value:  the first int value
3519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value2:  the second int value
3529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value3:  the third int value
3539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value4:  the first string value
3549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value5:  the second string value
3559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
3569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Add an step to an XPath Compiled Expression
3579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
3589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns -1 in case of failure, the index otherwise
3599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
36056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
3619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
3629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard   xmlXPathOp op, int value,
3639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard   int value2, int value3, void *value4, void *value5) {
3649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp->nbStep >= comp->maxStep) {
3659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathStepOp *real;
3669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	comp->maxStep *= 2;
3689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
3699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		                      comp->maxStep * sizeof(xmlXPathStepOp));
3709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (real == NULL) {
3719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    comp->maxStep /= 2;
3729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlGenericError(xmlGenericErrorContext,
3739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    "xmlXPathCompExprAdd : realloc failed\n");
3749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    return(-1);
3759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
3769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	comp->steps = real;
3779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
3789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->last = comp->nbStep;
3799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].ch1 = ch1;
3809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].ch2 = ch2;
3819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].op = op;
3829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value = value;
3839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value2 = value2;
3849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value3 = value3;
3859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value4 = value4;
3869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value5 = value5;
387e39a93d0d3df9907cf3538cd3f1fbbe4106e893dDaniel Veillard    comp->steps[comp->nbStep].cache = NULL;
3889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(comp->nbStep++);
3899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
3909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
391f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
392f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompSwap:
393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @comp:  the compiled expression
394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op: operation index
395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Swaps 2 operations in the compiled expression
397f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic void
399f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompSwap(xmlXPathStepOpPtr op) {
400f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int tmp;
401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
402bc6f759ac9b41773e3643ad288b5214732051c98Daniel Veillard#ifndef LIBXML_THREAD_ENABLED
4038146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    /*
4048146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * Since this manipulates possibly shared variables, this is
4058146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * disable if one detects that the library is used in a multithreaded
4068146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * application
4078146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     */
4088146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    if (xmlXPathDisableOptimizer)
4098146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard	return;
4108146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
4118146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard
412f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    tmp = op->ch1;
413f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    op->ch1 = op->ch2;
414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    op->ch2 = tmp;
415f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
416f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
417d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5)	\
418d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathCompExprAdd(ctxt->comp, (op1), (op2),			\
419d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	                (op), (val), (val2), (val3), (val4), (val5))
4209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5)			\
4219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1,		\
4229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                (op), (val), (val2), (val3), (val4), (val5))
4239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_LEAVE_EXPR(op, val, val2) 					\
4259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
4269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_UNARY_EXPR(op, ch, val, val2) 				\
4289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
4299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) 			\
4319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op), (val), (val2), 0 ,NULL ,NULL)
4329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
4343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
4353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 		Debugging related functions				*
4363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
4373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
4383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define TODO 								\
4403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,				\
4413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "Unimplemented block at %s:%d\n",				\
4423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            __FILE__, __LINE__);
4433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define STRANGE 							\
4453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,				\
4463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "Internal error at %s:%d\n",				\
4473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            __FILE__, __LINE__);
4483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_DEBUG_ENABLED
45056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
45156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
4523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
4533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
4543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
4563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
4573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
4583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
4593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
4603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "Node is NULL !\n");
4613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
4623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur->type == XML_DOCUMENT_NODE) ||
4663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     (cur->type == XML_HTML_DOCUMENT_NODE)) {
4673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
4683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, " /\n");
4693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->type == XML_ATTRIBUTE_NODE)
4703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
4713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
4723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlDebugDumpOneNode(output, cur, depth);
4733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
47556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) {
476f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    xmlNodePtr tmp;
477f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    int i;
478f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    char shift[100];
479f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
480f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
481f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
482f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
483f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    if (cur == NULL) {
484f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, shift);
485f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, "Node is NULL !\n");
486f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	return;
487f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
488f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
489f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
490f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    while (cur != NULL) {
491f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	tmp = cur;
492f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	cur = cur->next;
493f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	xmlDebugDumpOneNode(output, tmp, depth);
494f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
495f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard}
4963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
49856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
4993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
5003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
5013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
5033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
5043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
5053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
5073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
5083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "NodeSet is NULL !\n");
5093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
5103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
513911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (cur != NULL) {
514911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
515911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < cur->nodeNr;i++) {
516911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    fprintf(output, shift);
517911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    fprintf(output, "%d", i + 1);
518911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
519911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
5203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
5223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
52456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) {
525f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    int i;
526f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    char shift[100];
527f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
528f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
529f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
530f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
531f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
532f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) {
533f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, shift);
534f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, "Value Tree is NULL !\n");
535f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	return;
536f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
537f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
538f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
539f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    fprintf(output, shift);
540f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    fprintf(output, "%d", i + 1);
541f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);
542f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard}
5433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(LIBXML_XPTR_ENABLED)
54456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
54556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
5463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
5473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
5483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
5503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
5513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
5523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
5543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
5553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "LocationSet is NULL !\n");
5563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
5573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->locNr;i++) {
5613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
5623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "%d : ", i + 1);
5633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1);
5643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
566017b108fcf16dbce05ca7ebd75763f3d888abb5fDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
5673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
568afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
569afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathDebugDumpObject:
570afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @output:  the FILE * to dump the output
571afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @cur:  the object to inspect
572afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @depth:  indentation level
573afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
574afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Dump the content of the object for debugging purposes
575afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
576afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardvoid
577afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
5783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
5793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
5803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
5823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
5833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
5843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fprintf(output, shift);
5863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
5883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "Object is empty (NULL)\n");
5893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
5903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(cur->type) {
5923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_UNDEFINED:
5933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is uninitialized\n");
5943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
5953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
5963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Node Set :\n");
5973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
5983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
5993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_XSLT_TREE:
6003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is an XSLT value tree :\n");
601f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	    xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth);
6023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
6043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Boolean : ");
6053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (cur->boolval) fprintf(output, "true\n");
6063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else fprintf(output, "false\n");
6073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
609cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	    switch (xmlXPathIsInf(cur->floatval)) {
610357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    case 1:
6115fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard		fprintf(output, "Object is a number : Infinity\n");
612357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		break;
613357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    case -1:
614357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		fprintf(output, "Object is a number : -Infinity\n");
615357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		break;
616357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    default:
617cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard		if (xmlXPathIsNaN(cur->floatval)) {
618357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		    fprintf(output, "Object is a number : NaN\n");
619d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		} else if (cur->floatval == 0 && xmlXPathGetSign(cur->floatval) != 0) {
620d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    fprintf(output, "Object is a number : 0\n");
621357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		} else {
622357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		    fprintf(output, "Object is a number : %0g\n", cur->floatval);
623357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		}
624357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    }
6253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
6273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a string : ");
6283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlDebugDumpString(output, cur->stringval);
6293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "\n");
6303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
6323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a point : index %d in node", cur->index);
6333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
6343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "\n");
6353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
6373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((cur->user2 == NULL) ||
6383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		((cur->user2 == cur->user) && (cur->index == cur->index2))) {
6393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "Object is a collapsed range :\n");
6403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
6413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index >= 0)
6423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index);
6433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
6443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
6453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
6463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else  {
6473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "Object is a range :\n");
6483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
6493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "From ");
6503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index >= 0)
6513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index);
6523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
6533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
6543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
6553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
6563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "To ");
6573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index2 >= 0)
6583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index2);
6593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
6603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2,
6613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
6623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "\n");
6633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
6643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
6663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(LIBXML_XPTR_ENABLED)
6673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Location Set:\n");
6683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpLocationSet(output,
6693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    (xmlLocationSetPtr) cur->user, depth);
6703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
6713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_USERS:
6733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is user defined\n");
6743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
6753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
6779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
67856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
67956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
6809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                     xmlXPathStepOpPtr op, int depth) {
6819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
6829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    char shift[100];
6839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
6859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
6869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
6879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, shift);
6899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op == NULL) {
6909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	fprintf(output, "Step is NULL\n");
6919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
6929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
6939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    switch (op->op) {
6949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_END:
6959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "END"); break;
6969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_AND:
6979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "AND"); break;
6989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_OR:
6999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "OR"); break;
7009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_EQUAL:
7019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value)
7029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "EQUAL =");
7039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
7049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "EQUAL !=");
7059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
7069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_CMP:
7079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value)
7089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "CMP <");
7099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
7109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "CMP >");
7119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (!op->value2)
7129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "=");
7139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
7149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_PLUS:
7159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value == 0)
7169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS -");
7179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 1)
7189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS +");
7199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 2)
7209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS unary -");
7219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 3)
7229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS unary - -");
7239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
7249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_MULT:
7259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value == 0)
7269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT *");
7279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 1)
7289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT div");
7299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
7309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT mod");
7319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
7329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_UNION:
7339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "UNION"); break;
7349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_ROOT:
7359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "ROOT"); break;
7369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_NODE:
7379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "NODE"); break;
7389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_RESET:
7399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "RESET"); break;
7409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_SORT:
7419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "SORT"); break;
7429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_COLLECT: {
74378637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathAxisVal axis = (xmlXPathAxisVal)op->value;
74478637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathTestVal test = (xmlXPathTestVal)op->value2;
74578637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathTypeVal type = (xmlXPathTypeVal)op->value3;
7469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value4;
7479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value5;
7489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
7499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "COLLECT ");
7509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (axis) {
7519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ANCESTOR:
7529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'ancestors' "); break;
7539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ANCESTOR_OR_SELF:
7549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'ancestors-or-self' "); break;
7559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ATTRIBUTE:
7569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'attributes' "); break;
7579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_CHILD:
7589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'child' "); break;
7599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_DESCENDANT:
7609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'descendant' "); break;
7619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_DESCENDANT_OR_SELF:
7629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'descendant-or-self' "); break;
7639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_FOLLOWING:
7649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'following' "); break;
7659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_FOLLOWING_SIBLING:
7669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'following-siblings' "); break;
7679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_NAMESPACE:
7689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'namespace' "); break;
7699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PARENT:
7709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'parent' "); break;
7719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PRECEDING:
7729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'preceding' "); break;
7739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PRECEDING_SIBLING:
7749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'preceding-sibling' "); break;
7759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_SELF:
7769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'self' "); break;
7779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
7789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (test) {
7799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NONE:
7809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'none' "); break;
7819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_TYPE:
7829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'type' "); break;
7839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_PI:
7849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'PI' "); break;
7859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_ALL:
7869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'all' "); break;
7879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NS:
7889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'namespace' "); break;
7899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NAME:
7909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'name' "); break;
7919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
7929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (type) {
7939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_NODE:
7949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'node' "); break;
7959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_COMMENT:
7969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'comment' "); break;
7979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_TEXT:
7989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'text' "); break;
7999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_PI:
8009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'PI' "); break;
8019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
8029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
8039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "%s:", prefix);
8049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (name != NULL)
805580ced8ee28ecd99374da9383897678e4ba6c358Daniel Veillard		fprintf(output, "%s", (const char *) name);
8069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
8079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        }
8099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_VALUE: {
8109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4;
8119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "ELEM ");
8139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathDebugDumpObject(output, object, 0);
8149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    goto finish;
8159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
8169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_VARIABLE: {
8179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value5;
8189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value4;
8199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
8219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "VARIABLE %s:%s", prefix, name);
8229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    else
8239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "VARIABLE %s", name);
8249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
8259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
8269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_FUNCTION: {
8279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    int nbargs = op->value;
8289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value5;
8299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value4;
8309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
8329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "FUNCTION %s:%s(%d args)",
8339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			prefix, name, nbargs);
8349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    else
8359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "FUNCTION %s(%d args)", name, nbargs);
8369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
8379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
8389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_ARG: fprintf(output, "ARG"); break;
8399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
840d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
841fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
842fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard        case XPATH_OP_RANGETO: fprintf(output, "RANGETO"); break;
843fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
8449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	default:
8459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        fprintf(output, "UNKNOWN %d\n", op->op); return;
8469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
8479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, "\n");
8489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardfinish:
8499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op->ch1 >= 0)
8509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1);
8519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op->ch2 >= 0)
8529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1);
8539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
85456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard
8555e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
8565e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathDebugDumpCompExpr:
8575e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @output:  the FILE * for the output
8585e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @comp:  the precompiled XPath expression
8595e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @depth:  the indentation level.
8605e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
8615e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Dumps the tree of the compiled XPath expression.
8625e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
86356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardvoid
86456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
86556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	                  int depth) {
8669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
8679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    char shift[100];
8689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
8709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
8719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
8729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, shift);
8749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp == NULL) {
8769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	fprintf(output, "Compiled Expression is NULL\n");
8779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
8789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
8799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, "Compiled Expression : %d elements\n",
8809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    comp->nbStep);
8819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    i = comp->last;
8829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
8839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
884017b108fcf16dbce05ca7ebd75763f3d888abb5fDaniel Veillard#endif /* LIBXML_DEBUG_ENABLED */
8853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
8873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
8883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 		Parser stacks related functions and macros		*
8893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
8903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
8913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8925e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
8935e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * valuePop:
8945e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @ctxt: an XPath evaluation context
8955e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
8965e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Pops the top XPath object from the value stack
8975e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
8985e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Returns the XPath object just removed
8995e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
9001c732d2e10935529b717864b6fa4296f80edace1Daniel Veillardextern xmlXPathObjectPtr
9011c732d2e10935529b717864b6fa4296f80edace1Daniel VeillardvaluePop(xmlXPathParserContextPtr ctxt)
9021c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard{
9031c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    xmlXPathObjectPtr ret;
9041c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard
9051c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    if (ctxt->valueNr <= 0)
9061c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        return (0);
9071c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->valueNr--;
9081c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    if (ctxt->valueNr > 0)
9091c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
9101c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    else
9111c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        ctxt->value = NULL;
9121c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ret = ctxt->valueTab[ctxt->valueNr];
9131c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->valueTab[ctxt->valueNr] = 0;
9141c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    return (ret);
9151c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard}
9165e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
9175e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * valuePush:
9185e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @ctxt:  an XPath evaluation context
9195e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @value:  the XPath object
9205e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
9215e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Pushes a new XPath object on top of the value stack
922cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *
923cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * returns the number of items on the value stack
9245e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
9251c732d2e10935529b717864b6fa4296f80edace1Daniel Veillardextern int
9261c732d2e10935529b717864b6fa4296f80edace1Daniel VeillardvaluePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
9271c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard{
9281c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    if (ctxt->valueNr >= ctxt->valueMax) {
9291c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        ctxt->valueMax *= 2;
9301c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        ctxt->valueTab =
9311c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard            (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
9321c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard                                             ctxt->valueMax *
9331c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard                                             sizeof(ctxt->valueTab[0]));
9341c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        if (ctxt->valueTab == NULL) {
9351c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
9361c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard            return (0);
9371c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        }
9381c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    }
9391c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->valueTab[ctxt->valueNr] = value;
9401c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->value = value;
9411c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    return (ctxt->valueNr++);
9421c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard}
9433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
944f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
945f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopBoolean:
946f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
947f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
948f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a boolean from the stack, handling conversion if needed.
949f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
950f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
951f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the boolean
952f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
953f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
954f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
955f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
956f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int ret;
957f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
958f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
959f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
960f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
961f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
962f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
963f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathCastToBoolean(obj);
964f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
965f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
966f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
967f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
968f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
969f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopNumber:
970f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
971f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
972f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a number from the stack, handling conversion if needed.
973f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
974f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
975f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the number
976f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
977f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerdouble
978f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
979f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
980f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    double ret;
981f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
982f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
983f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
984f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
985f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
986f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
987f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathCastToNumber(obj);
988f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
989f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
990f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
991f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
992f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
993f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopString:
994f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
995f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
996f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a string from the stack, handling conversion if needed.
997f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
998f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
999f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the string
1000f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1001f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlChar *
1002f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopString (xmlXPathParserContextPtr ctxt) {
1003f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1004f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlChar * ret;
1005f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1006f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1007f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
1008f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1009f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1010f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1011f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathCastToString(obj);
1012f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    /* TODO: needs refactoring somewhere else */
1013f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj->stringval == ret)
1014f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	obj->stringval = NULL;
1015f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1016f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1017f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1018f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1019f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1020f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopNodeSet:
1021f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1022f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1023f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a node-set from the stack, handling conversion if needed.
1024f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1025f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1026f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the node-set
1027f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1028f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
1029f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
1030f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1031f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
1032f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1033f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value == NULL) {
1034f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1035f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1036f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1037f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (!xmlXPathStackIsNodeSet(ctxt)) {
1038f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetTypeError(ctxt);
1039f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1040f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1041f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1042f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = obj->nodesetval;
10439deb242b558cbcff45165866e0634a1962404885Daniel Veillard    /* to fix memory leak of not clearing obj->user */
10449deb242b558cbcff45165866e0634a1962404885Daniel Veillard    if (obj->boolval && obj->user != NULL)
10459deb242b558cbcff45165866e0634a1962404885Daniel Veillard        xmlFreeNodeList((xmlNodePtr) obj->user);
1046f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeNodeSetList(obj);
1047f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1048f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1049f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1050f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1051f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopExternal:
1052f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1053f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1054cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Pops an external object from the stack, handling conversion if needed.
1055f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1056f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1057f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the object
1058f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1059f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyervoid *
1060f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
1061f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1062f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    void * ret;
1063f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1064f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value == NULL) {
1065f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1066f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1067f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1068f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value->type != XPATH_USERS) {
1069f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetTypeError(ctxt);
1070f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1071f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1072f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1073f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = obj->user;
1074f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1075f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1076f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1077f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
10783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
10793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Macros for accessing the content. Those should be used only by the parser,
10803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and not exported.
10813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
10823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Dirty macros, i.e. one need to make assumption on the context to use them
10833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
10843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CUR_PTR return the current pointer to the xmlChar to be parsed.
10853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CUR     returns the current xmlChar value, i.e. a 8 bit value
10863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           in ISO-Latin or UTF-8.
10873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           This should be used internally by the parser
10883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           only to compare to ASCII values otherwise it would break when
10893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           running with UTF-8 encoding.
10903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
10913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           to compare on ASCII based substring.
10923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
10933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           strings within the parser.
10943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CURRENT Returns the current char value, with the full decoding of
10953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           UTF-8 if we are using this mode. It returns an int.
10963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   NEXT    Skip to the next character, this does the proper decoding
10973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
10983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           It returns the pointer to the current xmlChar.
10993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
11003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CUR (*ctxt->cur)
11023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SKIP(val) ctxt->cur += (val)
11033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define NXT(val) ctxt->cur[(val)]
11043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CUR_PTR ctxt->cur
110561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
110661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
110761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define COPY_BUF(l,b,i,v)                                              \
110861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (l == 1) b[i++] = (xmlChar) v;                                  \
110961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    else i += xmlCopyChar(l,&b[i],v)
111061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
111161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define NEXTL(l)  ctxt->cur += l
11123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SKIP_BLANKS 							\
11143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (IS_BLANK(*(ctxt->cur))) NEXT
11153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CURRENT (*ctxt->cur)
11173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)
11183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1119e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1120e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#ifndef DBL_DIG
1121e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define DBL_DIG 16
1122e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#endif
1123e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#ifndef DBL_EPSILON
1124e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define DBL_EPSILON 1E-9
1125e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#endif
1126e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1127e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define UPPER_DOUBLE 1E9
1128e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define LOWER_DOUBLE 1E-5
1129e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1130e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define INTEGER_DIGITS DBL_DIG
1131e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define FRACTION_DIGITS (DBL_DIG + 1)
1132e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define EXPONENT_DIGITS (3 + 2)
1133e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1134e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese/**
1135e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * xmlXPathFormatNumber:
1136e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @number:     number to format
1137e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @buffer:     output buffer
1138e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @buffersize: size of output buffer
1139e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese *
1140e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * Convert the number into a string representation.
1141e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese */
1142e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reesestatic void
1143e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn ReesexmlXPathFormatNumber(double number, char buffer[], int buffersize)
1144e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese{
1145cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    switch (xmlXPathIsInf(number)) {
1146e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    case 1:
11475fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (buffersize > (int)sizeof("Infinity"))
114849cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "Infinity");
1149e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1150e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    case -1:
1151e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	if (buffersize > (int)sizeof("-Infinity"))
115249cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "-Infinity");
1153e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1154e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    default:
1155cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(number)) {
1156e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    if (buffersize > (int)sizeof("NaN"))
115749cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin		snprintf(buffer, buffersize, "NaN");
1158d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	} else if (number == 0 && xmlXPathGetSign(number) != 0) {
115949cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "0");
116028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	} else if (number == ((int) number)) {
116128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    char work[30];
116228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    char *ptr, *cur;
116328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    int res, value = (int) number;
116428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard
116528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard            ptr = &buffer[0];
116628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (value < 0) {
116728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr++ = '-';
116828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		value = -value;
116928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
117028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (value == 0) {
117128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr++ = '0';
117228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    } else {
117328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		cur = &work[0];
117428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		while (value != 0) {
117528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    res = value % 10;
117628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    value = value / 10;
117728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    *cur++ = '0' + res;
117828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		}
117928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		cur--;
118028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		while ((cur >= &work[0]) && (ptr - buffer < buffersize)) {
118128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    *ptr++ = *cur--;
118228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		}
118328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
118428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (ptr - buffer < buffersize) {
118528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr = 0;
118628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    } else if (buffersize > 0) {
118728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		ptr--;
118828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr = 0;
118928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
1190e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	} else {
119170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* 3 is sign, decimal point, and terminating zero */
119270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
119370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    int integer_place, fraction_place;
119470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char *ptr;
119570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char *after_fraction;
119670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    double absolute_value;
119770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    int size;
119870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
119970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    absolute_value = fabs(number);
120070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
120170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /*
120270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * First choose format - scientific or regular floating point.
120370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * In either case, result is in work, and after_fraction points
120470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * just past the fractional part.
120570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    */
120670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if ( ((absolute_value > UPPER_DOUBLE) ||
120770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		  (absolute_value < LOWER_DOUBLE)) &&
120870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		 (absolute_value != 0.0) ) {
120970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		/* Use scientific notation */
121070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
121170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		fraction_place = DBL_DIG - 1;
121270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		snprintf(work, sizeof(work),"%*.*e",
121370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese			 integer_place, fraction_place, number);
121470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		after_fraction = strchr(work + DBL_DIG, 'e');
1215e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    }
121670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    else {
121770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		/* Use regular notation */
121856f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		if (absolute_value > 0.0)
121956f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		    integer_place = 1 + (int)log10(absolute_value);
122056f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		else
1221a3067d19ec3a96fd6e7997753e27a5422a2856f7Daniel Veillard		    integer_place = 0;
122270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		fraction_place = (integer_place > 0)
122370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		    ? DBL_DIG - integer_place
122470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		    : DBL_DIG;
122570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		size = snprintf(work, sizeof(work), "%0.*f",
122670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese				fraction_place, number);
122770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		after_fraction = work + size;
1228e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    }
1229e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
123070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* Remove fractional trailing zeroes */
123170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    ptr = after_fraction;
123270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    while (*(--ptr) == '0')
123370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		;
123470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if (*ptr != '.')
123570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	        ptr++;
12365dd3c9622ab6a8e75870bc5351499155e7963abcDaniel Veillard	    while ((*ptr++ = *after_fraction++) != 0);
123770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
123870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* Finally copy result back to caller */
123970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    size = strlen(work) + 1;
124070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if (size > buffersize) {
124170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		work[buffersize - 1] = 0;
124270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		size = buffersize;
124370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    }
12445dd3c9622ab6a8e75870bc5351499155e7963abcDaniel Veillard	    memmove(buffer, work, size);
1245e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	}
1246e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1247e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    }
1248e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese}
1249e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
12503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
12513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
12523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Error handling routines				*
12533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
12543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
12553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1257b44025c72b7472971a061b022cfe422adc42715dDaniel Veillardstatic const char *xmlXPathErrorMessages[] = {
12583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Ok",
12593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Number encoding",
1260cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard    "Unfinished literal",
1261cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard    "Start of literal",
12623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Expected $ for variable reference",
12633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Undefined variable",
12643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid predicate",
12653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid expression",
12663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Missing closing curly brace",
12673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Unregistered function",
12683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid operand",
12693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid type",
12703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid number of arguments",
12713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid context size",
12723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Invalid context position",
12733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Memory allocation error",
12743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Syntax error",
12753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Resource error",
12763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    "Sub resource error",
127761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    "Undefined namespace prefix",
127861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    "Encoding error",
127961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    "Char out of XML range"
12803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor};
12813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
12835e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPatherror:
12843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
12853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @file:  the file name
12863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @line:  the line number
12873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @no:  the error number
12883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1289f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Formats an error message.
12903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
12913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
1292dda8f1ba9fb2e731e2dd6aa325ed07add7905ec3Daniel VeillardxmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED,
1293dda8f1ba9fb2e731e2dd6aa325ed07add7905ec3Daniel Veillard              int line ATTRIBUTE_UNUSED, int no) {
12943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int n;
12953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *cur;
12963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *base;
12973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
12983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = ctxt->cur;
12993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    base = ctxt->base;
1300118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    if ((cur == NULL) || (base == NULL)) {
1301118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	if ((ctxt->comp != NULL) && (ctxt->comp->expr != NULL)) {
1302118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	    xmlGenericError(xmlGenericErrorContext,
1303118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		    "XPath error %s in %s\n", xmlXPathErrorMessages[no],
1304118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			    ctxt->comp->expr);
1305118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	} else {
1306118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	    xmlGenericError(xmlGenericErrorContext,
1307118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		    "XPath error %s\n", xmlXPathErrorMessages[no]);
1308118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	}
1309118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard
1310d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	return;
1311118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    }
1312118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
1313118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	    "XPath error %s\n", xmlXPathErrorMessages[no]);
1314d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
13153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
13163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur--;
13173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = 0;
13193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((n++ < 80) && (cur > base) && (*cur != '\n') && (*cur != '\r'))
13203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur--;
13213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((*cur == '\n') || (*cur == '\r')) cur++;
13223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    base = cur;
13233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = 0;
13243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((*cur != 0) && (*cur != '\n') && (*cur != '\r') && (n < 79)) {
13253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext, "%c", (unsigned char) *cur++);
13263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	n++;
13273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext, "\n");
13293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = ctxt->cur;
13303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((*cur == '\n') || (*cur == '\r'))
13313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur--;
13323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = 0;
13333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((cur != base) && (n++ < 80)) {
13343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext, " ");
13353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        base++;
13363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,"^\n");
13383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
13423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
13433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle NodeSets			*
13443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
13453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
13463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1348e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * xmlXPathOrderDocElems:
1349e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * @doc:  an input document
1350e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *
1351e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * Call this routine to speed up XPath computation on static documents.
1352e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * This stamps all the element nodes with the document order
1353e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * Like for line information, the order is kept in the element->content
1354e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * field, the value stored is actually - the node number (startting at -1)
1355e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * to be able to differenciate from line numbers.
1356e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *
1357e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * Returns the number of element found in the document or -1 in case
1358e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *    of error.
1359e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard */
1360e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillardlong
1361e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel VeillardxmlXPathOrderDocElems(xmlDocPtr doc) {
1362e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    long count = 0;
1363e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    xmlNodePtr cur;
1364e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1365e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    if (doc == NULL)
1366e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	return(-1);
1367e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    cur = doc->children;
1368e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    while (cur != NULL) {
1369e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	if (cur->type == XML_ELEMENT_NODE) {
1370e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur->content = (void *) (-(++count));
1371e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur->children != NULL) {
1372e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = cur->children;
1373e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		continue;
1374e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1375e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	}
1376e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	if (cur->next != NULL) {
1377e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur = cur->next;
1378e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    continue;
1379e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	}
1380e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	do {
1381e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur = cur->parent;
1382e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur == NULL)
1383e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1384e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur == (xmlNodePtr) doc) {
1385e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = NULL;
1386e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1387e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1388e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur->next != NULL) {
1389e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = cur->next;
1390e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1391e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1392e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	} while (cur != NULL);
1393e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    }
1394e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    return(count);
1395e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard}
1396e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1397e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard/**
13983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCmpNodes:
13993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node1:  the first node
14003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node2:  the second node
14013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
14023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Compare two nodes w.r.t document order
14033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
14043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -2 in case of error 1 if first point < second point, 0 if
14053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         that's the same node, -1 otherwise
14063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
14073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
14083473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
14093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int depth1, depth2;
1410edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    int attr1 = 0, attr2 = 0;
14113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodePtr cur, root;
14123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((node1 == NULL) || (node2 == NULL))
14143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-2);
14153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
14163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * a couple of optimizations which will avoid computations in most cases
14173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1418edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node1->type == XML_ATTRIBUTE_NODE) {
1419edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	attr1 = 1;
1420edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	node1 = node1->parent;
1421edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1422edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node2->type == XML_ATTRIBUTE_NODE) {
1423edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	attr2 = 1;
1424edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	node2 = node2->parent;
1425edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1426edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node1 == node2) {
1427edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	if (attr1 == attr2)
1428edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	    return(0);
1429edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	if (attr2 == 1)
1430edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	    return(1);
1431edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	return(-1);
1432edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1433b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard    if ((node1->type == XML_NAMESPACE_DECL) ||
1434b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard        (node2->type == XML_NAMESPACE_DECL))
1435b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard	return(1);
14363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->prev)
14373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
14383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->next)
14393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
14403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
1442e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard     * Speedup using document order if availble.
14437216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard     */
14447216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    if ((node1->type == XML_ELEMENT_NODE) &&
14457216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	(node2->type == XML_ELEMENT_NODE) &&
1446e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(0 > (long) node1->content) &&
1447e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(0 > (long) node2->content) &&
1448e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(node1->doc == node2->doc)) {
1449e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	long l1, l2;
1450e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1451e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	l1 = -((long) node1->content);
1452e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	l2 = -((long) node2->content);
14537216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	if (l1 < l2)
14547216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	    return(1);
14557216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	if (l1 > l2)
14567216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	    return(-1);
14577216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    }
1458e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
14597216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    /*
14603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * compute depth to root
14613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
14623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
14633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node1)
14643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(1);
14653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth2++;
14663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    root = cur;
14683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
14693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node2)
14703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-1);
14713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth1++;
14723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
14743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Distinct document (or distinct entities :-( ) case.
14753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
14763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (root != cur) {
14773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-2);
14783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
14803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * get the nearest common ancestor.
14813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
14823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (depth1 > depth2) {
14833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth1--;
14843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node1 = node1->parent;
14853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (depth2 > depth1) {
14873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth2--;
14883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node2 = node2->parent;
14893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (node1->parent != node2->parent) {
14913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node1 = node1->parent;
14923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node2 = node2->parent;
14933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* should not happen but just in case ... */
14943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((node1 == NULL) || (node2 == NULL))
14953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-2);
14963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
14973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
14983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Find who's first.
14993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
15003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->next)
15013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
15023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (cur = node1->next;cur != NULL;cur = cur->next)
15033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node2)
15043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(1);
15053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(-1); /* assume there is no sibling list corruption */
15063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
15073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
15093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetSort:
15103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @set:  the node set
15113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
15123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Sort the node set in document order
15133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
15143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
15153473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetSort(xmlNodeSetPtr set) {
1516e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    int i, j, incr, len;
15173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodePtr tmp;
15183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (set == NULL)
15203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
15213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Use Shell's sort to sort the node-set */
15233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    len = set->nodeNr;
15243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (incr = len / 2; incr > 0; incr /= 2) {
15253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (i = incr; i < len; i++) {
15263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    j = i - incr;
15273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (j >= 0) {
1528e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese		if (xmlXPathCmpNodes(set->nodeTab[j],
1529e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese				     set->nodeTab[j + incr]) == -1) {
15303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    tmp = set->nodeTab[j];
15313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    set->nodeTab[j] = set->nodeTab[j + incr];
15323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    set->nodeTab[j + incr] = tmp;
15333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    j -= incr;
15343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else
15353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
15363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
15373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
15383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
15393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
15403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NODESET_DEFAULT	10
15423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1543044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetDupNs:
1544044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @node:  the parent node of the namespace XPath node
1545044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  the libxml namespace declaration node.
1546044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1547044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Namespace node in libxml don't match the XPath semantic. In a node set
1548044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * the namespace nodes are duplicated and the next pointer is set to the
1549044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * parent node in the XPath semantic.
1550044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1551044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Returns the newly created object.
1552044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
1553044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillardstatic xmlNodePtr
1554044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
1555044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    xmlNsPtr cur;
1556044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1557044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
1558044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return(NULL);
1559044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1560044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return((xmlNodePtr) ns);
1561044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1562044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1563044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * Allocate a new Namespace and fill the fields.
1564044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1565044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1566044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (cur == NULL) {
1567044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
1568044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		"xmlXPathNodeSetDupNs : malloc failed\n");
1569044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return(NULL);
1570044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1571044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    memset(cur, 0, sizeof(xmlNs));
1572044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->type = XML_NAMESPACE_DECL;
1573044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (ns->href != NULL)
1574044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->href = xmlStrdup(ns->href);
1575044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (ns->prefix != NULL)
1576044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->prefix = xmlStrdup(ns->prefix);
1577044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->next = (xmlNsPtr) node;
1578044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    return((xmlNodePtr) cur);
1579044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1580044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1581044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
1582044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetFreeNs:
1583044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  the XPath namespace node found in a nodeset.
1584044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1585044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Namespace node in libxml don't match the XPath semantic. In a node set
1586044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * the namespace nodes are duplicated and the next pointer is set to the
1587044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * parent node in the XPath semantic. Check if such a node need to be freed
1588044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
1589f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Saninvoid
1590044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetFreeNs(xmlNsPtr ns) {
1591044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
1592044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return;
1593044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1594044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) {
1595044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (ns->href != NULL)
1596044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlFree((xmlChar *)ns->href);
1597044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (ns->prefix != NULL)
1598044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlFree((xmlChar *)ns->prefix);
1599044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlFree(ns);
1600044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1601044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1602044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1603044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
16043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetCreate:
16053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an initial xmlNodePtr, or NULL
16063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
16073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlNodeSetPtr of type double and of value @val
16083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
16093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
16103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
16113473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodeSetPtr
16123473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetCreate(xmlNodePtr val) {
16133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ret;
16143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
16163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
16173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
1618cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathNodeSetCreate: out of memory\n");
16193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
16203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlNodeSet));
16223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val != NULL) {
16233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
16243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
16253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret->nodeTab == NULL) {
16263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
1627cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		    "xmlXPathNodeSetCreate: out of memory\n");
16283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
16293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
16303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(ret->nodeTab, 0 ,
16313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
16323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret->nodeMax = XML_NODESET_DEFAULT;
1633044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (val->type == XML_NAMESPACE_DECL) {
1634044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val;
1635044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1636044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    ret->nodeTab[ret->nodeNr++] =
1637044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1638044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	} else
1639044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    ret->nodeTab[ret->nodeNr++] = val;
16403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
16423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
16433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1645f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeSetContains:
1646f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @cur:  the node-set
1647f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @val:  the node
1648f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1649f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * checks whether @cur contains @val
1650f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1651f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns true (1) if @cur contains @val, false (0) otherwise
1652f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1653f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
1654f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
1655f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i;
1656f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1657044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
1658044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0; i < cur->nodeNr; i++) {
1659044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) {
1660044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns1, ns2;
1661044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1662044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns1 = (xmlNsPtr) val;
1663044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns2 = (xmlNsPtr) cur->nodeTab[i];
1664044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if (ns1 == ns2)
1665044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return(1);
1666044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns1->next != NULL) && (ns2->next == ns1->next) &&
1667044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	            (xmlStrEqual(ns1->prefix, ns2->prefix)))
1668044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return(1);
1669044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
1670044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1671044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else {
1672044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0; i < cur->nodeNr; i++) {
1673044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (cur->nodeTab[i] == val)
1674044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		return(1);
1675044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1676f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1677f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(0);
1678f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1679f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1680f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1681044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetAddNs:
1682044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @cur:  the initial node set
1683044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @node:  the hosting node
1684044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  a the namespace node
1685044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1686044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * add a new namespace node to an existing NodeSet
1687044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
168879376ba94845db7096c3917f4f40baeb450eb0e9Aleksey Saninvoid
1689044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
1690044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    int i;
1691044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1692044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (node == NULL) || (ns->type != XML_NAMESPACE_DECL) ||
1693044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(node->type != XML_ELEMENT_NODE))
1694044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return;
1695044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1696044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
1697044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1698044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * check against doublons
1699044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1700044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    for (i = 0;i < cur->nodeNr;i++) {
1701044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        if ((cur->nodeTab[i] != NULL) &&
1702044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
1703c62a147963b5839fc815267706eaec381f90ca16Daniel Veillard	    (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
1704044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
1705044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1706044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1707044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1708044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1709044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * grow the nodeTab if needed
1710044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1711044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (cur->nodeMax == 0) {
1712044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
1713044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					     sizeof(xmlNodePtr));
1714044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (cur->nodeTab == NULL) {
1715044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlGenericError(xmlGenericErrorContext,
1716044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    "xmlXPathNodeSetAdd: out of memory\n");
1717044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1718044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1719044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	memset(cur->nodeTab, 0 ,
1720044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
1721044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeMax = XML_NODESET_DEFAULT;
1722044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else if (cur->nodeNr == cur->nodeMax) {
1723044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        xmlNodePtr *temp;
1724044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1725044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeMax *= 2;
1726044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
1727044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				      sizeof(xmlNodePtr));
1728044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (temp == NULL) {
1729044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlGenericError(xmlGenericErrorContext,
1730044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    "xmlXPathNodeSetAdd: out of memory\n");
1731044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1732044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1733044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab = temp;
1734044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1735044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
1736044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1737044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1738044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
17393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetAdd:
17403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
17413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  a new xmlNodePtr
17423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1743cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * add a new xmlNodePtr to an existing NodeSet
17443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
17453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
17463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
17473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
17483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL) return;
17503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1751ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#if 0
1752652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard    if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
1753652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	return;	/* an XSLT fake node */
1754ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#endif
1755652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard
1756044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
17573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
17583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * check against doublons
17593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
17603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->nodeNr;i++)
17613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->nodeTab[i] == val) return;
17623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
17643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * grow the nodeTab if needed
17653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
17663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->nodeMax == 0) {
17673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
17683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
17693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->nodeTab == NULL) {
17703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
17713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathNodeSetAdd: out of memory\n");
17723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
17733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
17743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(cur->nodeTab, 0 ,
17753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
17763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax = XML_NODESET_DEFAULT;
17773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->nodeNr == cur->nodeMax) {
17783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNodePtr *temp;
17793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax *= 2;
17813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
17823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				      sizeof(xmlNodePtr));
17833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (temp == NULL) {
17843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
17853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathNodeSetAdd: out of memory\n");
17863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
17873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
17883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->nodeTab = temp;
17893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1790044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
1791044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlNsPtr ns = (xmlNsPtr) val;
1792044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1793044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] =
1794044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1795044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else
1796044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] = val;
17973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
17983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
18003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetAddUnique:
18013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
18023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  a new xmlNodePtr
18033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1804cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * add a new xmlNodePtr to an existing NodeSet, optimized version
18053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * when we are sure the node is not already in the set.
18063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
18073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
18083473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
18093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL) return;
18103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1811ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#if 0
1812652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard    if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
1813652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	return;	/* an XSLT fake node */
1814ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#endif
1815652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard
1816044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
18173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
18183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * grow the nodeTab if needed
18193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
18203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->nodeMax == 0) {
18213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
18223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
18233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->nodeTab == NULL) {
18243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
18253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathNodeSetAddUnique: out of memory\n");
18263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
18273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
18283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(cur->nodeTab, 0 ,
18293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
18303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax = XML_NODESET_DEFAULT;
18313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->nodeNr == cur->nodeMax) {
18323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNodePtr *temp;
18333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax *= 2;
18353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
18363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				      sizeof(xmlNodePtr));
18373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (temp == NULL) {
18383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
18393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathNodeSetAddUnique: out of memory\n");
18403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
18413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
18423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->nodeTab = temp;
18433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1844044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
1845044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlNsPtr ns = (xmlNsPtr) val;
1846044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1847044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] =
1848044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1849044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else
1850044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] = val;
18513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
18523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
18543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetMerge:
18553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val1:  the first NodeSet or NULL
18563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val2:  the second NodeSet
18573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
18583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Merges two nodesets, all nodes from @val2 are added to @val1
18593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if @val1 is NULL, a new set is created and copied from @val2
18603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1861cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns @val1 once extended or NULL in case of error.
18623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
18633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodeSetPtr
18643473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
1865d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    int i, j, initNr, skip;
18663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val2 == NULL) return(val1);
18683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val1 == NULL) {
18693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	val1 = xmlXPathNodeSetCreate(NULL);
18703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
18713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1872044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
18733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    initNr = val1->nodeNr;
18743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < val2->nodeNr;i++) {
18763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
18773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * check against doublons
18783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
1879d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	skip = 0;
1880d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	for (j = 0; j < initNr; j++) {
1881d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    if (val1->nodeTab[j] == val2->nodeTab[i]) {
1882d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		skip = 1;
1883d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		break;
1884044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    } else if ((val1->nodeTab[j]->type == XML_NAMESPACE_DECL) &&
1885044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		       (val2->nodeTab[i]->type == XML_NAMESPACE_DECL)) {
1886044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns1, ns2;
1887044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns1 = (xmlNsPtr) val1->nodeTab[j];
1888044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns2 = (xmlNsPtr) val2->nodeTab[i];
1889044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns1->next == ns2->next) &&
1890044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (xmlStrEqual(ns1->prefix, ns2->prefix))) {
1891044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    skip = 1;
1892044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    break;
1893044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		}
1894d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    }
1895d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	}
1896d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	if (skip)
1897d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    continue;
18983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
19003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * grow the nodeTab if needed
19013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
19023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (val1->nodeMax == 0) {
19033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
19043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor						    sizeof(xmlNodePtr));
19053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (val1->nodeTab == NULL) {
19063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlGenericError(xmlGenericErrorContext,
19073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"xmlXPathNodeSetMerge: out of memory\n");
19083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
19093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
19103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    memset(val1->nodeTab, 0 ,
19113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
19123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeMax = XML_NODESET_DEFAULT;
19133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (val1->nodeNr == val1->nodeMax) {
19143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNodePtr *temp;
19153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeMax *= 2;
19173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
19183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
19193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (temp == NULL) {
19203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlGenericError(xmlGenericErrorContext,
19213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"xmlXPathNodeSetMerge: out of memory\n");
19223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
19233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
19243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeTab = temp;
19253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1926044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
1927044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
1928044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1929044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    val1->nodeTab[val1->nodeNr++] =
1930044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1931044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	} else
1932044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
19333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(val1);
19363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
19373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
193975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * xmlXPathNodeSetMergeUnique:
194075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * @val1:  the first NodeSet or NULL
194175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * @val2:  the second NodeSet
194275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard *
194375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * Merges two nodesets, all nodes from @val2 are added to @val1
194475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * if @val1 is NULL, a new set is created and copied from @val2
194575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard *
194675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * Returns @val1 once extended or NULL in case of error.
194775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard */
194875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillardstatic xmlNodeSetPtr
194975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel VeillardxmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
195078637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    int i;
195175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
195275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    if (val2 == NULL) return(val1);
195375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    if (val1 == NULL) {
195475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	val1 = xmlXPathNodeSetCreate(NULL);
195575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    }
195675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
195775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
195875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
195975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    for (i = 0;i < val2->nodeNr;i++) {
196075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	/*
196175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	 * grow the nodeTab if needed
196275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	 */
196375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	if (val1->nodeMax == 0) {
196475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
196575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard						    sizeof(xmlNodePtr));
196675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    if (val1->nodeTab == NULL) {
196775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		xmlGenericError(xmlGenericErrorContext,
196875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard				"xmlXPathNodeSetMerge: out of memory\n");
196975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		return(NULL);
197075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    }
197175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    memset(val1->nodeTab, 0 ,
197275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
197375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeMax = XML_NODESET_DEFAULT;
197475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	} else if (val1->nodeNr == val1->nodeMax) {
197575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    xmlNodePtr *temp;
197675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
197775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeMax *= 2;
197875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
197975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard					     sizeof(xmlNodePtr));
198075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    if (temp == NULL) {
198175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		xmlGenericError(xmlGenericErrorContext,
198275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard				"xmlXPathNodeSetMerge: out of memory\n");
198375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		return(NULL);
198475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    }
198575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab = temp;
198675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	}
198775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
198875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
198975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
199075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab[val1->nodeNr++] =
199175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
199275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	} else
199375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
199475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    }
199575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
199675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    return(val1);
199775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard}
199875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
199975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard/**
20003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetDel:
20013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
20023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an xmlNodePtr
20033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Removes an xmlNodePtr from an existing NodeSet
20053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
20063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
20073473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
20083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
20093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return;
20113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL) return;
20123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
20143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * check against doublons
20153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
20163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->nodeNr;i++)
20173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->nodeTab[i] == val) break;
20183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (i >= cur->nodeNr) {
20203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG
20213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
20223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
20233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		val->name);
20243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
20253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return;
20263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2027044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((cur->nodeTab[i] != NULL) &&
2028044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(cur->nodeTab[i]->type == XML_NAMESPACE_DECL))
2029044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]);
20303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeNr--;
20313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (;i < cur->nodeNr;i++)
20323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab[i] = cur->nodeTab[i + 1];
20333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeTab[cur->nodeNr] = NULL;
20343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
20353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
20373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetRemove:
20383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
20393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the index to remove
20403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Removes an entry from an existing NodeSet list.
20423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
20433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
20443473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) {
20453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return;
20463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val >= cur->nodeNr) return;
2047044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((cur->nodeTab[val] != NULL) &&
2048044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(cur->nodeTab[val]->type == XML_NAMESPACE_DECL))
2049044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]);
20503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeNr--;
20513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (;val < cur->nodeNr;val++)
20523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab[val] = cur->nodeTab[val + 1];
20533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeTab[cur->nodeNr] = NULL;
20543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
20553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
20573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeNodeSet:
20583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
20593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free the NodeSet compound (not the actual nodes !).
20613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
20623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
20633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
20643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
20653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab != NULL) {
2066044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	int i;
2067044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2068044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	/* @@ with_ns to check wether namespace nodes should be looked at @@ */
2069044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0;i < obj->nodeNr;i++)
2070044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if ((obj->nodeTab[i] != NULL) &&
2071044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		(obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
2072044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
20733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(obj->nodeTab);
20743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
20763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
20773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
20793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeValueTree:
20803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
20813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free the NodeSet compound and the actual tree, this is different
20833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * from xmlXPathFreeNodeSet()
20843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
208556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
20863473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeValueTree(xmlNodeSetPtr obj) {
20873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
20883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
20903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab != NULL) {
2092044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0;i < obj->nodeNr;i++) {
2093044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (obj->nodeTab[i] != NULL) {
2094044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if (obj->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2095044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
2096044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		} else {
2097044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    xmlFreeNodeList(obj->nodeTab[i]);
2098044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		}
2099044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
2100044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
21013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(obj->nodeTab);
21023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
21043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(DEBUG) || defined(DEBUG_STEP)
21073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
21083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlGenericErrorContextNodeSet:
21093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @output:  a FILE * for the output
21103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
21113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Quick display of a NodeSet
21133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
21143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
21153473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) {
21163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
21173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (output == NULL) output = xmlGenericErrorContext;
21193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL)  {
21203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "NodeSet == NULL !\n");
21213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
21223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeNr == 0) {
21243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "NodeSet is empty\n");
21253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
21263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab == NULL) {
21283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, " nodeTab == NULL !\n");
21293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
21303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0; i < obj->nodeNr; i++) {
21323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (obj->nodeTab[i] == NULL) {
21333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " NULL !\n");
21343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
21353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
21363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) ||
21373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE))
21383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " /");
21393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (obj->nodeTab[i]->name == NULL)
21403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " noname!");
21413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else fprintf(output, " %s", obj->nodeTab[i]->name);
21423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fprintf(output, "\n");
21443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
21463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
21483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewNodeSet:
21493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
21503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type NodeSet and initialize
21523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the single Node @val
21533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
21553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
21563473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
21573473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewNodeSet(xmlNodePtr val) {
21583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
21593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
21613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
21623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
21633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewNodeSet: out of memory\n");
21643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
21653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
21673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NODESET;
216877851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard    ret->boolval = 0;
21693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = xmlXPathNodeSetCreate(val);
2170044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /* @@ with_ns to check wether namespace nodes should be looked at @@ */
21713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
21723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
21753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewValueTree:
21763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
21773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize
21793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the tree root @val
21803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
21823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
21833473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
21843473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewValueTree(xmlNodePtr val) {
21853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
21863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
21883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
21893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
21903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewNodeSet: out of memory\n");
21913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
21923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
21943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_XSLT_TREE;
21950ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    ret->boolval = 1;
21960ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    ret->user = (void *) val;
21973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = xmlXPathNodeSetCreate(val);
21983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
21993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
22023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewNodeSetList:
22033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an existing NodeSet
22043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type NodeSet and initialize
22063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the Nodeset @val
22073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
22093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
22103473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
2211044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNewNodeSetList(xmlNodeSetPtr val)
2212044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard{
22133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
22143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
22153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL)
2217044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = NULL;
22183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (val->nodeTab == NULL)
2219044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = xmlXPathNewNodeSet(NULL);
2220044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    else {
2221044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = xmlXPathNewNodeSet(val->nodeTab[0]);
2222044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        for (i = 1; i < val->nodeNr; ++i)
2223044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard            xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]);
2224044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
22253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2226044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    return (ret);
22273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
22303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathWrapNodeSet:
22313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
22323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Wrap the Nodeset @val in a new xmlXPathObjectPtr
22343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
22363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
22373473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
22383473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathWrapNodeSet(xmlNodeSetPtr val) {
22393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
22403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
22423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
22433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
22443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathWrapNodeSet: out of memory\n");
22453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
22463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
22473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
22483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NODESET;
22493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = val;
22503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
22513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
22543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeNodeSetList:
22553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  an existing NodeSetList object
22563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
22583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the list contrary to xmlXPathFreeObject().
22593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
22603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
22613473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
22623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
22633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
22643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2266f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2267f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDifference:
2268f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2269f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2270f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2271f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets difference() function:
2272f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:difference (node-set, node-set)
2273f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2274f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the difference between the two node sets, or nodes1 if
2275f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         nodes2 is empty
2276f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2277f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2278f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2279f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2280f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l1;
2281f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2282f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2283f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2284f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2285f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2286f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2287f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2288f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2289f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2290f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l1 = xmlXPathNodeSetGetLength(nodes1);
2291f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2292f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l1; i++) {
2293f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2294f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (!xmlXPathNodeSetContains(nodes2, cur))
2295f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2296f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2297f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2298f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2299f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2300f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2301f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathIntersection:
2302f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2303f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2304f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2305f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets intersection() function:
2306f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:intersection (node-set, node-set)
2307f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2308f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a node set comprising the nodes that are within both the
2309f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         node sets passed as arguments
2310f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2311f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2312f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2313f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
2314f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l1;
2315f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2316f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2317f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2318f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2319f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2320f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2321f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2322f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l1 = xmlXPathNodeSetGetLength(nodes1);
2323f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2324f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l1; i++) {
2325f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2326f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlXPathNodeSetContains(nodes2, cur))
2327f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2328f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2329f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2330f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2331f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2332f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2333f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDistinctSorted:
2334f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set, sorted by document order
2335f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2336f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets distinct() function:
2337f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:distinct (node-set)
2338f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2339f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a subset of the nodes contained in @nodes, or @nodes if
2340f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         it is empty
2341f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2342f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2343f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
2344f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2345f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlHashTablePtr hash;
2346f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2347f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlChar * strval;
2348f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2349f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2350f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes))
2351f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2352f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2353f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2354f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2355f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    hash = xmlHashCreate (l);
2356f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2357f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2358f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	strval = xmlXPathCastNodeToString(cur);
2359f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlHashLookup(hash, strval) == NULL) {
2360f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlHashAddEntry(hash, strval, strval);
2361f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2362f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	} else {
2363f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlFree(strval);
2364f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	}
2365f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2366f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlHashFree(hash, (xmlHashDeallocator) xmlFree);
2367f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2368f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2369f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2370f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2371f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDistinct:
2372f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2373f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2374f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets distinct() function:
2375f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:distinct (node-set)
2376f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #exslSetsDistinctSorted
2377f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called with the sorted node-set
2378f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2379f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a subset of the nodes contained in @nodes, or @nodes if
2380f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         it is empty
2381f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2382f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2383f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDistinct (xmlNodeSetPtr nodes) {
2384f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes))
2385f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2386f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2387f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2388f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathDistinctSorted(nodes));
2389f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2390f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2391f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2392f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathHasSameNodes:
2393f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2394f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2395f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2396f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets has-same-nodes function:
2397f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    boolean set:has-same-node(node-set, node-set)
2398f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2399f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
2400f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         otherwise
2401f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2402f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
2403f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2404f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2405f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2406f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2407f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1) ||
2408f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetIsEmpty(nodes2))
2409f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
2410f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2411f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes1);
2412f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2413f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2414f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlXPathNodeSetContains(nodes2, cur))
2415f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    return(1);
2416f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2417f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(0);
2418f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2419f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2420f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2421f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeLeadingSorted:
2422f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes: a node-set, sorted by document order
2423f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node: a node
2424f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2425f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2426f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2427f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2428f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that precede @node in document order,
2429f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2430f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2431f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2432f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2433f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
2434f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2435f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2436f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2437f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2438f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (node == NULL)
2439f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2440f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2441f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2442f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes) ||
2443f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	(!xmlXPathNodeSetContains(nodes, node)))
2444f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2445f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2446f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2447f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2448f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2449f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (cur == node)
2450f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    break;
2451f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetAddUnique(ret, cur);
2452f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2453f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2454f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2455f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2456f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2457f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeLeading:
2458f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2459f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node:  a node
2460f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2461f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2462f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2463f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
2464f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called.
2465f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2466f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that precede @node in document order,
2467f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2468f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2469f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2470f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2471f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
2472f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2473f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes, node));
2474f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2475f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2476f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2477f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathLeadingSorted:
2478f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set, sorted by document order
2479f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set, sorted by document order
2480f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2481f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2482f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2483f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2484f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that precede the first node in @nodes2
2485f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2486f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2487f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2488f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2489f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2490f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2491f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2492f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes1,
2493f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				     xmlXPathNodeSetItem(nodes2, 1)));
2494f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2495f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2496f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2497f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathLeading:
2498f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2499f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2500f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2501f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2502f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2503f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1 and @nodes2 are sorted by document order, then
2504f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * #exslSetsLeadingSorted is called.
2505f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2506f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that precede the first node in @nodes2
2507f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2508f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2509f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2510f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2511f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2512f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2513f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2514f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2515f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(xmlXPathNodeSetCreate(NULL));
2516f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes1);
2517f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes2);
2518f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes1,
2519f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				     xmlXPathNodeSetItem(nodes2, 1)));
2520f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2521f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2522f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2523f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeTrailingSorted:
2524f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes: a node-set, sorted by document order
2525f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node: a node
2526f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2527f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2528f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2529f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2530f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that follow @node in document order,
2531f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2532f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2533f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2534f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2535f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
2536f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2537f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2538f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2539f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2540f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (node == NULL)
2541f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2542f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2543f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2544f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes) ||
2545f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	(!xmlXPathNodeSetContains(nodes, node)))
2546f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2547f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2548f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2549f186c8259ae985cd56b3e14c1def484ab127fd14Thomas Broyer    for (i = l; i > 0; i--) {
2550f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2551f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (cur == node)
2552f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    break;
2553f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetAddUnique(ret, cur);
2554f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2555f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2556f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2557f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2558f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2559f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeTrailing:
2560f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2561f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node:  a node
2562f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2563f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2564f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2565f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
2566f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called.
2567f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2568f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that follow @node in document order,
2569f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2570f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2571f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2572f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2573f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
2574f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2575f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes, node));
2576f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2577f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2578f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2579f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathTrailingSorted:
2580f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set, sorted by document order
2581f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set, sorted by document order
2582f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2583f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2584f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2585f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2586f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that follow the first node in @nodes2
2587f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2588f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2589f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2590f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2591f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2592f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2593f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2594f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes1,
2595f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				      xmlXPathNodeSetItem(nodes2, 0)));
2596f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2597f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2598f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2599f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathTrailing:
2600f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2601f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2602f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2603f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2604f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2605f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1 and @nodes2 are sorted by document order, then
2606f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * #xmlXPathTrailingSorted is called.
2607f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2608f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that follow the first node in @nodes2
2609f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2610f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2611f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2612f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2613f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2614f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2615f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2616f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2617f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(xmlXPathNodeSetCreate(NULL));
2618f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes1);
2619f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes2);
2620f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes1,
2621f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				      xmlXPathNodeSetItem(nodes2, 0)));
2622f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2623f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
26243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
26253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
26263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle extra functions			*
26273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
26283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
26293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterFunc:
26323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
26333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
26343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the function implementation or NULL
26353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new function. If @f is NULL it unregisters the function
26373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
26393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
26413473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
26423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		     xmlXPathFunction f) {
26433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f));
26443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
26473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterFuncNS:
26483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
26493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
26503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the function namespace URI
26513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the function implementation or NULL
26523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new function. If @f is NULL it unregisters the function
26543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
26563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
26573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
26583473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
26593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		       const xmlChar *ns_uri, xmlXPathFunction f) {
26603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
26613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
26623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
26633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
26643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->funcHash == NULL)
26663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->funcHash = xmlHashCreate(0);
26673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->funcHash == NULL)
26683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
26693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f));
26703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
26713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
26723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
2673ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * xmlXPathRegisterFuncLookup:
2674ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * @ctxt:  the XPath context
2675ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * @f:  the lookup function
2676cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @funcCtxt:  the lookup data
2677ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer *
2678cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Registers an external mechanism to do function lookup.
2679ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer */
2680ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyervoid
2681ba4ad3263bf7f5625329f115367e0c7018521a16Thomas BroyerxmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
2682ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer			    xmlXPathFuncLookupFunc f,
2683ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer			    void *funcCtxt) {
2684ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt == NULL)
2685ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return;
2686ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    ctxt->funcLookupFunc = (void *) f;
2687ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    ctxt->funcLookupData = funcCtxt;
2688ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer}
2689ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2690ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer/**
26913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFunctionLookup:
26923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
26933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
26943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Function array of the context for the given
26963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * function.
26973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
26983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathFunction or NULL if not found
26993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27003473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunction
27013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
2702ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt == NULL)
2703ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return (NULL);
2704ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2705ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcLookupFunc != NULL) {
2706ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	xmlXPathFunction ret;
270799e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	xmlXPathFuncLookupFunc f;
2708ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
270999e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	f = (xmlXPathFuncLookupFunc) ctxt->funcLookupFunc;
2710963d2ae41574066f9b44bcae610dd280c1e57dd8Daniel Veillard	ret = f(ctxt->funcLookupData, name, NULL);
2711ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	if (ret != NULL)
2712ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	    return(ret);
2713ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    }
27143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
27153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFunctionLookupNS:
27193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
27213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the function namespace URI
27223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Function array of the context for the given
27243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * function.
27253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathFunction or NULL if not found
27273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27283473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunction
27293473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
27303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 const xmlChar *ns_uri) {
27313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
27323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
27333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
27343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
27353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2736ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcLookupFunc != NULL) {
2737ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	xmlXPathFunction ret;
273899e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	xmlXPathFuncLookupFunc f;
2739ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
274099e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	f = (xmlXPathFuncLookupFunc) ctxt->funcLookupFunc;
2741963d2ae41574066f9b44bcae610dd280c1e57dd8Daniel Veillard	ret = f(ctxt->funcLookupData, name, ns_uri);
2742ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	if (ret != NULL)
2743ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	    return(ret);
2744ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    }
2745ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2746ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcHash == NULL)
2747ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return(NULL);
2748ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
27493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri));
27503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisteredFuncsCleanup:
27543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered functions
27573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
27593473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
27603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
27613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
27623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlHashFree(ctxt->funcHash, NULL);
27643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->funcHash = NULL;
27653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
27683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
27693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle Variable			*
27703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
27713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
27723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariable:
27753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
27773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @value:  the variable value or NULL
27783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new variable value. If @value is NULL it unregisters
27803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the variable
27813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
27833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
27843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
27853473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
27863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 xmlXPathObjectPtr value) {
27873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value));
27883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
27893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariableNS:
27923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
27943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the variable namespace URI
27953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @value:  the variable value or NULL
27963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new variable value. If @value is NULL it unregisters
27983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the variable
27993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
28013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
28033473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name,
28043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   const xmlChar *ns_uri,
28053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   xmlXPathObjectPtr value) {
28063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
28083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
28093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
28103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
28123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->varHash = xmlHashCreate(0);
28133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
28143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
28153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
28163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			       (void *) value,
28173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			       (xmlHashDeallocator)xmlXPathFreeObject));
28183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariableLookup:
28223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the lookup function
28243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @data:  the lookup data
28253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * register an external mechanism to do variable lookup
28273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
28293473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
28303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 xmlXPathVariableLookupFunc f, void *data) {
28313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
28333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varLookupFunc = (void *) f;
28343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varLookupData = data;
28353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathVariableLookup:
28393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
28413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Variable array of the context for the given
28433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * variable value.
28443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
284573c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * Returns a copy of the value or NULL if not found
28463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28473473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
28483473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
28493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
28513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varLookupFunc != NULL) {
28533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathObjectPtr ret;
28543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
28563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        (ctxt->varLookupData, name, NULL);
2857556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	return(ret);
28583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
28593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathVariableLookupNS(ctxt, name, NULL));
28603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathVariableLookupNS:
28643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
28663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the variable namespace URI
28673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Variable array of the context for the given
286973c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * variable value.
28703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
287173c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * Returns the a copy of the value or NULL if not found
28723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28733473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
28743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
28753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 const xmlChar *ns_uri) {
28763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
28783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varLookupFunc != NULL) {
28803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathObjectPtr ret;
28813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
28833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        (ctxt->varLookupData, name, ns_uri);
28843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret != NULL) return(ret);
28853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
28863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
28883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
28893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
28903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
28913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28928c357d58c2d1dde022b67393a47dcb52100ce129Daniel Veillard    return(xmlXPathObjectCopy((xmlXPathObjectPtr)
28938c357d58c2d1dde022b67393a47dcb52100ce129Daniel Veillard		xmlHashLookup2(ctxt->varHash, name, ns_uri)));
28943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisteredVariablesCleanup:
28983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered variables
29013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
29033473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
29043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
29053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
29063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
290776d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard    xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject);
29083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varHash = NULL;
29093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterNs:
29133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
29143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  the namespace prefix
29153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the namespace name
29163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new namespace. If @ns_uri is NULL it unregisters
29183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the namespace
29193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
29213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
29233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
29243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   const xmlChar *ns_uri) {
29253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
29263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
29273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
29283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
29293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->nsHash == NULL)
29313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->nsHash = xmlHashCreate(10);
29323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->nsHash == NULL)
29333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
293442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri),
29353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			      (xmlHashDeallocator)xmlFree));
29363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNsLookup:
29403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
29413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  the namespace prefix value
29423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the namespace declaration array of the context for the given
29443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace name associated to the given prefix
29453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the value or NULL if not found
29473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorconst xmlChar *
29493473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
29503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
29513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
29523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
29533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
29543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef XML_XML_NAMESPACE
29563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
29573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(XML_XML_NAMESPACE);
29583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
29593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2960c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard    if (ctxt->namespaces != NULL) {
2961c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	int i;
2962c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard
2963c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	for (i = 0;i < ctxt->nsNr;i++) {
2964c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	    if ((ctxt->namespaces[i] != NULL) &&
2965c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard		(xmlStrEqual(ctxt->namespaces[i]->prefix, prefix)))
2966c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard		return(ctxt->namespaces[i]->href);
2967c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	}
2968c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard    }
29693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
29713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29745e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathRegisteredNsCleanup:
29753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
29763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered variables
29783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
29803473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
29813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
29823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
29833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
298442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlHashFree(ctxt->nsHash, (xmlHashDeallocator)xmlFree);
29853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->nsHash = NULL;
29863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
29893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
29903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle Values			*
29913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
29923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
29933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/* Allocations are terrible, one need to optimize all this !!! */
29953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewFloat:
29983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the double value
29993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type double and of value @val
30013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
30033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
30043473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
30053473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewFloat(double val) {
30063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
30073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
30093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
30103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
30113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewFloat: out of memory\n");
30123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
30143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
30153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NUMBER;
30163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->floatval = val;
30173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
30183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
30193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
30213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewBoolean:
30223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the boolean value
30233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type boolean and of value @val
30253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
30273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
30283473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
30293473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewBoolean(int val) {
30303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
30313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
30333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
30343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
30353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewBoolean: out of memory\n");
30363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
30383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
30393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_BOOLEAN;
30403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->boolval = (val != 0);
30413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
30423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
30433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
30453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewString:
30463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the xmlChar * value
30473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type string and of value @val
30493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
30513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
30523473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
30533473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewString(const xmlChar *val) {
30543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
30553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
30573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
30583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
30593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewString: out of memory\n");
30603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
30623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
30633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_STRING;
30643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val != NULL)
30653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret->stringval = xmlStrdup(val);
30663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
30673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret->stringval = xmlStrdup((const xmlChar *)"");
30683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
30693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
30703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3072ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathWrapString:
3073ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  the xmlChar * value
3074ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3075ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Wraps the @val string into an XPath object.
3076ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3077ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the newly created object.
3078ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3079ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3080ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathWrapString (xmlChar *val) {
3081ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3082ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3083ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3084ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (ret == NULL) {
3085ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        xmlGenericError(xmlGenericErrorContext,
3086ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		"xmlXPathWrapString: out of memory\n");
3087ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(NULL);
3088ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3089ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
3090ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret->type = XPATH_STRING;
3091ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret->stringval = val;
3092ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3093ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3094ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3095ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
30963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewCString:
30973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the char * value
30983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type string and of value @val
31003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
31023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31033473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
31043473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewCString(const char *val) {
31053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
31063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
31083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
31093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
31103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewCString: out of memory\n");
31113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
31123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
31133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
31143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_STRING;
31153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->stringval = xmlStrdup(BAD_CAST val);
31163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
31173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3120ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathWrapCString:
3121ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  the char * value
3122ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3123ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Wraps a string into an XPath object.
3124ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3125ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the newly created object.
3126ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3127ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3128ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathWrapCString (char * val) {
3129ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathWrapString((xmlChar *)(val)));
3130ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3131ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3132ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3133f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathWrapExternal:
3134f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @val:  the user data
3135f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3136f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Wraps the @val data into an XPath object.
3137f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3138f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the newly created object.
3139f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
3140f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathObjectPtr
3141f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathWrapExternal (void *val) {
3142f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr ret;
3143f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3144f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3145f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ret == NULL) {
3146f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer        xmlGenericError(xmlGenericErrorContext,
3147cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathWrapExternal: out of memory\n");
3148f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
3149f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
3150f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
3151f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret->type = XPATH_USERS;
3152f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret->user = val;
3153f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
3154f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
3155f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3156f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
31573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathObjectCopy:
31583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the original object
31593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * allocate a new copy of a given object
31613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
31633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31643473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
31653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectCopy(xmlXPathObjectPtr val) {
31663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
31673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL)
31693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
31703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
31723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
31733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
31743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathObjectCopy: out of memory\n");
31753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
31763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
31773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memcpy(ret, val , (size_t) sizeof(xmlXPathObject));
31783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (val->type) {
31793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_BOOLEAN:
31803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_NUMBER:
31813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
31823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
31833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
31843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_STRING:
31853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->stringval = xmlStrdup(val->stringval);
31863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
31873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_XSLT_TREE:
31883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((val->nodesetval != NULL) &&
31890ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard		(val->nodesetval->nodeTab != NULL)) {
31909adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		xmlNodePtr cur, tmp;
31919adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		xmlDocPtr top;
3192ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard
31930ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard		ret->boolval = 1;
31949adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		top =  xmlNewDoc(NULL);
31959adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		top->name = (char *)
31969adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    xmlStrdup(val->nodesetval->nodeTab[0]->name);
3197ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		ret->user = top;
3198ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		if (top != NULL) {
31999adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    top->doc = top;
3200ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    cur = val->nodesetval->nodeTab[0]->children;
3201ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    while (cur != NULL) {
32029adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard			tmp = xmlDocCopyNode(cur, top, 1);
32039adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard			xmlAddChild((xmlNodePtr) top, tmp);
3204ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard			cur = cur->next;
3205ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    }
3206ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		}
32079adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		ret->nodesetval = xmlXPathNodeSetCreate((xmlNodePtr) top);
32080ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    } else
32093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret->nodesetval = xmlXPathNodeSetCreate(NULL);
32100ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    /* Deallocate the copied tree value */
32113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
32123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_NODESET:
32133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
32140ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    /* Do not deallocate the copied tree value */
32150ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    ret->boolval = 0;
32163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
32173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
32183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
32193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	{
32203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlLocationSetPtr loc = val->user;
32213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc);
32223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
32233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
32243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
322547334c09f4373e4cff71334e60a623fee73a525fThomas Broyer        case XPATH_USERS:
322647334c09f4373e4cff71334e60a623fee73a525fThomas Broyer	    ret->user = val->user;
322747334c09f4373e4cff71334e60a623fee73a525fThomas Broyer	    break;
322847334c09f4373e4cff71334e60a623fee73a525fThomas Broyer        case XPATH_UNDEFINED:
32293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
32303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathObjectCopy: unsupported type %d\n",
32313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    val->type);
32323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
32333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
32343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
32353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
32383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeObject:
32393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the object to free
32403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathObjectPtr object.
32423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
32433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
32443473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeObject(xmlXPathObjectPtr obj) {
32453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
32460ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
324777851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	if (obj->boolval) {
32480ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    if (obj->user != NULL) {
32490ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard                xmlXPathFreeNodeSet(obj->nodesetval);
325038bf6f042507c6051bfa2db5cc9b6666cfc35c2aDaniel Veillard		xmlFreeNodeList((xmlNodePtr) obj->user);
32510ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    } else if (obj->nodesetval != NULL)
325277851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard		xmlXPathFreeValueTree(obj->nodesetval);
325377851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	} else {
325477851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	    if (obj->nodesetval != NULL)
325577851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard		xmlXPathFreeNodeSet(obj->nodesetval);
325677851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	}
32573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
32583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (obj->type == XPATH_LOCATIONSET) {
32593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (obj->user != NULL)
32603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPtrFreeLocationSet(obj->user);
32613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
32623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (obj->type == XPATH_STRING) {
32633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (obj->stringval != NULL)
32643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(obj->stringval);
32653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
32663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
32683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3270ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3271ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/************************************************************************
3272ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *									*
3273ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *			Type Casting Routines				*
3274ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *									*
3275ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard ************************************************************************/
3276ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3277ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3278ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastBooleanToString:
3279ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a boolean
3280ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3281ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a boolean to its string value.
3282ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3283ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3284ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3285ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3286ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastBooleanToString (int val) {
3287ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret;
3288ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val)
3289ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "true");
3290ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    else
3291ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "false");
3292ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3293ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3294ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3295ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3296ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNumberToString:
3297ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a number
3298ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3299ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a number to its string value.
3300ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3301ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3302ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3303ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3304ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNumberToString (double val) {
3305ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret;
3306cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    switch (xmlXPathIsInf(val)) {
3307ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case 1:
33085fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	ret = xmlStrdup((const xmlChar *) "Infinity");
3309ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3310ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case -1:
3311ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "-Infinity");
3312ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3313ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    default:
3314cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(val)) {
3315ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "NaN");
3316d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	} else if (val == 0 && xmlXPathGetSign(val) != 0) {
3317d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "0");
3318ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	} else {
3319ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    /* could be improved */
3320ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    char buf[100];
3321ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlXPathFormatNumber(val, buf, 100);
3322ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) buf);
3323ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	}
3324ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3325ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3326ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3327ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3328ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3329ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeToString:
3330ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @node:  a node
3331ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3332ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node to its string value.
3333ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3334ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3335ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3336ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3337ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeToString (xmlNodePtr node) {
3338ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlNodeGetContent(node));
3339ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3340ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3341ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3342ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToString:
3343ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3344ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3345ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its string value.
3346ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3347ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3348ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3349ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3350ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
3351ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
3352ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlStrdup((const xmlChar *) ""));
3353ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3354ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathNodeSetSort(ns);
3355ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathCastNodeToString(ns->nodeTab[0]));
3356ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3357ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3358ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3359ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastToString:
3360ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3361ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3362ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its string() equivalent
3363ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3364ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the string value of the object, NULL in case of error.
3365cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *         A new string is allocated only if needed (@val isn't a
3366ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         string object).
3367ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3368ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3369ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToString(xmlXPathObjectPtr val) {
3370ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret = NULL;
3371ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3372ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3373ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlStrdup((const xmlChar *) ""));
3374ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3375ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_UNDEFINED:
3376ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3377ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
3378ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3379ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "");
3380ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3381ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_NODESET:
33820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        case XPATH_XSLT_TREE:
3383ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastNodeSetToString(val->nodesetval);
3384ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3385ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_STRING:
33864e2df54bb17645ef0d3f28b9665b2d2dde4b47a3Daniel Veillard	    return(xmlStrdup(val->stringval));
3387ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_BOOLEAN:
3388ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastBooleanToString(val->boolval);
3389ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3390ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_NUMBER: {
3391ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastNumberToString(val->floatval);
3392ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3393ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	}
3394ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_USERS:
3395ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_POINT:
3396ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_RANGE:
3397ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_LOCATIONSET:
3398ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    TODO
3399ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "");
3400ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3401ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3402ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3403ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3404ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3405ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3406ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertString:
3407ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3408ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3409ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its string() equivalent
3410ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3411ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3412ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3413ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3414ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3415ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertString(xmlXPathObjectPtr val) {
3416ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *res = NULL;
3417ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3418ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3419ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewCString(""));
3420ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3421ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3422ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3423ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3424ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
3425ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3426ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3427ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
34280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
3429ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastNodeSetToString(val->nodesetval);
3430ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3431ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3432ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3433ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3434ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastBooleanToString(val->boolval);
3435ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3436ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3437ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastNumberToString(val->floatval);
3438ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3439ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3440ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3441ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3442ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3443ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3444ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3445ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3446ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3447ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (res == NULL)
3448ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewCString(""));
3449ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathWrapString(res));
3450ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3451ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3452ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3453ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastBooleanToNumber:
3454ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a boolean
3455ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3456ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a boolean to its number value
3457ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3458ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3459ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3460ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3461ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastBooleanToNumber(int val) {
3462ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val)
3463ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(1.0);
3464ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(0.0);
3465ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3466ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3467ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3468ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastStringToNumber:
3469ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a string
3470ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3471ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a string to its number value
3472ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3473ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3474ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3475ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3476ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastStringToNumber(const xmlChar * val) {
3477ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathStringEvalNumber(val));
3478ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3479ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3480ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3481ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeToNumber:
3482ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @node:  a node
3483ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3484ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node to its number value
3485ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3486ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3487ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3488ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3489ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeToNumber (xmlNodePtr node) {
3490ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *strval;
3491ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret;
3492ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3493ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (node == NULL)
3494ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3495ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    strval = xmlXPathCastNodeToString(node);
3496ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (strval == NULL)
3497ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3498ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathCastStringToNumber(strval);
3499ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlFree(strval);
3500ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3501ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3502ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3503ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3504ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3505ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToNumber:
3506ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3507ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3508ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its number value
3509ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3510ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3511ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3512ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3513ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
3514ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *str;
3515ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret;
3516ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3517ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (ns == NULL)
3518ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3519ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    str = xmlXPathCastNodeSetToString(ns);
3520ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathCastStringToNumber(str);
3521ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlFree(str);
3522ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3523ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3524ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3525ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3526ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastToNumber:
3527ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3528ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3529ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an XPath object to its number value
3530ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3531ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3532ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3533ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3534ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToNumber(xmlXPathObjectPtr val) {
3535ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret = 0.0;
3536ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3537ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3538ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3539ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3540ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3541ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEGUB_EXPR
3542ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
3543ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3544ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNAN;
3545ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3546ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
35470c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
3548ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNodeSetToNumber(val->nodesetval);
3549ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3550ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3551ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastStringToNumber(val->stringval);
3552ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3553ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3554ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = val->floatval;
3555ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3556ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3557ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastBooleanToNumber(val->boolval);
3558ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3559ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3560ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3561ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3562ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3563ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3564ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNAN;
3565ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3566ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3567ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3568ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3569ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3570ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3571ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertNumber:
3572ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3573ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3574ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its number() equivalent
3575ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3576ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3577ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3578ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3579ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3580ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertNumber(xmlXPathObjectPtr val) {
3581ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3582ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3583ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3584ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewFloat(0.0));
3585ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val->type == XPATH_NUMBER)
3586ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3587ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
3588ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3589ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3590ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3591ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3592ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3593ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNumberToBoolean:
3594ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a number
3595ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3596ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a number to its boolean value
3597ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3598ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3599ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3600ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3601ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNumberToBoolean (double val) {
3602cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard     if (xmlXPathIsNaN(val) || (val == 0.0))
3603ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	 return(0);
3604ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard     return(1);
3605ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3606ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3607ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3608ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastStringToBoolean:
3609ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a string
3610ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3611ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a string to its boolean value
3612ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3613ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3614ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3615ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3616ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastStringToBoolean (const xmlChar *val) {
3617ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((val == NULL) || (xmlStrlen(val) == 0))
3618ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3619ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(1);
3620ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3621ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3622ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3623ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToBoolean:
3624ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3625ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3626ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its boolean value
3627ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3628ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3629ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3630ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3631ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
3632ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((ns == NULL) || (ns->nodeNr == 0))
3633ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3634ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(1);
3635ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3636ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3637ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
36385e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathCastToBoolean:
3639ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3640ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3641ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an XPath object to its boolean value
3642ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3643ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3644ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3645ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3646ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToBoolean (xmlXPathObjectPtr val) {
3647ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    int ret = 0;
3648ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3649ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3650ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3651ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3652ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3653ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3654ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n");
3655ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3656ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = 0;
3657ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3658ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
36590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
3660ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
3661ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3662ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3663ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastStringToBoolean(val->stringval);
3664ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3665ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3666ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNumberToBoolean(val->floatval);
3667ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3668ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3669ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = val->boolval;
3670ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3671ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3672ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3673ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3674ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3675ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3676ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = 0;
3677ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3678ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3679ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3680ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3681ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3682ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3683ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3684ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertBoolean:
3685ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3686ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3687ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its boolean() equivalent
3688ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3689ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3690ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3691ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3692ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3693ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertBoolean(xmlXPathObjectPtr val) {
3694ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3695ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3696ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3697ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewBoolean(0));
3698ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val->type == XPATH_BOOLEAN)
3699ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3700ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
3701ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3702ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3703ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3704ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
37053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
37063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
37073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle XPath contexts			*
37083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
37093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
37103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
37123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewContext:
37133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @doc:  the XML document
37143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
37153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathContext
37163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
3717af43f63aaabf0dc4b4a070773875d0927da3d8a2Daniel Veillard * Returns the xmlXPathContext just allocated. The caller will need to free it.
37183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
37193473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathContextPtr
37203473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewContext(xmlDocPtr doc) {
37213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathContextPtr ret;
37223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
37243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
37253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
37263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewContext: out of memory\n");
37273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
37283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
37293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
37303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->doc = doc;
37313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->node = NULL;
37323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->varHash = NULL;
37343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nb_types = 0;
37363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->max_types = 0;
37373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->types = NULL;
37383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->funcHash = xmlHashCreate(0);
37403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nb_axis = 0;
37423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->max_axis = 0;
37433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->axis = NULL;
37443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nsHash = NULL;
37463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->user = NULL;
37473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->contextSize = -1;
37493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->proximityPosition = -1;
37503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterAllFunctions(ret);
37523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
37543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
37553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
37573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeContext:
37583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the context to free
37593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
37603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathContext
37613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
37623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
37633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeContext(xmlXPathContextPtr ctxt) {
37643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredNsCleanup(ctxt);
37653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredFuncsCleanup(ctxt);
37663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredVariablesCleanup(ctxt);
37673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
37683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
37693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
37713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
37723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle XPath parser contexts		*
37733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
37743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
37753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CHECK_CTXT(ctxt)						\
37773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) { 						\
37783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,				\
37793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"%s:%d Internal error: ctxt == NULL\n",			\
37803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        __FILE__, __LINE__);					\
37813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
37823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
37843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CHECK_CONTEXT(ctxt)						\
37853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) { 						\
37863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,				\
37873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"%s:%d Internal error: no context\n",			\
37883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        __FILE__, __LINE__);					\
37893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
37903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (ctxt->doc == NULL) { 					\
37913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,				\
37923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"%s:%d Internal error: no document\n",			\
37933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        __FILE__, __LINE__);					\
37943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
37953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (ctxt->doc->children == NULL) { 				\
37963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,				\
37973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        "%s:%d Internal error: document without root\n",	\
37983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        __FILE__, __LINE__);					\
37993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
38003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
38013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
38023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
38033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewParserContext:
38043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
38053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
38063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
38073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathParserContext
38083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
38093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathParserContext just allocated.
38103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
38113473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParserContextPtr
38123473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
38133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr ret;
38143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
38153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
38163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
38173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
38183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathNewParserContext: out of memory\n");
38193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
38203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
38213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
38223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->cur = ret->base = str;
38233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->context = ctxt;
38243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
38259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret->comp = xmlXPathNewCompExpr();
38269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret->comp == NULL) {
38279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret->valueTab);
38289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret);
38299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
38309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
38319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
38329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(ret);
38339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
38349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
38359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
38369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompParserContext:
38379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the XPath compiled expression
38389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctxt:  the XPath context
38399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
38409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Create a new xmlXPathParserContext when processing a compiled expression
38419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
38429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns the xmlXPathParserContext just allocated.
38439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
384456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathParserContextPtr
38459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
38469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathParserContextPtr ret;
38479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
38489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
38499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret == NULL) {
38509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
3851cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompParserContext: out of memory\n");
38529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
38539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
38549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
38559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
38563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Allocate the value stack */
38573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueTab = (xmlXPathObjectPtr *)
38583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                     xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
38599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret->valueTab == NULL) {
38609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret);
38619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        xmlGenericError(xmlGenericErrorContext,
3862cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompParserContext: out of memory\n");
38639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
38649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
38653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueNr = 0;
38663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueMax = 10;
38673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->value = NULL;
38689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3869fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    ret->context = ctxt;
38709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret->comp = comp;
38719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
38723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
38733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
38743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
38753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
38763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeParserContext:
38773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the context to free
38783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
38793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathParserContext
38803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
38813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
38823473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
38833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->valueTab != NULL) {
38843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(ctxt->valueTab);
38853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
38869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->comp)
38879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathFreeCompExpr(ctxt->comp);
38883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
38893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
38903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
38913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
38923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
38933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		The implicit core function library			*
38943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
38953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
38963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
38973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
389801c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathNodeValHash:
3899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @node:  a node pointer
3900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
3901f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Function computing the beginning of the string value of the node,
3902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * used to speed up comparisons
3903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
3904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns an int usable as a hash
3905f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
3906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic unsigned int
3907f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNodeValHash(xmlNodePtr node) {
3908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int len = 2;
3909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar * string = NULL;
3910f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr tmp = NULL;
3911f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int ret = 0;
3912f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3913f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (node == NULL)
3914f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
3915f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
39169adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard    if (node->type == XML_DOCUMENT_NODE) {
39179adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	tmp = xmlDocGetRootElement((xmlDocPtr) node);
39189adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	if (tmp == NULL)
39199adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    node = node->children;
39209adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	else
39219adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    node = tmp;
39229adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard
39239adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	if (node == NULL)
39249adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    return(0);
39259adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard    }
3926f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (node->type) {
3928f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_COMMENT_NODE:
3929f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_PI_NODE:
3930f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_CDATA_SECTION_NODE:
3931f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_TEXT_NODE:
3932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    string = node->content;
3933f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string == NULL)
3934f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3935f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
3936f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3937f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(((unsigned int) string[0]) +
3938f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		   (((unsigned int) string[1]) << 8));
3939f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_NAMESPACE_DECL:
3940f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    string = ((xmlNsPtr)node)->href;
3941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string == NULL)
3942f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
3944f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3945f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(((unsigned int) string[0]) +
3946f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		   (((unsigned int) string[1]) << 8));
3947f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_ATTRIBUTE_NODE:
3948f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = ((xmlAttrPtr) node)->children;
3949f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
3950f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_ELEMENT_NODE:
3951f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = node->children;
3952f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
3953f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	default:
3954f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(0);
3955f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
3956f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (tmp != NULL) {
3957f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	switch (tmp->type) {
3958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_COMMENT_NODE:
3959f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_PI_NODE:
3960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_CDATA_SECTION_NODE:
3961f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_TEXT_NODE:
3962f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		string = tmp->content;
3963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3964f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_NAMESPACE_DECL:
3965f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		string = ((xmlNsPtr)tmp)->href;
3966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3967f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    default:
3968f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
3969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
3970f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if ((string != NULL) && (string[0] != 0)) {
3971f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
3972f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
3973f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (len == 1) {
3974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(ret + (((unsigned int) string[0]) << 8));
3975f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
3976f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[1] == 0) {
3977f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		len = 1;
3978f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		ret = (unsigned int) string[0];
3979f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    } else {
3980f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(((unsigned int) string[0]) +
3981f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		       (((unsigned int) string[1]) << 8));
3982f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
3983f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
3984f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	/*
3985f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	 * Skip to next node
3986f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	 */
3987f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if ((tmp->children != NULL) && (tmp->type != XML_DTD_NODE)) {
3988f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp->children->type != XML_ENTITY_DECL) {
3989f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = tmp->children;
3990f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		continue;
3991f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
3992f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
3993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (tmp == node)
3994f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
3995f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
3996f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (tmp->next != NULL) {
3997f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = tmp->next;
3998f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    continue;
3999f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4000f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4001f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	do {
4002f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = tmp->parent;
4003f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp == NULL)
4004f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4005f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp == node) {
4006f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = NULL;
4007f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4008f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4009f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp->next != NULL) {
4010f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = tmp->next;
4011f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4012f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4013f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	} while (tmp != NULL);
4014f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
4015f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(ret);
4016f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
4017f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4018f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
4019f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathStringHash:
4020f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @string:  a string
4021f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4022f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Function computing the beginning of the string value of the node,
4023f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * used to speed up comparisons
4024f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4025f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns an int usable as a hash
4026f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
4027f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic unsigned int
4028f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathStringHash(const xmlChar * string) {
4029f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (string == NULL)
4030f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return((unsigned int) 0);
4031f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (string[0] == 0)
4032f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4033f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(((unsigned int) string[0]) +
4034f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	   (((unsigned int) string[1]) << 8));
4035f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
4036f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4037f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
40383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetFloat:
40393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
40403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
40413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
40423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
40433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the value
40443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
40453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a number
40463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
40473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
40483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
40493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
40503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
40513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a number,
40523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in the
40533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node-set such that the result of performing the comparison on the number
40543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be compared and on the result of converting the string-value of that
40553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node to a number using the number function is true.
40563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
40573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
40583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
405956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
40603473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
40613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr f) {
40623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, ret = 0;
40633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
40643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
40653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((f == NULL) || (arg == NULL) ||
40673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
40683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg);
40693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(f);
40703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
40713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
40723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4073911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (ns != NULL) {
4074911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < ns->nodeNr;i++) {
4075ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
4076911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     if (str2 != NULL) {
4077911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt,
4078911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard			   xmlXPathNewString(str2));
4079911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlFree(str2);
4080911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlXPathNumberFunction(ctxt, 1);
4081911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt, xmlXPathObjectCopy(f));
4082911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 ret = xmlXPathCompareValues(ctxt, inf, strict);
4083911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 if (ret)
4084911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		     break;
4085911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     }
4086911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
40873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
40883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
40893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(f);
40903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
40913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
40923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
40943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetString:
40953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
40963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
40973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
40983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
40993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @s:  the value
41003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a string
41023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
41033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
41043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
41053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
41063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a string,
41083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
41093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
41103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string-value of the node and the other string is true.
41113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
41133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
411456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
41153473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
41163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr s) {
41173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, ret = 0;
41183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
41193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
41203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((s == NULL) || (arg == NULL) ||
41223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
41233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg);
41243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(s);
41253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
41263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
41273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4128911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (ns != NULL) {
4129911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < ns->nodeNr;i++) {
4130ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
4131911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     if (str2 != NULL) {
4132911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt,
4133911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard			   xmlXPathNewString(str2));
4134911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlFree(str2);
4135911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt, xmlXPathObjectCopy(s));
4136911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 ret = xmlXPathCompareValues(ctxt, inf, strict);
4137911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 if (ret)
4138911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		     break;
4139911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     }
4140911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
41413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
41423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
41433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(s);
41443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
41453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
41463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
41483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSets:
4149ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @inf:  less than (1) or greater than (0)
41503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
4151cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @arg1:  the first node set object
41523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg2:  the second node set object
41533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation on nodesets:
41553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If both objects to be compared are node-sets, then the comparison
41573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if there is a node in the first node-set
41583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and a node in the second node-set such that the result of performing
41593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the comparison on the string-values of the two nodes is true.
41603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ....
41613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * When neither object to be compared is a node-set and the operator
41623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is <=, <, >= or >, then the objects are compared by converting both
41633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * objects to numbers and comparing the numbers according to IEEE 754.
41643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ....
41653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The number function converts its argument to a number as follows:
41663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - a string that consists of optional whitespace followed by an
41673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    optional minus sign followed by a Number followed by whitespace
41683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    is converted to the IEEE 754 number that is nearest (according
41693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    to the IEEE 754 round-to-nearest rule) to the mathematical value
41703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    represented by the string; any other string is converted to NaN
41713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
41723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Conclusion all nodes need to be converted first to their string value
41733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and then the comparison must be done when possible
41743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
417556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
417656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathCompareNodeSets(int inf, int strict,
41773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
41783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, j, init = 0;
41793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val1;
41803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double *values2;
41813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
41823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns1;
41833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns2;
41843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg1 == NULL) ||
41864dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) {
41874dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
41883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
41894dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
41903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2 == NULL) ||
41914dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) {
41924dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
41934dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
41943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
41954dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
41963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
41973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns1 = arg1->nodesetval;
41983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns2 = arg2->nodesetval;
41993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4200d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
42014dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
42024dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
42033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
42044dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
4205d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
42064dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
42074dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
42083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
42094dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
42103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
42123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values2 == NULL) {
42134dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
42144dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
42153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
42163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
42173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++) {
4218ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]);
4219cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(val1))
42203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    continue;
42213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++) {
42223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (init == 0) {
4223ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]);
42243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
4225cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	    if (xmlXPathIsNaN(values2[j]))
42263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		continue;
42273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (inf && strict)
42283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 < values2[j]);
42293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (inf && !strict)
42303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 <= values2[j]);
42313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (!inf && strict)
42323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 > values2[j]);
42333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (!inf && !strict)
42343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 >= values2[j]);
42353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ret)
42363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		break;
42373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
42383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret)
42393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
42403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	init = 1;
42413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
42423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values2);
42434dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    xmlXPathFreeObject(arg1);
42444dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    xmlXPathFreeObject(arg2);
42453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
42463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
42473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
42493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetValue:
42503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
42513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
42523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
42533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
42543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the value
42553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a value
42573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
42583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
42593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
42603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
42613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a boolean,
42633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if the result of performing
42643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the comparison on the boolean and on the result of converting
42653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set to a boolean using the boolean function is true.
42663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
42683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
426956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
42703473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
42713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr val) {
42723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((val == NULL) || (arg == NULL) ||
42733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
42743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
42753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(val->type) {
42773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
42783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
42793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
42803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_XSLT_TREE:
428156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    return(xmlXPathCompareNodeSets(inf, strict, arg, val));
42823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
42833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
42843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
42853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, arg);
42863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathBooleanFunction(ctxt, 1);
42873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, val);
42883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareValues(ctxt, inf, strict));
42893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
42903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    TODO
42913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
42923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
42933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
42943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
429601c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSetString:
42973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the nodeset object argument
42983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the string to compare to.
42990c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:  flag to show whether for '=' (0) or '!=' (1)
43003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
43023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a string,
43033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
43043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
43053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string-value of the node and the other string is true.
43063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
43083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
430956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
43100c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq)
4311f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
43123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
43133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
43143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
4315f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int hash;
43163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((str == NULL) || (arg == NULL) ||
4318f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
4319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return (0);
43203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hash = xmlXPathStringHash(str);
4322d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ns == NULL)
4323f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return (0);
432473c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard    if (ns->nodeNr <= 0) {
432573c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard	if (hash == 0)
43260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    return(neq ^ 1);
43270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        return(neq);
432873c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard    }
4329f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < ns->nodeNr; i++) {
4330f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
4331f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            str2 = xmlNodeGetContent(ns->nodeTab[i]);
4332f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((str2 != NULL) && (xmlStrEqual(str, str2))) {
4333f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(str2);
43340c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (neq)
43350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    continue;
4336f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (1);
43379adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    } else if ((str2 == NULL) && (xmlStrEqual(str, BAD_CAST ""))) {
43389adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		if (neq)
43399adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    continue;
43409adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard                return (1);
43410c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack            } else if (neq) {
43420c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (str2 != NULL)
43430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    xmlFree(str2);
43440c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		return (1);
43450c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
4346f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (str2 != NULL)
4347f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(str2);
43480c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        } else if (neq)
43490c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    return (1);
43503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4351f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (0);
43523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
43533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
435501c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSetFloat:
43563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the nodeset object argument
43573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the float to compare to
43580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:  flag to show whether to compare '=' (0) or '!=' (1)
43593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
43613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a number,
43623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
43633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
43643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number to be compared and on the result of converting the string-value
43653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of that node to a number using the number function is true.
43663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
43683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
436956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
43700c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
43710c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg, double f, int neq) {
43720c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  int i, ret=0;
43730c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlNodeSetPtr ns;
43740c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlChar *str2;
43750c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlXPathObjectPtr val;
43760c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  double v;
43773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg == NULL) ||
43793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
43803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
43813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    ns = arg->nodesetval;
43830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (ns != NULL) {
43840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	for (i=0;i<ns->nodeNr;i++) {
43850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
43860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (str2 != NULL) {
43870c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		valuePush(ctxt, xmlXPathNewString(str2));
43880c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlFree(str2);
43890c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlXPathNumberFunction(ctxt, 1);
43900c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		val = valuePop(ctxt);
43910c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		v = val->floatval;
43920c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlXPathFreeObject(val);
43930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (!xmlXPathIsNaN(v)) {
43940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    if ((!neq) && (v==f)) {
43950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			ret = 1;
43960c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			break;
43970c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    } else if ((neq) && (v!=f)) {
43980c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			ret = 1;
43990c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			break;
44000c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    }
44010c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		}
44020c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
44030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
44040c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
44050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
44060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return(ret);
44073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
44083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
441101c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSets:
44123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg1:  first nodeset object argument
44133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg2:  second nodeset object argument
44140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:   flag to show whether to test '=' (0) or '!=' (1)
44153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
44160c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal / not equal operation on XPath nodesets:
44170c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @arg1 == @arg2  or  @arg1 != @arg2
44183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If both objects to be compared are node-sets, then the comparison
44193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if there is a node in the first node-set and
44203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * a node in the second node-set such that the result of performing the
44213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * comparison on the string-values of the two nodes is true.
44223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
44233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (needless to say, this is a costly operation)
44243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
44253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
44263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
442756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
44280c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) {
44293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, j;
4430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int *hashs1;
4431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int *hashs2;
44323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar **values1;
44333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar **values2;
44343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
44353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns1;
44363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns2;
44373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg1 == NULL) ||
44393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)))
44403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
44413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2 == NULL) ||
44423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE)))
44433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
44443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns1 = arg1->nodesetval;
44463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns2 = arg2->nodesetval;
44473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4448911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((ns1 == NULL) || (ns1->nodeNr <= 0))
44493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
4450911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((ns2 == NULL) || (ns2->nodeNr <= 0))
44513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
44523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
44540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     * for equal, check if there is a node pertaining to both sets
44553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
44560c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (neq == 0)
44570c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	for (i = 0;i < ns1->nodeNr;i++)
44580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    for (j = 0;j < ns2->nodeNr;j++)
44590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (ns1->nodeTab[i] == ns2->nodeTab[j])
44600c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    return(1);
44613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
44633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values1 == NULL)
44643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
4465f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
4466f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (hashs1 == NULL) {
4467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values1);
4468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4469f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
44703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
44713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
44723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values2 == NULL) {
4473f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(hashs1);
44743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(values1);
44753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
44763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
4478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (hashs2 == NULL) {
4479f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(hashs1);
4480f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values1);
4481f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values2);
4482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4483f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
44843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *));
44853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++) {
4486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]);
44873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++) {
44883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (i == 0)
4489f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]);
44900c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (hashs1[i] != hashs2[j]) {
44910c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (neq) {
44920c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
44930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
44940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		}
44950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
44960c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    else {
4497f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (values1[i] == NULL)
4498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
4499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (values2[j] == NULL)
4500f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
45010c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlStrEqual(values1[i], values2[j]) ^ neq;
4502f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (ret)
4503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    break;
4504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
45053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
45063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret)
45073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
45083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
45093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++)
45103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (values1[i] != NULL)
45113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(values1[i]);
45123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (j = 0;j < ns2->nodeNr;j++)
45133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (values2[j] != NULL)
45143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(values2[j]);
45153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values1);
45163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values2);
4517f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlFree(hashs1);
4518f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlFree(hashs2);
45193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
45203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
45213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackstatic int
45230c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
45240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
45253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
45260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
45270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *At this point we are assured neither arg1 nor arg2
45280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *is a nodeset, so we can just pick the appropriate routine.
45290c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
45303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (arg1->type) {
45313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_UNDEFINED:
45323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
45333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
45343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "Equal: undefined\n");
45353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
45363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
45373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
45383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
45393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
45403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
45413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
45423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
45433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
45443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
45463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
45473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
45483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: %d boolean %d \n",
45493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    arg1->boolval, arg2->boolval);
45503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
45513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == arg2->boolval);
45523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
4554ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		    ret = (arg1->boolval ==
4555ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack			   xmlXPathCastNumberToBoolean(arg2->floatval));
45563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
45583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg2->stringval == NULL) ||
45593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg2->stringval[0] == 0)) ret = 0;
45603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
45613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
45623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == ret);
45633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
45653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
45663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
45673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
45683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
45693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45700c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
45710c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
45720c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
45733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
45743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
45753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
45763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
45773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
45783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
45793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
45803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
45813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
45823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
4584ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		    ret = (arg2->boolval==
4585ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack			   xmlXPathCastNumberToBoolean(arg1->floatval));
45863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
45873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
45883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    valuePush(ctxt, arg2);
45893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlXPathNumberFunction(ctxt, 1);
45903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    arg2 = valuePop(ctxt);
45913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* no break on purpose */
45923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
4593d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    /* Hand check NaN and Infinity equalities */
459421458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
459521458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = 0;
4596d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
4597d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		        if (xmlXPathIsInf(arg2->floatval) == 1)
4598d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4599d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4600d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4601d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
4602d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == -1)
4603d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4604d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4605d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4606d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
4607d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == 1)
4608d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4609d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4610d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4611d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
4612d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == -1)
4613d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4614d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4615d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
461621458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    } else {
461721458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = (arg1->floatval == arg2->floatval);
461821458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    }
46193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
46203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
46213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
46223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
46233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
46243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
46253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
46260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
46270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
46280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
46293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
46303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
46313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
46323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
46333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
46343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
46353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
46363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
46373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
46383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
46393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
46403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg1->stringval == NULL) ||
46413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg1->stringval[0] == 0)) ret = 0;
46423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
46433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
46443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg2->boolval == ret);
46453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
46463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
46473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlStrEqual(arg1->stringval, arg2->stringval);
46483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
46493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
46503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    valuePush(ctxt, arg1);
46513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlXPathNumberFunction(ctxt, 1);
46523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    arg1 = valuePop(ctxt);
4653d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    /* Hand check NaN and Infinity equalities */
465421458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
465521458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = 0;
4656d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
4657d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == 1)
4658d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4659d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4660d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4661d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
4662d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == -1)
4663d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4664d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4665d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4666d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
4667d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == 1)
4668d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4669d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4670d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4671d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
4672d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == -1)
4673d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4674d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4675d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
467621458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    } else {
467721458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = (arg1->floatval == arg2->floatval);
467821458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    }
46793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
46803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
46813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
46823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
46833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
46843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
46853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
46860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
46870c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
46880c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
46893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
46903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
46913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_USERS:
46923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
46933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
46943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
46953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    TODO
46963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
46970c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	case XPATH_NODESET:
46980c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	case XPATH_XSLT_TREE:
46990c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    break;
47003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
47013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg1);
47023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg2);
47033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
47043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack/**
47070c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * xmlXPathEqualValues:
47080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @ctxt:  the XPath Parser context
47090c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
47100c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal operation on XPath objects content: @arg1 == @arg2
47110c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
47120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Returns 0 or 1 depending on the results of the test.
47130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack */
47140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackint
47150c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
47160c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg1, arg2, argtmp;
47170c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    int ret = 0;
47180c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
47190c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
47200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg1 = valuePop(ctxt);
47210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
47220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
47230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
47240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
47250c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
47260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	XP_ERROR0(XPATH_INVALID_OPERAND);
47270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
47280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
47290c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (arg1 == arg2) {
47300c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
47310c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        xmlGenericError(xmlGenericErrorContext,
47320c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		"Equal: by pointer\n");
47330c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
47340c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        return(1);
47350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
47360c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
47370c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
47380c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *If either argument is a nodeset, it's a 'special case'
47390c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
47400c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
47410c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
47420c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	/*
47430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 *Hack it to assure arg1 is the nodeset
47440c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 */
47450c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
47460c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		argtmp = arg2;
47470c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg2 = arg1;
47480c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg1 = argtmp;
47490c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
47500c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	switch (arg2->type) {
47510c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_UNDEFINED:
47520c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
47530c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlGenericError(xmlGenericErrorContext,
47540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			"Equal: undefined\n");
47550c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
47560c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
47570c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NODESET:
47580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_XSLT_TREE:
47590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSets(arg1, arg2, 0);
47600c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
47610c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_BOOLEAN:
47620c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if ((arg1->nodesetval == NULL) ||
47630c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		  (arg1->nodesetval->nodeNr == 0)) ret = 0;
47640c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		else
47650c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
47660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = (ret == arg2->boolval);
47670c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
47680c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NUMBER:
47690c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0);
47700c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
47710c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_STRING:
47720c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0);
47730c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
47740c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_USERS:
47750c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_POINT:
47760c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_RANGE:
47770c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_LOCATIONSET:
47780c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		TODO
47790c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
47800c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
47810c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg1);
47820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg2);
47830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	return(ret);
47840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
47850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
47860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return (xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
47870c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack}
47880c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
47890c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack/**
47900c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * xmlXPathNotEqualValues:
47910c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @ctxt:  the XPath Parser context
47920c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
47930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal operation on XPath objects content: @arg1 == @arg2
47940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
47950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Returns 0 or 1 depending on the results of the test.
47960c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack */
47970c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackint
47980c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
47990c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg1, arg2, argtmp;
48000c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    int ret = 0;
48010c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
48020c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
48030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg1 = valuePop(ctxt);
48040c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
48050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
48060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
48070c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
48080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
48090c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	XP_ERROR0(XPATH_INVALID_OPERAND);
48100c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
48110c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
48120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (arg1 == arg2) {
48130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
48140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        xmlGenericError(xmlGenericErrorContext,
48150c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		"NotEqual: by pointer\n");
48160c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
48170c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        return(0);
48180c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
48190c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
48200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
48210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *If either argument is a nodeset, it's a 'special case'
48220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
48230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
48240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
48250c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	/*
48260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 *Hack it to assure arg1 is the nodeset
48270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 */
48280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
48290c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		argtmp = arg2;
48300c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg2 = arg1;
48310c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg1 = argtmp;
48320c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
48330c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	switch (arg2->type) {
48340c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_UNDEFINED:
48350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
48360c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlGenericError(xmlGenericErrorContext,
48370c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			"NotEqual: undefined\n");
48380c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
48390c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
48400c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NODESET:
48410c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_XSLT_TREE:
48420c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSets(arg1, arg2, 1);
48430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
48440c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_BOOLEAN:
48450c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if ((arg1->nodesetval == NULL) ||
48460c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		  (arg1->nodesetval->nodeNr == 0)) ret = 0;
48470c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		else
48480c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
4849ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		ret = (ret != arg2->boolval);
48500c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
48510c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NUMBER:
48520c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1);
48530c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
48540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_STRING:
48550c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1);
48560c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
48570c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_USERS:
48580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_POINT:
48590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_RANGE:
48600c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_LOCATIONSET:
48610c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		TODO
48620c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
48630c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
48640c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg1);
48650c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg2);
48660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	return(ret);
48670c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
48680c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
48690c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
48700c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack}
48713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
48733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareValues:
48743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
48753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
48763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
48773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
48783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation on XPath objects:
48793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 < @arg2    (1, 1, ...
48803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 <= @arg2   (1, 0, ...
48813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 > @arg2    (0, 1, ...
48823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 >= @arg2   (0, 0, ...
48833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
48843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * When neither object to be compared is a node-set and the operator is
48853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * <=, <, >=, >, then the objects are compared by converted both objects
48863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to numbers and comparing the numbers according to IEEE 754. The <
48873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * comparison will be true if and only if the first number is less than the
48883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * second number. The <= comparison will be true if and only if the first
48893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number is less than or equal to the second number. The > comparison
48903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if the first number is greater than the second
48913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number. The >= comparison will be true if and only if the first number
48923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is greater than or equal to the second number.
48933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
4894cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if the comparison succeeded, 0 if it failed
48953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
48963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
48973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
4898d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard    int ret = 0, arg1i = 0, arg2i = 0;
48993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg1, arg2;
49003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49010c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
49023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    arg1 = valuePop(ctxt);
49030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
49040c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
49050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
49060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
49070c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
49083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
49093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
49103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49110c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
49120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
49130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) &&
49140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	  ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){
491556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    ret = xmlXPathCompareNodeSets(inf, strict, arg1, arg2);
49163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
49170c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
49184af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard		ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
49194af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard			                          arg1, arg2);
49203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else {
49214af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard		ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict,
49224af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard			                          arg2, arg1);
49233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
49243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
49253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(ret);
49263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
49273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
49283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1->type != XPATH_NUMBER) {
49293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, arg1);
49303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathNumberFunction(ctxt, 1);
49313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	arg1 = valuePop(ctxt);
49323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
49333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1->type != XPATH_NUMBER) {
49343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
49353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
49363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
49373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
49383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2->type != XPATH_NUMBER) {
49393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, arg2);
49403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathNumberFunction(ctxt, 1);
49413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	arg2 = valuePop(ctxt);
49423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
49433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2->type != XPATH_NUMBER) {
49443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
49453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
49463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
49473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
49483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
49493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Add tests for infinity and nan
49503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * => feedback on 3.4 for Inf and NaN
49513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
4952d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard    /* Hand check NaN and Infinity comparisons */
495321458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
4954d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	ret=0;
495521458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    } else {
4956d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	arg1i=xmlXPathIsInf(arg1->floatval);
4957d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	arg2i=xmlXPathIsInf(arg2->floatval);
4958d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	if (inf && strict) {
4959d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if ((arg1i == -1 && arg2i != -1) ||
4960d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		(arg2i == 1 && arg1i != 1)) {
4961d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
4962d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
4963d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval < arg2->floatval);
4964d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
4965d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
4966d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
4967d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
4968d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (inf && !strict) {
4969d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if (arg1i == -1 || arg2i == 1) {
4970d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
4971d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
4972d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval <= arg2->floatval);
4973d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
4974d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
4975d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
4976d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
4977d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (!inf && strict) {
4978d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if ((arg1i == 1 && arg2i != 1) ||
4979d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		(arg2i == -1 && arg1i != -1)) {
4980d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
4981d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
4982d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval > arg2->floatval);
4983d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
4984d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
4985d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
4986d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
4987d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (!inf && !strict) {
4988d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if (arg1i == 1 || arg2i == -1) {
4989d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
4990d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
4991d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval >= arg2->floatval);
4992d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
4993d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
4994d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
4995d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
499621458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    }
49973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg1);
49983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg2);
49993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
50003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
50013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
50033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathValueFlipSign:
50043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
50053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the unary - operation on an XPath object
50073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
50083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
50093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
50103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
50113473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
5012ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5013ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5014eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (xmlXPathIsNaN(ctxt->value->floatval))
5015eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathNAN;
5016eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (xmlXPathIsInf(ctxt->value->floatval) == 1)
5017eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathNINF;
5018eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (xmlXPathIsInf(ctxt->value->floatval) == -1)
5019eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathPINF;
5020eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (ctxt->value->floatval == 0) {
50215fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard        if (xmlXPathGetSign(ctxt->value->floatval) == 0)
50225fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNZERO;
50235fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else
50245fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = 0;
50255fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
50265fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else
50275fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard        ctxt->value->floatval = - ctxt->value->floatval;
50283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
50293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
50313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathAddValues:
50323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
50333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the add operation on XPath objects:
50353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
50363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
50373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
50383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
50393473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
50403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
50413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
50423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5043ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5044ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5045ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5046ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
50473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
50483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5049ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5050ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5051ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval += val;
50523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
50533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
50553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubValues:
50563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
50573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5058cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Implement the subtraction operation on XPath objects:
50593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
50603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
50613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
50623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
50633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
50643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
50653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
50663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5067ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5068ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5069ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5070ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
50713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
50723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5073ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5074ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5075ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval -= val;
50763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
50773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
50793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathMultValues:
50803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
50813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the multiply operation on XPath objects:
50833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
50843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
50853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
50863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
50873473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
50883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
50893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
50903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5091ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5092ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5093ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5094ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
50953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
50963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5097ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5098ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5099ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval *= val;
51003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
51013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
51033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathDivValues:
51043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
51053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
51063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the div operation on XPath objects @arg1 / @arg2:
51073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
51083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
51093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
51103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
51113473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
51123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
51133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
51143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5115ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5116ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5117ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5118ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
51193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
51203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5121ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5122ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5123eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (xmlXPathIsNaN(val) || xmlXPathIsNaN(ctxt->value->floatval))
5124eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard	ctxt->value->floatval = xmlXPathNAN;
5125eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (val == 0 && xmlXPathGetSign(val) != 0) {
51265fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (ctxt->value->floatval == 0)
51275fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNAN;
51285fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else if (ctxt->value->floatval > 0)
51295fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNINF;
51305fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else if (ctxt->value->floatval < 0)
51315fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathPINF;
51325fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
51335fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else if (val == 0) {
51345f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	if (ctxt->value->floatval == 0)
51355f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathNAN;
51365f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	else if (ctxt->value->floatval > 0)
51375f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathPINF;
51385f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	else if (ctxt->value->floatval < 0)
51395f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathNINF;
51405f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard    } else
51415f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	ctxt->value->floatval /= val;
51423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
51433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
51453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathModValues:
51463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
51473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
51483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the mod operation on XPath objects: @arg1 / @arg2
51493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
51503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
51513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
51523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
51533473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathModValues(xmlXPathParserContextPtr ctxt) {
51543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
5155fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    double arg1, arg2;
51563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5157ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5158ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5159ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
51605fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    arg2 = xmlXPathCastToNumber(arg);
51613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
51623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5163ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5164ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
51655fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    arg1 = ctxt->value->floatval;
5166268fd1bc97f79b43290041cfda2287fb0b0ef2d6Daniel Veillard    if (arg2 == 0)
5167268fd1bc97f79b43290041cfda2287fb0b0ef2d6Daniel Veillard	ctxt->value->floatval = xmlXPathNAN;
51685fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else {
5169fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	ctxt->value->floatval = fmod(arg1, arg2);
51705fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
51713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
51723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
51743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
51753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		The traversal functions					*
51763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
51773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
51783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
51803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A traversal function enumerates nodes along an axis.
51813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initially it must be called with NULL, and it indicates
51823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * termination on the axis by returning NULL.
51833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
51843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylortypedef xmlNodePtr (*xmlXPathTraversalFunction)
51853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    (xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
51863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
51883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextSelf:
51893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
51903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
51913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
51923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "self" direction
51933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The self axis contains just the context node itself
51943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
51953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
51963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
51973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
51983473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
51993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
52003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
52013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
52023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextChild:
52063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
52083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "child" direction
52103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The child axis contains the children of the context node in document order.
52113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
52133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52143473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
52153473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
52163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
52173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
52183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
52193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
52203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
52213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
52223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
52233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
52243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
52253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
52263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
52273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DTD_NODE:
52283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->children);
52293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
52303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
52313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
52323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5233eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5234eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
52353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
52363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(((xmlDocPtr) ctxt->context->node)->children);
52373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
52383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
52393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
52403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE:
52413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_NAMESPACE_DECL:
52423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
52433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
52443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
52453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
52463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
52473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
52483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur->type == XML_DOCUMENT_NODE) ||
52493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        (cur->type == XML_HTML_DOCUMENT_NODE))
52503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
52513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->next);
52523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextDescendant:
52563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
52583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "descendant" direction
52603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the descendant axis contains the descendants of the context node in document
52613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * order; a descendant is a child or a child of a child and so on.
52623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
52643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
52663473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
52673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
52683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL)
52693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
52703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
52713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
52723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
52733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
52753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(ctxt->context->doc->children);
52763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->children);
52773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
52783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5279567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    if (cur->children != NULL) {
528068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	/*
528168e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	 * Do not descend on entities declarations
528268e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	 */
528368e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    	if (cur->children->type != XML_ENTITY_DECL) {
528468e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    cur = cur->children;
528568e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    /*
528668e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	     * Skip DTDs
528768e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	     */
528868e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    if (cur->type != XML_DTD_NODE)
528968e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard		return(cur);
529068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	}
5291567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    }
5292567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard
5293567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    if (cur == ctxt->context->node) return(NULL);
5294567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard
529568e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    while (cur->next != NULL) {
529668e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	cur = cur->next;
529768e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	if ((cur->type != XML_ENTITY_DECL) &&
529868e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    (cur->type != XML_DTD_NODE))
529968e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    return(cur);
530068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    }
53013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
53033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
53043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == NULL) return(NULL);
53053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == ctxt->context->node) return(NULL);
53063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->next != NULL) {
53073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur = cur->next;
53083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(cur);
53093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
53103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (cur != NULL);
53113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur);
53123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
53133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
53153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextDescendantOrSelf:
53163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
53173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
53183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "descendant-or-self" direction
53203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the descendant-or-self axis contains the context node and the descendants
53213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node in document order; thus the context node is the first
53223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node on the axis, and the first child of the context node is the second node
53233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * on the axis
53243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
53263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53273473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
53283473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
53293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
53303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL)
53313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
53323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
53333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
53343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
53353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
53363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
53373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathNextDescendant(ctxt, cur));
53393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
53403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
53423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextParent:
53433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
53443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
53453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "parent" direction
53473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The parent axis contains the parent of the context node, if there is one.
53483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
53503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53513473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
53523473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
53533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
53543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * the parent of an attribute or namespace node is the element
53553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * to which the attribute or namespace node is attached
53563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Namespace handling !!!
53573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
53583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
53593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
53603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
53613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
53623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
53633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
53643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
53653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
53663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
53673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
53683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
53693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DTD_NODE:
53703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
53713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
53723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
53733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
53743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
53753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (ctxt->context->node->parent == NULL)
53763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return((xmlNodePtr) ctxt->context->doc);
53778e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
5378652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    ((ctxt->context->node->parent->name[0] == ' ') ||
5379652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		     (xmlStrEqual(ctxt->context->node->parent->name,
5380652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard				 BAD_CAST "fake node libxslt"))))
53818e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		    return(NULL);
53823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->parent);
53833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE: {
53843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
53853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(att->parent);
53873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
53883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
53893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
53903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
53913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5392eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5393eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
53943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
53953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5396044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    case XML_NAMESPACE_DECL: {
5397044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5398044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
5399044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns->next != NULL) &&
5400044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (ns->next->type != XML_NAMESPACE_DECL))
5401044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return((xmlNodePtr) ns->next);
54023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5403044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
54043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
54053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
54073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
54083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
54103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAncestor:
54113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
54123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
54133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "ancestor" direction
54153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the ancestor axis contains the ancestors of the context node; the ancestors
54163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node consist of the parent of context node and the parent's
54173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent and so on; the nodes are ordered in reverse document order; thus the
54183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent is the first node on the axis, and the parent's parent is the second
54193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node on the axis
54203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
54223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
54233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
54243473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
54253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
54263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * the parent of an attribute or namespace node is the element
54273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * to which the attribute or namespace node is attached
54283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * !!!!!!!!!!!!!
54293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
54303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
54313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
54323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
54333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
54343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
54353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
54363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
54373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
54383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
54393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
54403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_DTD_NODE:
54413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
54423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
54433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
54443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
54453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
54463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
54473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (ctxt->context->node->parent == NULL)
54483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return((xmlNodePtr) ctxt->context->doc);
54498e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
5450652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    ((ctxt->context->node->parent->name[0] == ' ') ||
5451652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		     (xmlStrEqual(ctxt->context->node->parent->name,
5452652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard				 BAD_CAST "fake node libxslt"))))
54538e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		    return(NULL);
54543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->parent);
54553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE: {
545656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard		xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node;
54573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
545856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard		return(tmp->parent);
54593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
54603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
54613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
54623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
54633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5464eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5465eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
54663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
54673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5468044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    case XML_NAMESPACE_DECL: {
5469044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5470044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
5471044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns->next != NULL) &&
5472044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (ns->next->type != XML_NAMESPACE_DECL))
5473044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return((xmlNodePtr) ns->next);
5474044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		/* Bad, how did that namespace ended-up there ? */
54753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5476044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
54773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
54783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
54793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == ctxt->context->doc->children)
54813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return((xmlNodePtr) ctxt->context->doc);
54823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
54833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
54843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (cur->type) {
54853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
54863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_TEXT_NODE:
54873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_CDATA_SECTION_NODE:
54883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ENTITY_REF_NODE:
54893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ENTITY_NODE:
54903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_PI_NODE:
54913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_COMMENT_NODE:
54923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_NOTATION_NODE:
54933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DTD_NODE:
54943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ELEMENT_DECL:
54953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ATTRIBUTE_DECL:
54963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ENTITY_DECL:
54973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_XINCLUDE_START:
54983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_XINCLUDE_END:
54998e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard	    if (cur->parent == NULL)
55008e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		return(NULL);
55018e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard	    if ((cur->parent->type == XML_ELEMENT_NODE) &&
5502652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		((cur->parent->name[0] == ' ') ||
5503652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		 (xmlStrEqual(cur->parent->name,
5504652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard			      BAD_CAST "fake node libxslt"))))
55058e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		return(NULL);
55063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(cur->parent);
55073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE: {
55083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
55093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(att->parent);
55113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5512dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	case XML_NAMESPACE_DECL: {
5513dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5514dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin
5515dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    if ((ns->next != NULL) &&
5516dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	        (ns->next->type != XML_NAMESPACE_DECL))
5517dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	        return((xmlNodePtr) ns->next);
5518dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    /* Bad, how did that namespace ended-up there ? */
5519dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin            return(NULL);
5520dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	}
55213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_NODE:
55223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_TYPE_NODE:
55233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_FRAG_NODE:
55243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_HTML_DOCUMENT_NODE:
5525eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5526eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	case XML_DOCB_DOCUMENT_NODE:
55273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
55283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
55293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
55303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
55313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAncestorOrSelf:
55353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
55373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "ancestor-or-self" direction
55393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * he ancestor-or-self axis contains the context node and ancestors of
55403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node in reverse document order; thus the context node is
55413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the first node on the axis, and the context node's parent the second;
55423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent here is defined the same as with the parent axis.
55433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
55453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
55473473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
55483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
55493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
55503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathNextAncestor(ctxt, cur));
55513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextFollowingSibling:
55553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
55573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "following-sibling" direction
55593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The following-sibling axis contains the following siblings of the context
55603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node in document order.
55613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
55633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55643473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
55653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
55663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
55673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->context->node->type == XML_NAMESPACE_DECL))
55683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
55693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
55703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
55713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
55723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->next);
55733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->next);
55743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextPrecedingSibling:
55783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
55803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "preceding-sibling" direction
55823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The preceding-sibling axis contains the preceding siblings of the context
55833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node in reverse document order; the first preceding sibling is first on the
55843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * axis; the sibling preceding that node is the second on the axis and so on.
55853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
55873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55883473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
55893473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
55903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
55913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->context->node->type == XML_NAMESPACE_DECL))
55923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
55933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
55943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
55953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
55963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->prev);
5597f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
5598f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
5599f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (cur == NULL)
5600f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(ctxt->context->node->prev);
5601f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
56023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->prev);
56033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
56043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
56063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextFollowing:
56073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
56083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
56093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "following" direction
56113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The following axis contains all nodes in the same document as the context
56123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node that are after the context node in document order, excluding any
56133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * descendants and excluding attribute nodes and namespace nodes; the nodes
56143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * are ordered in document order
56153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
56173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
56183473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
56193473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
56203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur != NULL && cur->children != NULL)
56213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return cur->children ;
56223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) cur = ctxt->context->node;
56233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return(NULL) ; /* ERROR */
56243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->next != NULL) return(cur->next) ;
56253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
56263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
56273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur == NULL) return(NULL);
56283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
56293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->next != NULL) return(cur->next);
56303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (cur != NULL);
56313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur);
56323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
56333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
56353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsAncestor:
56363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ancestor:  the ancestor node
56373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node:  the current node
56383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Check that @ancestor is a @node's ancestor
56403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
56423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
56433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int
56443473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
56453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ancestor == NULL) || (node == NULL)) return(0);
56463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* nodes need to be in the same document */
56473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ancestor->doc != node->doc) return(0);
56483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* avoid searching if ancestor or node is the root node */
56493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ancestor == (xmlNodePtr) node->doc) return(1);
56503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node == (xmlNodePtr) ancestor->doc) return(0);
56513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (node->parent != NULL) {
56523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (node->parent == ancestor)
56533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            return(1);
56543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node = node->parent;
56553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
56563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
56573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
56583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
56603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextPreceding:
56613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
56623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
56633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "preceding" direction
56653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the preceding axis contains all nodes in the same document as the context
56663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node that are before the context node in document order, excluding any
56673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ancestors and excluding attribute nodes and namespace nodes; the nodes are
56683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ordered in reverse document order
56693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
56713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
56723473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
5673f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
5674f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
5675f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (cur == NULL)
5676f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = ctxt->context->node;
56773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
5678f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return (NULL);
5679f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
5680f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
56813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
56823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->prev != NULL) {
5683f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
5684f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (cur);
56853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
56863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
5688f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5689f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5690f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == ctxt->context->doc->children)
5691f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
56923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (xmlXPathIsAncestor(cur, ctxt->context->node));
5693f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (cur);
5694f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
5695f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
5696f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
5697f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNextPrecedingInternal:
5698f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath Parser context
5699f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @cur:  the current node in the traversal
5700f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
5701f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Traversal function for the "preceding" direction
5702f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * the preceding axis contains all nodes in the same document as the context
5703f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * node that are before the context node in document order, excluding any
5704f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * ancestors and excluding attribute nodes and namespace nodes; the nodes are
5705f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * ordered in reverse document order
5706f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * This is a faster implementation but internal only since it requires a
5707f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * state kept in the parser context: ctxt->ancestor.
5708f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
5709f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the next element following that axis
5710f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
5711f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic xmlNodePtr
5712f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
5713f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlNodePtr cur)
5714f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
5715f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (cur == NULL) {
5716f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = ctxt->context->node;
5717f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5718f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5719f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->ancestor = cur->parent;
5720f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
5721f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
5722f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
5723f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (cur->prev == NULL) {
5724f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = cur->parent;
5725f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5726f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5727f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == ctxt->context->doc->children)
5728f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5729f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur != ctxt->ancestor)
5730f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (cur);
5731f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->ancestor = cur->parent;
5732f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
5733f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    cur = cur->prev;
5734f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (cur->last != NULL)
5735f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = cur->last;
5736f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (cur);
57373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextNamespace:
57413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current attribute in the traversal
57433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "namespace" direction
57453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the namespace axis contains the namespace nodes of the context node;
57463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the order of nodes on this axis is implementation-defined; the axis will
57473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * be empty unless the context node is an element
57483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
574920ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard * We keep the XML namespace node at the end of the list.
575020ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard *
57513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
57523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57533473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
57543473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
57553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
5756fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) {
57577d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard        if (ctxt->context->tmpNsList != NULL)
57587d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	    xmlFree(ctxt->context->tmpNsList);
57597d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsList =
57603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGetNsList(ctxt->context->doc, ctxt->context->node);
57617d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsNr = 0;
5762fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	if (ctxt->context->tmpNsList != NULL) {
5763fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
5764fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		ctxt->context->tmpNsNr++;
5765fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    }
5766fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	}
5767fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return((xmlNodePtr) xmlXPathXMLNamespace);
57687d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    }
5769fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    if (ctxt->context->tmpNsNr > 0) {
5770fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return (xmlNodePtr)ctxt->context->tmpNsList[--ctxt->context->tmpNsNr];
5771fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    } else {
5772fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	if (ctxt->context->tmpNsList != NULL)
5773fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlFree(ctxt->context->tmpNsList);
57747d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsList = NULL;
5775fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return(NULL);
57763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
57773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAttribute:
57813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current attribute in the traversal
57833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "attribute" direction
57853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * TODO: support DTD inherited default attributes
57863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
57883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57893473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
57903473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5791e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard    if (ctxt->context->node == NULL)
5792e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard	return(NULL);
5793e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard    if (ctxt->context->node->type != XML_ELEMENT_NODE)
5794e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard	return(NULL);
57953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
57963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
57973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
57983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return((xmlNodePtr)ctxt->context->node->properties);
57993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
58003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((xmlNodePtr)cur->next);
58013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
58023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
58043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
58053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		NodeTest Functions					*
58063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
58073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
58083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_FUNCTION			200
58103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5811d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
5812d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/************************************************************************
5813d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
5814d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *		Implicit tree core function library			*
5815d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
5816d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard ************************************************************************/
5817d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
58183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
5819d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathRoot:
58203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
58213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5822d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Initialize the context to the root of the document
58233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
5824d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
5825d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathRoot(xmlXPathParserContextPtr ctxt) {
5826d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
5827d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
5828d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
58293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5830d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/************************************************************************
5831d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
5832d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *		The explicit core function library			*
5833d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib	*
5834d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
5835d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard ************************************************************************/
58363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5837d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
5838d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
5839d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathLastFunction:
5840d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
5841d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @nargs:  the number of arguments
5842d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
5843d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Implement the last() XPath function
5844d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *    number last()
5845d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * The last function returns the number of nodes in the context node list.
5846d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
5847d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
5848d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
5849d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    CHECK_ARITY(0);
5850d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ctxt->context->contextSize >= 0) {
5851d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) ctxt->context->contextSize));
5852d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_EXPR
5853d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlGenericError(xmlGenericErrorContext,
5854d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		"last() : %d\n", ctxt->context->contextSize);
58553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
5856d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    } else {
5857d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	XP_ERROR(XPATH_INVALID_CTXT_SIZE);
58583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
5859d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
58603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5861d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
5862d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathPositionFunction:
5863d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
5864d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @nargs:  the number of arguments
5865d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
5866d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Implement the position() XPath function
5867d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *    number position()
5868d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * The position function returns the position of the context node in the
5869cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * context node list. The first position is 1, and so the last position
5870d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * will be equal to last().
5871d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
5872d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
5873d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
5874d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    CHECK_ARITY(0);
5875d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ctxt->context->proximityPosition >= 0) {
5876d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	valuePush(ctxt,
5877d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	      xmlXPathNewFloat((double) ctxt->context->proximityPosition));
5878d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_EXPR
5879d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "position() : %d\n",
5880d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		ctxt->context->proximityPosition);
58813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
5882d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    } else {
5883d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	XP_ERROR(XPATH_INVALID_CTXT_POSITION);
5884d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
5885d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
58863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
58883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCountFunction:
58893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
58903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
58913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the count() XPath function
58933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number count(node-set)
58943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
58953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
58963473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
58973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
58983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
59003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
59013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
59023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
59033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
59043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
59053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5906911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur == NULL) || (cur->nodesetval == NULL))
5907911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) 0));
59080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    else if ((cur->type == XPATH_NODESET) || (cur->type == XPATH_XSLT_TREE)) {
5909911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) cur->nodesetval->nodeNr));
5910fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    } else {
5911fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	if ((cur->nodesetval->nodeNr != 1) ||
5912fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    (cur->nodesetval->nodeTab == NULL)) {
5913fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    valuePush(ctxt, xmlXPathNewFloat((double) 0));
5914fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	} else {
5915fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    xmlNodePtr tmp;
5916fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    int i = 0;
5917fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard
5918fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    tmp = cur->nodesetval->nodeTab[0];
5919fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    if (tmp != NULL) {
5920fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		tmp = tmp->children;
5921fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		while (tmp != NULL) {
5922fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		    tmp = tmp->next;
5923fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		    i++;
5924fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		}
5925fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    }
5926fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    valuePush(ctxt, xmlXPathNewFloat((double) i));
5927fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	}
5928fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    }
59293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
59303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
59313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
5933ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathGetElementsByIds:
5934ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @doc:  the document
5935ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ids:  a whitespace separated list of IDs
5936ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
5937ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Selects elements by their unique ID.
5938ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
5939ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a node-set of selected elements.
5940ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
5941ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardstatic xmlNodeSetPtr
5942ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
5943ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodeSetPtr ret;
5944ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    const xmlChar *cur = ids;
5945ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ID;
5946ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlAttrPtr attr;
5947ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodePtr elem = NULL;
5948ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
59497a985a18c2fee0aa9b490792dd990b75506e3740Daniel Veillard    if (ids == NULL) return(NULL);
59507a985a18c2fee0aa9b490792dd990b75506e3740Daniel Veillard
5951ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNodeSetCreate(NULL);
5952ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5953ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    while (IS_BLANK(*cur)) cur++;
5954ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    while (*cur != 0) {
5955e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	while ((!IS_BLANK(*cur)) && (*cur != 0))
5956e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	    cur++;
5957ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5958ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        ID = xmlStrndup(ids, cur - ids);
5959e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	if (ID != NULL) {
5960e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	    if (xmlValidateNCName(ID, 1) == 0) {
5961e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard		attr = xmlGetID(doc, ID);
5962e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard		if (attr != NULL) {
5963e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard		    if (attr->type == XML_ATTRIBUTE_NODE)
5964e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard			elem = attr->parent;
5965e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard		    else if (attr->type == XML_ELEMENT_NODE)
5966e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard			elem = (xmlNodePtr) attr;
5967e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard		    else
5968e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard			elem = NULL;
5969e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard		    if (elem != NULL)
5970e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard			xmlXPathNodeSetAdd(ret, elem);
5971e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard		}
5972e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	    }
5973ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlFree(ID);
5974e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	}
5975ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5976ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	while (IS_BLANK(*cur)) cur++;
5977ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ids = cur;
5978ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
5979ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
5980ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
5981ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
5982ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
59833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIdFunction:
59843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
59853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
59863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the id() XPath function
59883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    node-set id(object)
59893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The id function selects elements by their unique ID
59903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set,
59913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the result is the union of the result of applying id to the
59923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string value of each of the nodes in the argument node-set. When the
59933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument to id is of any other type, the argument is converted to a
59943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string as if by a call to the string function; the string is split
59953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * into a whitespace-separated list of tokens (whitespace is any sequence
59963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of characters matching the production S); the result is a node-set
59973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * containing the elements in the same document as the context node that
59983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * have a unique ID equal to any of the tokens in the list.
59993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
60003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
60013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6002ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *tokens;
6003ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodeSetPtr ret;
6004ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr obj;
60053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
60073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    obj = valuePop(ctxt);
60083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
60090c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
6010ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlNodeSetPtr ns;
60113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i;
60123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6013ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNodeSetCreate(NULL);
60143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6015911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	if (obj->nodesetval != NULL) {
6016911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
6017ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		tokens =
6018ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		    xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
6019ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
6020ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		ret = xmlXPathNodeSetMerge(ret, ns);
6021ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		xmlXPathFreeNodeSet(ns);
6022ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		if (tokens != NULL)
6023ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		    xmlFree(tokens);
6024911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    }
60253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
60263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(obj);
6028ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt, xmlXPathWrapNodeSet(ret));
60293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
60303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6031ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    obj = xmlXPathConvertString(obj);
60323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6033ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval);
6034ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
60353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(obj);
60373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return;
60383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
60413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathLocalNameFunction:
60423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
60433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
60443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the local-name() XPath function
60463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string local-name(node-set?)
60473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The local-name function returns a string containing the local part
60483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the name of the node in the argument node-set that is first in
60493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * document order. If the node-set is empty or the first node has no
60503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * name, an empty string is returned. If the argument is omitted it
60513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
60523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
60533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
60543473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
60553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
60563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
60583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
60593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs = 1;
60603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
60633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
60643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
60653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
60663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
60673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
60683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6069911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
60703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
60713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
60723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i = 0; /* Should be first in document order !!!!! */
60733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (cur->nodesetval->nodeTab[i]->type) {
60743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
60753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE:
60763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_PI_NODE:
6077652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	    if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
6078652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		valuePush(ctxt, xmlXPathNewCString(""));
6079652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	    else
6080652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		valuePush(ctxt,
60813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		      xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
60823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
60833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_NAMESPACE_DECL:
60843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewString(
60853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
60863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
60873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
60883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewCString(""));
60893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
60903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
60923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
60953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNamespaceURIFunction:
60963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
60973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
60983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
60993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the namespace-uri() XPath function
61003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string namespace-uri(node-set?)
61013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The namespace-uri function returns a string containing the
61023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace URI of the expanded name of the node in the argument
61033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node-set that is first in document order. If the node-set is empty,
61043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the first node has no name, or the expanded name has no namespace
61053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * URI, an empty string is returned. If the argument is omitted it
61063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
61073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
61083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
61093473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
61103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
61113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
61133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
61143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs = 1;
61153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
61163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
61173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
61183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
61193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
61203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
61213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
61223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6123911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
61243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
61253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
61263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i = 0; /* Should be first in document order !!!!! */
61273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (cur->nodesetval->nodeTab[i]->type) {
61283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
61293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE:
61303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (cur->nodesetval->nodeTab[i]->ns == NULL)
61313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		valuePush(ctxt, xmlXPathNewCString(""));
61323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else
61333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		valuePush(ctxt, xmlXPathNewString(
61343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			  cur->nodesetval->nodeTab[i]->ns->href));
61353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
61363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
61373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewCString(""));
61383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
61393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
61403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
61413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
61423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
61443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNameFunction:
61453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
61463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
61473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the name() XPath function
61493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string name(node-set?)
61503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The name function returns a string containing a QName representing
6151cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * the name of the node in the argument node-set that is first in document
61523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * order. The QName must represent the name with respect to the namespace
61533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * declarations in effect on the node whose name is being represented.
61543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Typically, this will be the form in which the name occurred in the XML
61553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * source. This need not be the case if there are namespace declarations
61563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in effect on the node that associate multiple prefixes with the same
61573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace. However, an implementation may include information about
61583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the original prefix in its representation of nodes; in this case, an
61593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * implementation can ensure that the returned string is always the same
61603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * as the QName used in the XML source. If the argument it omitted it
61613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
61623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Libxml keep the original prefix so the "real qualified name" used is
61633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returned.
61643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
616556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
61660438375d2e6be47d0179826271081ae64df94f8bDaniel VeillardxmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
61670438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard{
61683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
61693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
61710438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
61720438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        nargs = 1;
61733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
61743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
61760438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard    if ((ctxt->value == NULL) ||
61770438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        ((ctxt->value->type != XPATH_NODESET) &&
61780438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard         (ctxt->value->type != XPATH_XSLT_TREE)))
61790438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        XP_ERROR(XPATH_INVALID_TYPE);
61803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
61813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6182911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
61830438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        valuePush(ctxt, xmlXPathNewCString(""));
61843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
61850438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        int i = 0;              /* Should be first in document order !!!!! */
61863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61870438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        switch (cur->nodesetval->nodeTab[i]->type) {
61880438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            case XML_ELEMENT_NODE:
61890438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            case XML_ATTRIBUTE_NODE:
6190652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
6191652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    valuePush(ctxt, xmlXPathNewCString(""));
6192652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
6193652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard                         (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
61940438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    valuePush(ctxt,
6195c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		        xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
61960438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard
6197652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		} else {
6198c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    xmlChar *fullname;
6199c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard
6200c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name,
6201c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard				     cur->nodesetval->nodeTab[i]->ns->prefix,
6202c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard				     NULL, 0);
6203c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    if (fullname == cur->nodesetval->nodeTab[i]->name)
6204c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard			fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
6205c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    if (fullname == NULL) {
6206c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard			XP_ERROR(XPATH_MEMORY_ERROR);
6207c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    }
6208c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard                    valuePush(ctxt, xmlXPathWrapString(fullname));
62090438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                }
62100438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                break;
62110438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            default:
62120438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                valuePush(ctxt,
62130438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                          xmlXPathNewNodeSet(cur->nodesetval->nodeTab[i]));
62140438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                xmlXPathLocalNameFunction(ctxt, 1);
62150438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        }
62163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
62173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
62183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
62193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6220fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
6221fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
62223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringFunction:
62233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
62243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
62253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
62263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the string() XPath function
62273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string string(object?)
62283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * he string function converts an object to a string as follows:
62293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - A node-set is converted to a string by returning the value of
62303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      the node in the node-set that is first in document order.
62313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      If the node-set is empty, an empty string is returned.
62323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - A number is converted to a string as follows
62333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + NaN is converted to the string NaN
62343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + positive zero is converted to the string 0
62353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + negative zero is converted to the string 0
62363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + positive infinity is converted to the string Infinity
62373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + negative infinity is converted to the string -Infinity
62383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + if the number is an integer, the number is represented in
62393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        decimal form as a Number with no decimal point and no leading
62403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        zeros, preceded by a minus sign (-) if the number is negative
62413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + otherwise, the number is represented in decimal form as a
62423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        Number including a decimal point with at least one digit
62433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        before the decimal point and at least one digit after the
62443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        decimal point, preceded by a minus sign (-) if the number
62453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        is negative; there must be no leading zeros before the decimal
6246cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *        point apart possibly from the one required digit immediately
62473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        before the decimal point; beyond the one required digit
62483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        after the decimal point there must be as many, but only as
62493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        many, more digits as are needed to uniquely distinguish the
62503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        number from all other IEEE 754 numeric values.
62513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - The boolean false value is converted to the string false.
62523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      The boolean true value is converted to the string true.
62533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
62543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If the argument is omitted, it defaults to a node-set with the
62553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * context node as its only member.
62563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
62573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
62583473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
62593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
62603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
6262ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt,
6263ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		  xmlXPathWrapString(
6264ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard			xmlXPathCastNodeToString(ctxt->context->node)));
6265ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return;
62663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
62673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
62693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
62703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
6271fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertString(cur);
6272fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
62733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
62743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
62763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringLengthFunction:
62773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
62783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
62793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
62803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the string-length() XPath function
62813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number string-length(string?)
62823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The string-length returns the number of characters in the string
62833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (see [3.6 Strings]). If the argument is omitted, it defaults to
62843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node converted to a string, in other words the value
62853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node.
62863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
62873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
62883473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
62893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
62903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
62923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) {
62933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(0));
62943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
62953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlChar *content;
62963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6297ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    content = xmlXPathCastNodeToString(ctxt->context->node);
6298e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard	    valuePush(ctxt, xmlXPathNewFloat(xmlUTF8Strlen(content)));
62993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(content);
63003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
63013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
63023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
63043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
63053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
63063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
6307e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    valuePush(ctxt, xmlXPathNewFloat(xmlUTF8Strlen(cur->stringval)));
63083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
63093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
63123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathConcatFunction:
63133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
63153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the concat() XPath function
63173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string concat(string, string, string*)
63183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The concat function returns the concatenation of its arguments.
63193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
63203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
63213473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
63223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur, newobj;
63233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *tmp;
63243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs < 2) {
63263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(2);
63273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
63303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
63313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur == NULL) || (cur->type != XPATH_STRING)) {
63323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(cur);
63333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
63343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    nargs--;
63363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (nargs > 0) {
63383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CAST_TO_STRING;
63393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	newobj = valuePop(ctxt);
63403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((newobj == NULL) || (newobj->type != XPATH_STRING)) {
63413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(newobj);
63423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(cur);
63433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_INVALID_TYPE);
63443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
63453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	tmp = xmlStrcat(newobj->stringval, cur->stringval);
63463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	newobj->stringval = cur->stringval;
63473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->stringval = tmp;
63483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(newobj);
63503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs--;
63513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, cur);
63533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
63563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathContainsFunction:
63573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
63593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the contains() XPath function
63613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean contains(string, string)
63623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The contains function returns true if the first argument string
63633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * contains the second argument string, and otherwise returns false.
63643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
63653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
63663473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
63673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr hay, needle;
63683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(2);
63703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
63713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
63723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    needle = valuePop(ctxt);
63733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
63743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    hay = valuePop(ctxt);
63753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((hay == NULL) || (hay->type != XPATH_STRING)) {
63763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(hay);
63773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(needle);
63783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
63793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrstr(hay->stringval, needle->stringval))
63813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(1));
63823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
63833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(0));
63843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(hay);
63853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(needle);
63863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
63893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStartsWithFunction:
63903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
63923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the starts-with() XPath function
63943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean starts-with(string, string)
63953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The starts-with function returns true if the first argument string
63963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * starts with the second argument string, and otherwise returns false.
63973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
63983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
63993473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
64003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr hay, needle;
64013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int n;
64023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(2);
64043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
64053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
64063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    needle = valuePop(ctxt);
64073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
64083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    hay = valuePop(ctxt);
64093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((hay == NULL) || (hay->type != XPATH_STRING)) {
64103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(hay);
64113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(needle);
64123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
64133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
64143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = xmlStrlen(needle->stringval);
64153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrncmp(hay->stringval, needle->stringval, n))
64163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(0));
64173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
64183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(1));
64193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(hay);
64203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(needle);
64213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
64223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
64243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringFunction:
64253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
64263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
64273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
64283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring() XPath function
64293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring(string, number, number?)
64303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring function returns the substring of the first argument
64313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * starting at the position specified in the second argument with
64323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * length specified in the third argument. For example,
64333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * substring("12345",2,3) returns "234". If the third argument is not
64343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * specified, it returns the substring starting at the position specified
64353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in the second argument and continuing to the end of the string. For
64363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * example, substring("12345",2) returns "2345".  More precisely, each
64373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character in the string (see [3.6 Strings]) is considered to have a
64383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * numeric position: the position of the first character is 1, the position
64393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the second character is 2 and so on. The returned substring contains
64403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * those characters for which the position of the character is greater than
64413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * or equal to the second argument and, if the third argument is specified,
64423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * less than the sum of the second and third arguments; the comparisons
64433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and addition used for the above follow the standard IEEE 754 rules. Thus:
64443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 1.5, 2.6) returns "234"
64453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 0, 3) returns "12"
64463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 0 div 0, 3) returns ""
64473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 1, 0 div 0) returns ""
64483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", -42, 1 div 0) returns "12345"
64493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", -1 div 0, 1 div 0) returns ""
64503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
64513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
64523473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
64533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr str, start, len;
645497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    double le=0, in;
645597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    int i, l, m;
64563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret;
64573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs < 2) {
64593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(2);
64603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
64613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs > 3) {
64623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(3);
64633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
646497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    /*
646597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     * take care of possible last (position) argument
646697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    */
64673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 3) {
64683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CAST_TO_NUMBER;
64693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_TYPE(XPATH_NUMBER);
64703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len = valuePop(ctxt);
64713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	le = len->floatval;
64723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(len);
64733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
647497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
64753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
64763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
64773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    start = valuePop(ctxt);
64783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    in = start->floatval;
64793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(start);
64803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
64813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
64823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    str = valuePop(ctxt);
648397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    m = xmlUTF8Strlen((const unsigned char *)str->stringval);
648497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
648597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    /*
648697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     * If last pos not present, calculate last position
648797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    */
64889e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    if (nargs != 3) {
64899e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	le = (double)m;
64909e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	if (in < 1.0)
64919e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    in = 1.0;
64929e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    }
649397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
64940eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    /* Need to check for the special cases where either
64950eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard     * the index is NaN, the length is NaN, or both
64960eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard     * arguments are infinity (relying on Inf + -Inf = NaN)
649797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     */
64989e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    if (!xmlXPathIsNaN(in + le) && !xmlXPathIsInf(in)) {
64990eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        /*
65009e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard         * To meet the requirements of the spec, the arguments
65019e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * must be converted to integer format before
65029e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * initial index calculations are done
65030eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard         *
65049e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard         * First we go to integer form, rounding up
65059e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * and checking for special cases
65060eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard         */
65070eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        i = (int) in;
65089e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (((double)i)+0.5 <= in) i++;
65099e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard
65109e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	if (xmlXPathIsInf(le) == 1) {
65119e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = m;
65129e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    if (i < 1)
65139e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard		i = 1;
65149e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	}
65159e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	else if (xmlXPathIsInf(le) == -1 || le < 0.0)
65169e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = 0;
65179e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	else {
65189e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = (int) le;
65199e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    if (((double)l)+0.5 <= le) l++;
65209e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	}
65210eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard
65229e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	/* Now we normalize inidices */
65239e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        i -= 1;
65249e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        l += i;
65259e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (i < 0)
65269e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard            i = 0;
65279e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (l > m)
65289e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard            l = m;
65293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65300eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        /* number of chars to copy */
65310eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        l -= i;
65323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65330eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        ret = xmlUTF8Strsub(str->stringval, i, l);
65340eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    }
65350eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    else {
65360eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        ret = NULL;
65370eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    }
65383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL)
65403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
65413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
65423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewString(ret));
65433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(ret);
65443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
654597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
65463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(str);
65473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
65483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringBeforeFunction:
65513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring-before() XPath function
65553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring-before(string, string)
65563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring-before function returns the substring of the first
65573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string that precedes the first occurrence of the second
65583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string in the first argument string, or the empty string
65593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if the first argument string does not contain the second argument
65603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, substring-before("1999/04/01","/") returns 1999.
65613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr str;
65653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr find;
65663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
65673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  const xmlChar *point;
65683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  int offset;
65693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(2);
65713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
65723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  find = valuePop(ctxt);
65733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
65743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  str = valuePop(ctxt);
65753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
65773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target) {
65783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    point = xmlStrstr(str->stringval, find->stringval);
65793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (point) {
65803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      offset = (int)(point - str->stringval);
65813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      xmlBufferAdd(target, str->stringval, offset);
65823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
65833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
65843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
65853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
65863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(str);
65883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(find);
65893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
65903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringAfterFunction:
65933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring-after() XPath function
65973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring-after(string, string)
65983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring-after function returns the substring of the first
65993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string that follows the first occurrence of the second
66003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string in the first argument string, or the empty stringi
66013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if the first argument string does not contain the second argument
66023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, substring-after("1999/04/01","/") returns 04/01,
66033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and substring-after("1999/04/01","19") returns 99/04/01.
66043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
66053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
66063473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
66073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr str;
66083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr find;
66093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
66103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  const xmlChar *point;
66113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  int offset;
66123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(2);
66143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
66153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  find = valuePop(ctxt);
66163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
66173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  str = valuePop(ctxt);
66183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
66203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target) {
66213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    point = xmlStrstr(str->stringval, find->stringval);
66223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (point) {
66233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
66243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      xmlBufferAdd(target, &str->stringval[offset],
66253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   xmlStrlen(str->stringval) - offset);
66263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
66283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
66293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
66303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(str);
66323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(find);
66333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNormalizeFunction:
66373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
66383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
66393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
66403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the normalize-space() XPath function
66413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string normalize-space(string?)
66423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The normalize-space function returns the argument string with white
66433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * space normalized by stripping leading and trailing whitespace
66443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and replacing sequences of whitespace characters by a single
66453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * space. Whitespace characters are the same allowed by the S production
66463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in XML. If the argument is omitted, it defaults to the context
66473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node converted to a string, in other words the value of the context node.
66483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
66493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
66503473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
66513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr obj = NULL;
66523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlChar *source = NULL;
66533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
66543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlChar blank;
66553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (nargs == 0) {
66573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Use current context node */
6658ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    valuePush(ctxt,
6659ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	      xmlXPathWrapString(
6660ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		  xmlXPathCastNodeToString(ctxt->context->node)));
66613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    nargs = 1;
66623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
66633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(1);
66653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
66663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_TYPE(XPATH_STRING);
66673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  obj = valuePop(ctxt);
66683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  source = obj->stringval;
66693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
66713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target && source) {
66723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Skip leading whitespaces */
66743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (IS_BLANK(*source))
66753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      source++;
66763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Collapse intermediate whitespaces, and skip trailing whitespaces */
66783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    blank = 0;
66793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (*source) {
66803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      if (IS_BLANK(*source)) {
668197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	blank = 0x20;
66823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      } else {
66833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (blank) {
66843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	  xmlBufferAdd(target, &blank, 1);
66853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	  blank = 0;
66863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
66873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlBufferAdd(target, source, 1);
66883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      }
66893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      source++;
66903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
66933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
66943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
66953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(obj);
66963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathTranslateFunction:
67003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
67013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
67023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
67033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the translate() XPath function
67043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string translate(string, string, string)
67053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The translate function returns the first argument string with
67063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * occurrences of characters in the second argument string replaced
67073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by the character at the corresponding position in the third argument
67083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, translate("bar","abc","ABC") returns the string
67093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * BAr. If there is a character in the second argument string with no
67103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character at a corresponding position in the third argument string
67113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (because the second argument string is longer than the third argument
67123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string), then occurrences of that character in the first argument
67133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string are removed. For example, translate("--aaa--","abc-","ABC")
67143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns "AAA". If a character occurs more than once in second
67153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string, then the first occurrence determines the replacement
67163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character. If the third argument string is longer than the second
67173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string, then excess characters are ignored.
67183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
67193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
67203473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6721e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr str;
6722e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr from;
6723e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr to;
6724e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlBufferPtr target;
672597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    int offset, max;
6726e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlChar ch;
672797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    xmlChar *point;
672897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    xmlChar *cptr;
67293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6730e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CHECK_ARITY(3);
67313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6732e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6733e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    to = valuePop(ctxt);
6734e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6735e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    from = valuePop(ctxt);
6736e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6737e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    str = valuePop(ctxt);
67383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6739e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    target = xmlBufferCreate();
6740e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    if (target) {
674197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	max = xmlUTF8Strlen(to->stringval);
674297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	for (cptr = str->stringval; (ch=*cptr); ) {
674397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    offset = xmlUTF8Strloc(from->stringval, cptr);
674497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    if (offset >= 0) {
674597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if (offset < max) {
674697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    point = xmlUTF8Strpos(to->stringval, offset);
674797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    if (point)
674897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1));
674997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		}
675097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    } else
675197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
675297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
675397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    /* Step to next character in input */
675497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    cptr++;
675597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    if ( ch & 0x80 ) {
675697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		/* if not simple ascii, verify proper format */
675797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if ( (ch & 0xc0) != 0xc0 ) {
675897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    xmlGenericError(xmlGenericErrorContext,
675997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			"xmlXPathTranslateFunction: Invalid UTF8 string\n");
676097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    break;
676197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		}
676297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		/* then skip over remaining bytes for this char */
676397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		while ( (ch <<= 1) & 0x80 )
676497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    if ( (*cptr++ & 0xc0) != 0x80 ) {
676597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			xmlGenericError(xmlGenericErrorContext,
676697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			    "xmlXPathTranslateFunction: Invalid UTF8 string\n");
676797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			break;
676897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    }
676997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if (ch & 0x80) /* must have had error encountered */
677097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    break;
677197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    }
6772e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard	}
67733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6774e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
6775e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlBufferFree(target);
6776e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(str);
6777e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(from);
6778e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(to);
67793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
67803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
6782fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathBooleanFunction:
6783fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath Parser context
6784fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @nargs:  the number of arguments
6785fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
6786fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Implement the boolean() XPath function
6787fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    boolean boolean(object)
6788fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * he boolean function converts its argument to a boolean as follows:
6789fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a number is true if and only if it is neither positive or
6790fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *      negative zero nor NaN
6791fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a node-set is true if and only if it is non-empty
6792fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a string is true if and only if its length is non-zero
6793fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
6794fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardvoid
6795fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6796fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    xmlXPathObjectPtr cur;
6797fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
6798fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    CHECK_ARITY(1);
6799fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = valuePop(ctxt);
6800fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
6801fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertBoolean(cur);
6802fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
68033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNotFunction:
68073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the not() XPath function
68113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean not(boolean)
68123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The not function returns true if its argument is false,
68133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and false otherwise.
68143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
68163473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
68173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
68183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_BOOLEAN;
68193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_BOOLEAN);
68203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->value->boolval = ! ctxt->value->boolval;
68213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathTrueFunction:
68253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the true() XPath function
68293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean true()
68303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
68323473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
68333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(0);
68343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(1));
68353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFalseFunction:
68393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the false() XPath function
68433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean false()
68443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
68463473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
68473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(0);
68483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(0));
68493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathLangFunction:
68533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the lang() XPath function
68573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean lang(string)
68583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The lang function returns true or false depending on whether the
68593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * language of the context node as specified by xml:lang attributes
68603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is the same as or is a sublanguage of the language specified by
68613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the argument string. The language of the context node is determined
68623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by the value of the xml:lang attribute on the context node, or, if
68633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node has no xml:lang attribute, by the value of the
68643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xml:lang attribute on the nearest ancestor of the context node that
68653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * has an xml:lang attribute. If there is no such attribute, then lang
68663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns false. If there is such an attribute, then lang returns
68673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * true if the attribute value is equal to the argument ignoring case,
68683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * or if there is some suffix starting with - such that the attribute
68693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * value is equal to the argument ignoring that suffix of the attribute
68703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * value and ignoring case.
68713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
68733473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
68743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr val;
68753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *theLang;
68763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *lang;
68773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
68783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
68793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
68813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
68823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
68833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    val = valuePop(ctxt);
68843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    lang = val->stringval;
68853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    theLang = xmlNodeGetLang(ctxt->context->node);
68863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((theLang != NULL) && (lang != NULL)) {
68873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        for (i = 0;lang[i] != 0;i++)
68883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (toupper(lang[i]) != toupper(theLang[i]))
68893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        goto not_equal;
68903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret = 1;
68913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
68923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylornot_equal:
68933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(val);
68943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(ret));
68953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNumberFunction:
68993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
69013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the number() XPath function
69033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number number(object?)
69043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
69063473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
69073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
69083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double res;
69093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
69113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) {
69123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(0.0));
69133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
69143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlChar* content = xmlNodeGetContent(ctxt->context->node);
69153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res = xmlXPathStringEvalNumber(content);
69173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(res));
69183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(content);
69193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
69203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
69213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
69223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
69243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
6925fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertNumber(cur);
6926fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
69273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
69283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
69303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSumFunction:
69313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
69333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the sum() XPath function
69353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number sum(node-set)
69363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The sum function returns the sum of the values of the nodes in
69373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the argument node-set.
69383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
69403473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
69413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
69423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
6943ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double res = 0.0;
69443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
69463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
69473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
69483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
69493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
69503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
69513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6952d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
69533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewFloat(0.0));
69543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
6955ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	for (i = 0; i < cur->nodesetval->nodeNr; i++) {
6956ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]);
69573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
6958ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat(res));
69593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
69603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
69613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
69623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
69643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFloorFunction:
69653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
69673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the floor() XPath function
69693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number floor(number)
69703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The floor function returns the largest (closest to positive infinity)
69713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number that is not greater than the argument and that is an integer.
69723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
69743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
697556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    double f;
697656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard
69773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
69783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
69793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
698056cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard
698156cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    f = (double)((int) ctxt->value->floatval);
698256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (f != ctxt->value->floatval) {
698356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval > 0)
698456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
698556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
698656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f - 1;
698756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
69883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
69893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
69913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCeilingFunction:
69923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
69943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the ceiling() XPath function
69963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number ceiling(number)
69973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The ceiling function returns the smallest (closest to negative infinity)
69983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number that is not less than the argument and that is an integer.
69993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
70003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
70013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
70023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double f;
70033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
70053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
70063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
70073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if 0
70093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->value->floatval = ceil(ctxt->value->floatval);
70103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else
70113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    f = (double)((int) ctxt->value->floatval);
701256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (f != ctxt->value->floatval) {
701356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval > 0)
701456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f + 1;
70155fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else {
70165fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    if (ctxt->value->floatval < 0 && f == 0)
70175fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	        ctxt->value->floatval = xmlXPathNZERO;
70185fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    else
70195fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	        ctxt->value->floatval = f;
70205fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	}
70215fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
702256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
70233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
70243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
70253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
70273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRoundFunction:
70283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
70293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
70303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
70313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the round() XPath function
70323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number round(number)
70333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The round function returns the number that is closest to the
70343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument and that is an integer. If there are two such numbers,
70353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the one that is even is returned.
70363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
70373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
70383473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
70393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double f;
70403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
70423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
70433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
70443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7045cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    if ((xmlXPathIsNaN(ctxt->value->floatval)) ||
7046cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	(xmlXPathIsInf(ctxt->value->floatval) == 1) ||
7047cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	(xmlXPathIsInf(ctxt->value->floatval) == -1) ||
70483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->value->floatval == 0.0))
70493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
70503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    f = (double)((int) ctxt->value->floatval);
705256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (ctxt->value->floatval < 0) {
705356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval < f - 0.5)
705456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f - 1;
705556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
705656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
70575fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (ctxt->value->floatval == 0)
70585fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNZERO;
705956cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    } else {
706056cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval < f + 0.5)
706156cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
706256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
706356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f + 1;
706456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
70653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
70663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
70683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
70693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			The Parser					*
70703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
70713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
70723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
70743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * a couple of forward declarations since we use a recursive call based
70753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * implementation.
70763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7077afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt);
7078d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardstatic void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
7079afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
7080afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt);
70812156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillardstatic xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,
70822156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	                                  int qualified);
70833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
708561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * xmlXPathCurrentChar:
708661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @ctxt:  the XPath parser context
708761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @cur:  pointer to the beginning of the char
708861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @len:  pointer to the length of the char read
708961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard *
7090cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * The current char value, if using UTF-8 this may actually span multiple
709161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * bytes in the input buffer.
709261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard *
709360087f30f3b4cf21de48f39181736e7d71e7a661Daniel Veillard * Returns the current char value and its length
709461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard */
709561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
709661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardstatic int
709761d80a2822b2678dee885ac2850295cc96277c63Daniel VeillardxmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
709861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    unsigned char c;
709961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    unsigned int val;
710061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    const xmlChar *cur;
710161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
710261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (ctxt == NULL)
710361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(0);
710461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    cur = ctxt->cur;
710561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
710661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
710761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * We are supposed to handle UTF8, check it's valid
710861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * From rfc2044: encoding of the Unicode values on UTF-8:
710961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     *
711061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
711161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0000-0000 007F   0xxxxxxx
711261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
711361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
711461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     *
711561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Check for the 0x110000 limit too
711661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
711761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    c = *cur;
711861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (c & 0x80) {
711961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if ((cur[1] & 0xc0) != 0x80)
712061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    goto encoding_error;
712161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if ((c & 0xe0) == 0xe0) {
712261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
712361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if ((cur[2] & 0xc0) != 0x80)
712461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		goto encoding_error;
712561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if ((c & 0xf0) == 0xf0) {
712661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		if (((c & 0xf8) != 0xf0) ||
712761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    ((cur[3] & 0xc0) != 0x80))
712861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    goto encoding_error;
712961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		/* 4-byte code */
713061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		*len = 4;
713161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val = (cur[0] & 0x7) << 18;
713261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[1] & 0x3f) << 12;
713361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[2] & 0x3f) << 6;
713461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= cur[3] & 0x3f;
713561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    } else {
713661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	      /* 3-byte code */
713761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		*len = 3;
713861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val = (cur[0] & 0xf) << 12;
713961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[1] & 0x3f) << 6;
714061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= cur[2] & 0x3f;
714161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
714261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	} else {
714361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	  /* 2-byte code */
714461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    *len = 2;
714561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    val = (cur[0] & 0x1f) << 6;
714661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    val |= cur[1] & 0x3f;
714761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
714861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if (!IS_CHAR(val)) {
714961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    XP_ERROR0(XPATH_INVALID_CHAR_ERROR);
715061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
715161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(val);
715261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    } else {
715361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	/* 1-byte code */
715461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	*len = 1;
715561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return((int) *cur);
715661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
715761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardencoding_error:
715861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
715961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * If we detect an UTF8 error that probably mean that the
716061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * input encoding didn't get properly advertized in the
716161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * declaration header. Report the error and switch the encoding
716261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * to ISO-Latin-1 (if you don't like this policy, just declare the
716361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * encoding !)
716461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
716542596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard    *len = 0;
716661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    XP_ERROR0(XPATH_ENCODING_ERROR);
716761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
716861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
716961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard/**
71703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseNCName:
71713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
71723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML namespace non qualified name.
71743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
71763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
71783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                       CombiningChar | Extender
71793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the namespace name or NULL
71813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
71823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71833473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
71843473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
71852156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    const xmlChar *in;
71862156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    xmlChar *ret;
71872156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    int count = 0;
71883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71892156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    /*
71902156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard     * Accelerator for simple ASCII names
71912156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard     */
71922156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    in = ctxt->cur;
71932156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    if (((*in >= 0x61) && (*in <= 0x7A)) ||
71942156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	((*in >= 0x41) && (*in <= 0x5A)) ||
71952156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	(*in == '_')) {
71962156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	in++;
71972156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	while (((*in >= 0x61) && (*in <= 0x7A)) ||
71982156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	       ((*in >= 0x41) && (*in <= 0x5A)) ||
71992156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	       ((*in >= 0x30) && (*in <= 0x39)) ||
72009a89a8ab80bc021deec9da7d79bda20995c4e78dDaniel Veillard	       (*in == '_') || (*in == '.') ||
72019a89a8ab80bc021deec9da7d79bda20995c4e78dDaniel Veillard	       (*in == '-'))
72022156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    in++;
72032156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	if ((*in == ' ') || (*in == '>') || (*in == '/') ||
72042156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard            (*in == '[') || (*in == ']') || (*in == ':') ||
72052156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard            (*in == '@') || (*in == '*')) {
72062156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    count = in - ctxt->cur;
72072156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (count == 0)
72082156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		return(NULL);
72092156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    ret = xmlStrndup(ctxt->cur, count);
72102156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    ctxt->cur = in;
72112156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    return(ret);
72122156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	}
72132156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    }
72142156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    return(xmlXPathParseNameComplex(ctxt, 0));
72153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
72163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72172156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard
72183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
72193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseQName:
72203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
72213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  a xmlChar **
72223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML qualified name
72243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 5] QName ::= (Prefix ':')? LocalPart
72263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 6] Prefix ::= NCName
72283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 7] LocalPart ::= NCName
72303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the function returns the local part, and prefix is updated
72323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   to get the Prefix if any.
72333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
72343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
723556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
72363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
72373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret = NULL;
72383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *prefix = NULL;
72403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = xmlXPathParseNCName(ctxt);
72413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == ':') {
72423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        *prefix = ret;
72433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
72443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = xmlXPathParseNCName(ctxt);
72453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
72463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
72473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
72483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
72503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseName:
72513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
72523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML name
72543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
72563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  CombiningChar | Extender
72573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] Name ::= (Letter | '_' | ':') (NameChar)*
72593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the namespace name or NULL
72613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
72623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72633473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
72643473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseName(xmlXPathParserContextPtr ctxt) {
726561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    const xmlChar *in;
726661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    xmlChar *ret;
726761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int count = 0;
72683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
726961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
727061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Accelerator for simple ASCII names
727161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
727261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    in = ctxt->cur;
727361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (((*in >= 0x61) && (*in <= 0x7A)) ||
727461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	((*in >= 0x41) && (*in <= 0x5A)) ||
727561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	(*in == '_') || (*in == ':')) {
727661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	in++;
727761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	while (((*in >= 0x61) && (*in <= 0x7A)) ||
727861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	       ((*in >= 0x41) && (*in <= 0x5A)) ||
727961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	       ((*in >= 0x30) && (*in <= 0x39)) ||
728076d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	       (*in == '_') || (*in == '-') ||
728176d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	       (*in == ':') || (*in == '.'))
728261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    in++;
728376d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	if ((*in > 0) && (*in < 0x80)) {
728461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    count = in - ctxt->cur;
728561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    ret = xmlStrndup(ctxt->cur, count);
728661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    ctxt->cur = in;
728761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    return(ret);
728861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
728961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
72902156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    return(xmlXPathParseNameComplex(ctxt, 1));
729161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
72923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
729361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardstatic xmlChar *
72942156a56bcbf5d83fb3d694123be01beebf84d273Daniel VeillardxmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
729561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    xmlChar buf[XML_MAX_NAMELEN + 5];
729661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int len = 0, l;
729761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int c;
72983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
729961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
730061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Handler for more complex cases
730161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
730261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    c = CUR_CHAR(l);
730361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
73042156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard        (c == '[') || (c == ']') || (c == '@') || /* accelerators */
73052156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard        (c == '*') || /* accelerators */
730661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	(!IS_LETTER(c) && (c != '_') &&
73072156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard         ((qualified) && (c != ':')))) {
730861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(NULL);
730961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
73103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
731161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
731261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
731361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard            (c == '.') || (c == '-') ||
73142156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    (c == '_') || ((qualified) && (c == ':')) ||
731561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    (IS_COMBINING(c)) ||
731661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    (IS_EXTENDER(c)))) {
731761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	COPY_BUF(l,buf,len,c);
731861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	NEXTL(l);
731961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	c = CUR_CHAR(l);
732061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if (len >= XML_MAX_NAMELEN) {
732161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    /*
732261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     * Okay someone managed to make a huge name, so he's ready to pay
732361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     * for the processing speed.
732461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     */
732561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    xmlChar *buffer;
732661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    int max = len * 2;
732761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
73283c908dca479ed50dca24b8593bca90e40dbde6b8Daniel Veillard	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
732961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if (buffer == NULL) {
733061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		XP_ERROR0(XPATH_MEMORY_ERROR);
733161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
733261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    memcpy(buffer, buf, len);
733361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
733461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (c == '.') || (c == '-') ||
73352156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		   (c == '_') || ((qualified) && (c == ':')) ||
733661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (IS_COMBINING(c)) ||
733761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (IS_EXTENDER(c))) {
733861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		if (len + 10 > max) {
733961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    max *= 2;
734061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    buffer = (xmlChar *) xmlRealloc(buffer,
734161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard			                            max * sizeof(xmlChar));
734261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    if (buffer == NULL) {
734361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard			XP_ERROR0(XPATH_MEMORY_ERROR);
734461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    }
734561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		}
734661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		COPY_BUF(l,buffer,len,c);
734761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		NEXTL(l);
734861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		c = CUR_CHAR(l);
734961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
735061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    buffer[len] = 0;
735161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    return(buffer);
735261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
735361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
73542156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    if (len == 0)
73552156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	return(NULL);
735661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    return(xmlStrndup(buf, len));
735761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
73583cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
73593cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard#define MAX_FRAC 20
73603cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
73613cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillardstatic double my_pow10[MAX_FRAC] = {
73623cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1.0, 10.0, 100.0, 1000.0, 10000.0,
73633cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0,
73643cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,
73653cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    100000000000000.0,
73663cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1000000000000000.0, 10000000000000000.0, 100000000000000000.0,
73673cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1000000000000000000.0, 10000000000000000000.0
73683cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard};
73693cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
73703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
73713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringEvalNumber:
73723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  A string to scan
73733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
737470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese *  [30a]  Float  ::= Number ('e' Digits?)?
737570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese *
73763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [30]   Number ::=   Digits ('.' Digits?)?
73773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | '.' Digits
73783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [31]   Digits ::=   [0-9]+
73793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7380afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Number in the string
73813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * In complement of the Number expression, this function also handles
73823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * negative values : '-' Number.
73833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
73843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the double value.
73853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
73863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble
73873473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringEvalNumber(const xmlChar *str) {
73883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *cur = str;
73897b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double ret;
7390b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    int ok = 0;
73913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int isneg = 0;
739270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int exponent = 0;
739370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int is_exponent_negative = 0;
7394b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#ifdef __GNUC__
7395b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    unsigned long tmp = 0;
73967b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double temp;
7397b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#endif
7398eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (cur == NULL) return(0);
73993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (IS_BLANK(*cur)) cur++;
74003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) {
74013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(xmlXPathNAN);
74023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == '-') {
74043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	isneg = 1;
74053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur++;
74063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7407b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard
7408b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#ifdef __GNUC__
7409d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard    /*
74107b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * tmp/temp is a workaround against a gcc compiler bug
74117b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * http://veillard.com/gcc.bug
7412d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard     */
74137b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
74143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((*cur >= '0') && (*cur <= '9')) {
74157b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10;
74167b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	tmp = (*cur - '0');
74173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ok = 1;
74183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur++;
74197b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	temp = (double) tmp;
74207b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret + temp;
74213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7422b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#else
74237b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
7424b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    while ((*cur >= '0') && (*cur <= '9')) {
7425b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	ret = ret * 10 + (*cur - '0');
7426b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	ok = 1;
7427b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	cur++;
7428b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    }
7429b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#endif
7430d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard
74313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == '.') {
74323cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	int v, frac = 0;
74333cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	double fraction = 0;
74343cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
74353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur++;
74363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (((*cur < '0') || (*cur > '9')) && (!ok)) {
74373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathNAN);
74383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
74393cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	while (((*cur >= '0') && (*cur <= '9')) && (frac < MAX_FRAC)) {
74403cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    v = (*cur - '0');
74413cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    fraction = fraction * 10 + v;
74423cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    frac = frac + 1;
74433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur++;
74443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
74453cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	fraction /= my_pow10[frac];
74463cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	ret = ret + fraction;
74473cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	while ((*cur >= '0') && (*cur <= '9'))
74483cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    cur++;
74493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
745070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if ((*cur == 'e') || (*cur == 'E')) {
745170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      cur++;
745270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      if (*cur == '-') {
745370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	is_exponent_negative = 1;
745470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	cur++;
745570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      }
745670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      while ((*cur >= '0') && (*cur <= '9')) {
745770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	exponent = exponent * 10 + (*cur - '0');
745870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	cur++;
745970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      }
746070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    }
74613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (IS_BLANK(*cur)) cur++;
74623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur != 0) return(xmlXPathNAN);
74633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (isneg) ret = -ret;
746470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if (is_exponent_negative) exponent = -exponent;
746570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    ret *= pow(10.0, (double)exponent);
74663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
74673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
74683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7470afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompNumber:
74713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
74723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [30]   Number ::=   Digits ('.' Digits?)?
74743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | '.' Digits
74753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [31]   Digits ::=   [0-9]+
74763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7477afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Number, then push it on the stack
74783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7480afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7481d79bcd1b36412a7996ace1900ab613e38a609b60Daniel VeillardxmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
7482d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard{
74833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double ret = 0.0;
74843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double mult = 1;
74857b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    int ok = 0;
748670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int exponent = 0;
748770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int is_exponent_negative = 0;
74887b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#ifdef __GNUC__
74897b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    unsigned long tmp = 0;
74907b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double temp;
74917b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#endif
74923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
74943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
74953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        XP_ERROR(XPATH_NUMBER_ERROR);
74963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74977b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#ifdef __GNUC__
7498d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard    /*
74997b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * tmp/temp is a workaround against a gcc compiler bug
75007b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * http://veillard.com/gcc.bug
7501d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard     */
75027b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
75033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR >= '0') && (CUR <= '9')) {
75047b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10;
75057b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	tmp = (CUR - '0');
7506d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        ok = 1;
7507d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        NEXT;
75087b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	temp = (double) tmp;
75097b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret + temp;
75103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
75117b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#else
75127b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
75137b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    while ((CUR >= '0') && (CUR <= '9')) {
75147b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10 + (CUR - '0');
75157b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ok = 1;
75167b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	NEXT;
75177b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    }
75187b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#endif
75193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '.') {
75203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
7521d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (((CUR < '0') || (CUR > '9')) && (!ok)) {
7522d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            XP_ERROR(XPATH_NUMBER_ERROR);
7523d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
7524d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        while ((CUR >= '0') && (CUR <= '9')) {
7525d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            mult /= 10;
7526d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            ret = ret + (CUR - '0') * mult;
7527d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
7528d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
75293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
753070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if ((CUR == 'e') || (CUR == 'E')) {
7531d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        NEXT;
7532d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (CUR == '-') {
7533d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            is_exponent_negative = 1;
7534d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
7535d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
7536d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        while ((CUR >= '0') && (CUR <= '9')) {
7537d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            exponent = exponent * 10 + (CUR - '0');
7538d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
7539d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
7540d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (is_exponent_negative)
7541d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            exponent = -exponent;
7542d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        ret *= pow(10.0, (double) exponent);
754370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    }
75449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0,
7545d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard                   xmlXPathNewFloat(ret), NULL);
75463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
75473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7549fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathParseLiteral:
7550fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath Parser context
7551fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7552fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Parse a Literal
7553fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7554fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *  [29]   Literal ::=   '"' [^"]* '"'
7555fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *                    | "'" [^']* "'"
7556fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7557fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Returns the value found or NULL in case of error
7558fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
7559fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardstatic xmlChar *
7560fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
7561fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    const xmlChar *q;
7562fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    xmlChar *ret = NULL;
7563fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
7564fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (CUR == '"') {
7565fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        NEXT;
7566fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	q = CUR_PTR;
756734ba38793669da505d735e76794253b23dec447cDaniel Veillard	while ((IS_CHAR((unsigned int) CUR)) && (CUR != '"'))
7568fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
756934ba38793669da505d735e76794253b23dec447cDaniel Veillard	if (!IS_CHAR((unsigned int) CUR)) {
7570fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    XP_ERROR0(XPATH_UNFINISHED_LITERAL_ERROR);
7571fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	} else {
7572fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    ret = xmlStrndup(q, CUR_PTR - q);
7573fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
7574fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        }
7575fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    } else if (CUR == '\'') {
7576fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        NEXT;
7577fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	q = CUR_PTR;
757834ba38793669da505d735e76794253b23dec447cDaniel Veillard	while ((IS_CHAR((unsigned int) CUR)) && (CUR != '\''))
7579fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
758034ba38793669da505d735e76794253b23dec447cDaniel Veillard	if (!IS_CHAR((unsigned int) CUR)) {
7581fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    XP_ERROR0(XPATH_UNFINISHED_LITERAL_ERROR);
7582fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	} else {
7583fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    ret = xmlStrndup(q, CUR_PTR - q);
7584fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
7585fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        }
7586fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    } else {
7587fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	XP_ERROR0(XPATH_START_LITERAL_ERROR);
7588fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    }
7589fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    return(ret);
7590fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard}
7591fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
7592fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
7593afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompLiteral:
75943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
75953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Parse a Literal and push it on the stack.
75973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [29]   Literal ::=   '"' [^"]* '"'
75993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | "'" [^']* "'"
76003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7601afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * TODO: xmlXPathCompLiteral memory allocation could be improved.
76023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7603afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7604afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
76053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *q;
76063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret = NULL;
76073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '"') {
76093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
76103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	q = CUR_PTR;
761134ba38793669da505d735e76794253b23dec447cDaniel Veillard	while ((IS_CHAR((unsigned int) CUR)) && (CUR != '"'))
76123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
761334ba38793669da505d735e76794253b23dec447cDaniel Veillard	if (!IS_CHAR((unsigned int) CUR)) {
76143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
76153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
76163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlStrndup(q, CUR_PTR - q);
76173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
76183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
76193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '\'') {
76203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
76213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	q = CUR_PTR;
762234ba38793669da505d735e76794253b23dec447cDaniel Veillard	while ((IS_CHAR((unsigned int) CUR)) && (CUR != '\''))
76233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
762434ba38793669da505d735e76794253b23dec447cDaniel Veillard	if (!IS_CHAR((unsigned int) CUR)) {
76253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
76263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
76273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlStrndup(q, CUR_PTR - q);
76283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
76293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
76303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
76313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_START_LITERAL_ERROR);
76323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
76333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) return;
76349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0,
76359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           xmlXPathNewString(ret), NULL);
76363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ret);
76373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
76383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7640afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompVariableReference:
76413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
76423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
76433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Parse a VariableReference, evaluate it and push it on the stack.
76443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
76453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The variable bindings consist of a mapping from variable names
76463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to variable values. The value of a variable is an object, which
76473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of any of the types that are possible for the value of an expression,
76483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and may also be of additional types not specified here.
76493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
76503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Early evaluation is possible since:
76513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The variable bindings [...] used to evaluate a subexpression are
76523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * always the same as those used to evaluate the containing expression.
76533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
76543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [36]   VariableReference ::=   '$' QName
76553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7656afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7657afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
76583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name;
76593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *prefix;
76603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
76623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '$') {
76633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
76643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
76653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
76663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    name = xmlXPathParseQName(ctxt, &prefix);
76673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
76683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
76693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7670fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    ctxt->comp->last = -1;
76719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
76729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           name, prefix);
76733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
76743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
76753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
76773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsNodeType:
76783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  a name string
76793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
76803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Is the name given a NodeType one.
76813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
76823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [38]   NodeType ::=   'comment'
76833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'text'
76843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'processing-instruction'
76853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'node'
76863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
76873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 1 if true 0 otherwise
76883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
76893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
76903473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsNodeType(const xmlChar *name) {
76913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
76923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
76933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76941971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "node"))
76953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
76963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrEqual(name, BAD_CAST "text"))
76973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
76981971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "comment"))
76993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
77001971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
77013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
77023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
77033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
77043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7706afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompFunctionCall:
77073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
77083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [16]   FunctionCall ::=   FunctionName '(' ( Argument ( ',' Argument)*)? ')'
77103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [17]   Argument ::=   Expr
77113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7712afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a function call, the evaluation of all arguments are
77133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * pushed on the stack
77143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7715afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7716afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
77173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name;
77183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *prefix;
77193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int nbargs = 0;
77203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    name = xmlXPathParseQName(ctxt, &prefix);
77223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
77233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_EXPR_ERROR);
77243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
77263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
77273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
77283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Calling function %s\n",
77293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			name);
77303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
77313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n",
77323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			prefix, name);
77333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
77343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '(') {
77363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_EXPR_ERROR);
77373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
77393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
77403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt->comp->last = -1;
774271f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard    if (CUR != ')') {
774371f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	while (CUR != 0) {
774471f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    int op1 = ctxt->comp->last;
774571f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    ctxt->comp->last = -1;
774671f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    xmlXPathCompileExpr(ctxt);
774771f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    CHECK_ERROR;
774871f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
774971f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    nbargs++;
775071f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    if (CUR == ')') break;
775171f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    if (CUR != ',') {
775271f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard		XP_ERROR(XPATH_EXPR_ERROR);
775371f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    }
775471f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    NEXT;
775571f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    SKIP_BLANKS;
77563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
77573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0,
77599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           name, prefix);
77603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
77613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
77623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
77633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7765afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPrimaryExpr:
77663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
77673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [15]   PrimaryExpr ::=   VariableReference
77693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | '(' Expr ')'
77703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | Literal
77713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | Number
77723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | FunctionCall
77733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7774afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a primary expression.
77753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7776afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7777afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) {
77783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
7779afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    if (CUR == '$') xmlXPathCompVariableReference(ctxt);
77803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (CUR == '(') {
77813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
77823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
7783afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompileExpr(ctxt);
778450fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	CHECK_ERROR;
77853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ')') {
77863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
77873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
77883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
77893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
779001917aa1cb20fb33e6fa2b1e0ca2125051e491e0Daniel Veillard    } else if (IS_DIGIT(CUR) || (CUR == '.' && IS_DIGIT(NXT(1)))) {
7791afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompNumber(ctxt);
77923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if ((CUR == '\'') || (CUR == '"')) {
7793afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompLiteral(ctxt);
77943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
7795afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompFunctionCall(ctxt);
77963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
77983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
77993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7801afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompFilterExpr:
78023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
78033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [20]   FilterExpr ::=   PrimaryExpr
78053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr Predicate
78063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7807afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a filter expression.
78083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Square brackets are used to filter expressions in the same way that
78093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * they are used in location paths. It is an error if the expression to
78103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * be filtered does not evaluate to a node-set. The context node list
78113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * used for evaluating the expression in square brackets is the node-set
78123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be filtered listed in document order.
78133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
78143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7815afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7816afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
7817afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompPrimaryExpr(ctxt);
78183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
78193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
78203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '[') {
7822d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlXPathCompPredicate(ctxt, 1);
78233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
78243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
78253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
78283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
78303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathScanName:
78313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
78323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Trickery: parse an XML name but without consuming the input flow
78343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Needed to avoid insanity in the parser state.
78353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
78373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  CombiningChar | Extender
78383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] Name ::= (Letter | '_' | ':') (NameChar)*
78403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [6] Names ::= Name (S Name)*
78423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the Name parsed or NULL
78443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
78453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
784656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
78473473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathScanName(xmlXPathParserContextPtr ctxt) {
78483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar buf[XML_MAX_NAMELEN];
78493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int len = 0;
78503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
78523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (!IS_LETTER(CUR) && (CUR != '_') &&
78533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        (CUR != ':')) {
78543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
78553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
78563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
78583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           (NXT(len) == '.') || (NXT(len) == '-') ||
78593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	   (NXT(len) == '_') || (NXT(len) == ':') ||
78603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	   (IS_COMBINING(NXT(len))) ||
78613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	   (IS_EXTENDER(NXT(len)))) {
78623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	buf[len] = NXT(len);
78633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len++;
78643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (len >= XML_MAX_NAMELEN) {
78653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
78663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       "xmlScanName: reached XML_MAX_NAMELEN limit\n");
78673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while ((IS_LETTER(NXT(len))) || (IS_DIGIT(NXT(len))) ||
78683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   (NXT(len) == '.') || (NXT(len) == '-') ||
78693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   (NXT(len) == '_') || (NXT(len) == ':') ||
78703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   (IS_COMBINING(NXT(len))) ||
78713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   (IS_EXTENDER(NXT(len))))
78723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		 len++;
78733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
78743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
78753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
78763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlStrndup(buf, len));
78773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
78783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7880afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPathExpr:
78813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
78823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [19]   PathExpr ::=   LocationPath
78843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr
78853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr '/' RelativeLocationPath
78863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr '//' RelativeLocationPath
78873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7888afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a path expression.
78893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The / operator and // operators combine an arbitrary expression
78903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and a relative location path. It is an error if the expression
78913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * does not evaluate to a node-set.
78923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The / operator does composition in the same way as when / is
78933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * used in a location path. As in location paths, // is short for
78943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * /descendant-or-self::node()/.
78953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
78963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7897afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7898afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
78993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int lc = 1;           /* Should we branch to LocationPath ?         */
79003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name = NULL; /* we may have to preparse a name to find out */
79013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
79033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '$') || (CUR == '(') || (IS_DIGIT(CUR)) ||
790401917aa1cb20fb33e6fa2b1e0ca2125051e491e0Daniel Veillard        (CUR == '\'') || (CUR == '"') || (CUR == '.' && IS_DIGIT(NXT(1)))) {
79053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 0;
79063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '*') {
79073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative or absolute location path */
79083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
79093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '/') {
79103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative or absolute location path */
79113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
79123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '@') {
79133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative abbreviated attribute location path */
79143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
79153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '.') {
79163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative abbreviated attribute location path */
79173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
79183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
79193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
79203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * Problem is finding if we have a name here whether it's:
79213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a nodetype
79223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a function call in which case it's followed by '('
79233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - an axis in which case it's followed by ':'
79243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a element name
79253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * We do an a priori analysis here rather than having to
79263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * maintain parsed token content through the recursive function
79273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * calls. This looks uglier but makes the code quite easier to
79283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * read/write/debug.
79293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
79303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
79313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathScanName(ctxt);
79323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
79333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
79343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
79353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "PathExpr: Axis\n");
79363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
79373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    lc = 1;
79383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
79393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (name != NULL) {
79403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int len =xmlStrlen(name);
79413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (NXT(len) != 0) {
79443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (NXT(len) == '/') {
79453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* element name */
79463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
79473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
79483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
79493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
79503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
79513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
79523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if (IS_BLANK(NXT(len))) {
795378637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack		    /* ignore blanks */
795478637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack		    ;
79553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if (NXT(len) == ':') {
79563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
79573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
79583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
79593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
79603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
79613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
79623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '(')) {
79633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* Note Type or Function */
79643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if (xmlXPathIsNodeType(name)) {
79653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
79663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		        xmlGenericError(xmlGenericErrorContext,
79673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"PathExpr: Type search\n");
79683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
79693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			lc = 1;
79703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    } else {
79713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
79723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		        xmlGenericError(xmlGenericErrorContext,
79733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"PathExpr: function call\n");
79743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
79753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			lc = 0;
79763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    }
79773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    break;
79783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '[')) {
79793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* element name */
79803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
79813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
79823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
79833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
79843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
79853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
79863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '<') || (NXT(len) == '>') ||
79873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   (NXT(len) == '=')) {
79883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
79893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
79903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
79913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
79923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
79933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
79943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		len++;
79953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
79963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (NXT(len) == 0) {
79973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
79983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlGenericError(xmlGenericErrorContext,
79993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			"PathExpr: AbbrRelLocation\n");
80003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
80013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		/* element name */
80023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		lc = 1;
80033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
80043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
80053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
80063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /* make sure all cases are covered explicitely */
80073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
80083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
80093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (lc) {
80129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (CUR == '/') {
80139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0);
80149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	} else {
80159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
80163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8017afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompLocationPath(ctxt);
80183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
8019afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompFilterExpr(ctxt);
80203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
80213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((CUR == '/') && (NXT(1) == '/')) {
80223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(2);
80233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
80249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
80259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
80269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
80279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_RESET, ctxt->comp->last, 1, 0);
80289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8029afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompRelativeLocationPath(ctxt);
80303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == '/') {
8031afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompRelativeLocationPath(ctxt);
80323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
80333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
80353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
80363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8038afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompUnionExpr:
80393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
80403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [18]   UnionExpr ::=   PathExpr
80423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | UnionExpr '|' PathExpr
80433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8044afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an union expression.
80453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
80463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8047afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8048afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) {
8049afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompPathExpr(ctxt);
80503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
80513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
80523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '|') {
80539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
80549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
80553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
80573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8058afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompPathExpr(ctxt);
80593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0);
80619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
80623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
80633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
80653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8067afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompUnaryExpr:
80683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
80693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [27]   UnaryExpr ::=   UnionExpr
80713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | '-' UnaryExpr
80723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8073afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an unary expression.
80743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
80753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8076afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8077afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) {
80783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int minus = 0;
80799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int found = 0;
80803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
808268d7b67ada0941ad7e1d02602f48de4015a67af3Daniel Veillard    while (CUR == '-') {
808368d7b67ada0941ad7e1d02602f48de4015a67af3Daniel Veillard        minus = 1 - minus;
80849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	found = 1;
80853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
80863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
80873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8089afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompUnionExpr(ctxt);
80903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
80919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (found) {
80929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (minus)
80939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0);
80949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	else
80959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0);
80963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
80983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8100afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompMultiplicativeExpr:
81013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
81023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [26]   MultiplicativeExpr ::=   UnaryExpr
81043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr MultiplyOperator UnaryExpr
81053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr 'div' UnaryExpr
81063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr 'mod' UnaryExpr
81073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [34]   MultiplyOperator ::=   '*'
81083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8109afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Additive expression.
81103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
81113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8112afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8113afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) {
8114afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompUnaryExpr(ctxt);
81153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
81163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
81173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '*') ||
81183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) ||
81193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) {
81203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int op = -1;
81219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
81223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '*') {
81243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 0;
81253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
81263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == 'd') {
81273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 1;
81283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(3);
81293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == 'm') {
81303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 2;
81313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(3);
81323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
81333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8134afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompUnaryExpr(ctxt);
81353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
81369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0);
81373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
81383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
81393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
81403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8142afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompAdditiveExpr:
81433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
81443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [25]   AdditiveExpr ::=   MultiplicativeExpr
81463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | AdditiveExpr '+' MultiplicativeExpr
81473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | AdditiveExpr '-' MultiplicativeExpr
81483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8149afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Additive expression.
81503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
81513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8152afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8153afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) {
81549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8155afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompMultiplicativeExpr(ctxt);
81563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
81573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
81583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '+') || (CUR == '-')) {
81593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int plus;
81609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
81613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '+') plus = 1;
81633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else plus = 0;
81643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
81653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8166afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompMultiplicativeExpr(ctxt);
81673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
81689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0);
81693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
81703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
81713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
81723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8174afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompRelationalExpr:
81753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
81763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [24]   RelationalExpr ::=   AdditiveExpr
81783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '<' AdditiveExpr
81793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '>' AdditiveExpr
81803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '<=' AdditiveExpr
81813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '>=' AdditiveExpr
81823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  A <= B > C is allowed ? Answer from James, yes with
81843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (AdditiveExpr <= AdditiveExpr) > AdditiveExpr
81853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  which is basically what got implemented.
81863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8187afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Relational expression, then push the result
81883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * on the stack
81893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
81903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8191afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8192afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) {
8193afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompAdditiveExpr(ctxt);
81943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
81953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
81963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '<') ||
81973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           (CUR == '>') ||
81983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == '<') && (NXT(1) == '=')) ||
81993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == '>') && (NXT(1) == '='))) {
82009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int inf, strict;
82019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
82023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '<') inf = 1;
82043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else inf = 0;
82053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (NXT(1) == '=') strict = 0;
82063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else strict = 1;
82073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
82083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!strict) NEXT;
82093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8210afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompAdditiveExpr(ctxt);
82113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
82129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict);
82133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
82143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
82153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
82163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8218afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompEqualityExpr:
82193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
82203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [23]   EqualityExpr ::=   RelationalExpr
82223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | EqualityExpr '=' RelationalExpr
82233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | EqualityExpr '!=' RelationalExpr
82243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  A != B != C is allowed ? Answer from James, yes with
82263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (RelationalExpr = RelationalExpr) = RelationalExpr
82273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (RelationalExpr != RelationalExpr) != RelationalExpr
82283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  which is basically what got implemented.
82293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8230afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Equality expression.
82313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8233afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8234afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) {
8235afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompRelationalExpr(ctxt);
82363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
82373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
82383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) {
82399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int eq;
82409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
82413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '=') eq = 1;
82433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else eq = 0;
82443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
82453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!eq) NEXT;
82463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8247afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompRelationalExpr(ctxt);
82483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
82499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0);
82503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
82513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
82523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
82533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8255afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompAndExpr:
82563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
82573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [22]   AndExpr ::=   EqualityExpr
82593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | AndExpr 'and' EqualityExpr
82603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8261afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an AND expression.
82623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8264afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8265afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) {
8266afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompEqualityExpr(ctxt);
82673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
82683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
82693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
82709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
82713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        SKIP(3);
82723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8273afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompEqualityExpr(ctxt);
82743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
82759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0);
82763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
82773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
82783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
82793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8281591b4be0fe1986b5e71d54c5c063493987ef4285Daniel Veillard * xmlXPathCompileExpr:
82823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
82833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [14]   Expr ::=   OrExpr
82853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [21]   OrExpr ::=   AndExpr
82863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | OrExpr 'or' AndExpr
82873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8288afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Parse and compile an expression
82893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8290afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8291afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompileExpr(xmlXPathParserContextPtr ctxt) {
8292afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompAndExpr(ctxt);
82933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
82943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
82953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == 'o') && (NXT(1) == 'r')) {
82969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
82973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        SKIP(2);
82983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8299afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompAndExpr(ctxt);
83003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
83019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0);
83029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	op1 = ctxt->comp->nbStep;
83033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
83043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE) {
83069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	/* more ops could be optimized too */
83079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0);
83089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
83093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
83103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8312afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPredicate:
83133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
8314d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @filter:  act as a filter
83153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [8]   Predicate ::=   '[' PredicateExpr ']'
83173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [9]   PredicateExpr ::=   Expr
83183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8319afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a predicate expression
83209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
8321afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8322d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
83239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int op1 = ctxt->comp->last;
83249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
83259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
83269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (CUR != '[') {
83279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
83289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
83299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NEXT;
83309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
83319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
83329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt->comp->last = -1;
8333afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompileExpr(ctxt);
83349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    CHECK_ERROR;
83359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
83369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (CUR != ']') {
83379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
83389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
83399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8340d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (filter)
8341d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
8342d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    else
8343d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
83449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
83459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NEXT;
83469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
83479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
83489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
83499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
8350afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompNodeTest:
83513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
83523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @test:  pointer to a xmlXPathTestVal
83533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @type:  pointer to a xmlXPathTypeVal
83543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  placeholder for a possible name prefix
83553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [7] NodeTest ::=   NameTest
83573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | NodeType '(' ')'
83583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | 'processing-instruction' '(' Literal ')'
83593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [37] NameTest ::=  '*'
83613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | NCName ':' '*'
83623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | QName
83633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [38] NodeType ::= 'comment'
83643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'text'
83653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'processing-instruction'
83663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'node'
83673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the name found and update @test, @type and @prefix appropriately
83693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
837056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
8371afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
8372afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	             xmlXPathTypeVal *type, const xmlChar **prefix,
8373afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		     xmlChar *name) {
83743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int blanks;
83753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
83773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	STRANGE;
83783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
83793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
838078637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    *type = (xmlXPathTypeVal) 0;
838178637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    *test = (xmlXPathTestVal) 0;
83823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *prefix = NULL;
83833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
83843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((name == NULL) && (CUR == '*')) {
83863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
83873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * All elements
83883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
83893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
83903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*test = NODE_TEST_ALL;
83913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
83923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
83953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathParseNCName(ctxt);
83963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
83973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_EXPR_ERROR);
83983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    blanks = IS_BLANK(CUR);
84013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
84023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '(') {
84033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
84043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
84053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * NodeType or PI search
84063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
84073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (xmlStrEqual(name, BAD_CAST "comment"))
84083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_COMMENT;
84093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "node"))
84103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_NODE;
84113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
84123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_PI;
84133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "text"))
84143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_TEXT;
84153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else {
84163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
84173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
84183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_EXPR_ERROR);
84193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
84203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*test = NODE_TEST_TYPE;
84223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
84243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*type == NODE_TYPE_PI) {
84253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /*
84263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     * Specific case: search a PI by name.
84273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     */
84283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
84293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
843082e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    name = NULL;
843182e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    if (CUR != ')') {
843282e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		name = xmlXPathParseLiteral(ctxt);
843382e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		CHECK_ERROR 0;
8434ed23b7dc73f6c1146701ece20ed3f03d68366516Daniel Veillard		*test = NODE_TEST_PI;
843582e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		SKIP_BLANKS;
843682e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    }
84373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
84383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ')') {
84393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
84403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
84413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_UNCLOSED_ERROR);
84423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
84433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
84443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(name);
84453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
84463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *test = NODE_TEST_NAME;
84473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((!blanks) && (CUR == ':')) {
84483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
84493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
8451fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * Since currently the parser context don't have a
8452fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * namespace list associated:
8453fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * The namespace name for this prefix can be computed
8454fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * only at evaluation time. The compilation is done
8455fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * outside of any context.
84563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
8457fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#if 0
84583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*prefix = xmlXPathNsLookup(ctxt->context, name);
84593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (name != NULL)
84603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
84613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*prefix == NULL) {
84623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
84633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8464fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#else
8465fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	*prefix = name;
8466fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#endif
84673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR == '*') {
84693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /*
84703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     * All elements
84713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     */
84723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
84733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *test = NODE_TEST_ALL;
84743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
84753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
84763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathParseNCName(ctxt);
84783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (name == NULL) {
84793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_EXPR_ERROR);
84803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
84813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
84823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(name);
84833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
84843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
84863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsAxisName:
84873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  a preparsed name token
84883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [6] AxisName ::=   'ancestor'
84903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'ancestor-or-self'
84913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'attribute'
84923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'child'
84933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'descendant'
84943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'descendant-or-self'
84953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'following'
84963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'following-sibling'
84973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'namespace'
84983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'parent'
84993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'preceding'
85003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'preceding-sibling'
85013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'self'
85023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the axis or 0
85043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
850556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathAxisVal
85063473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsAxisName(const xmlChar *name) {
850778637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal ret = (xmlXPathAxisVal) 0;
85083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (name[0]) {
85093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'a':
85103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "ancestor"))
85113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ANCESTOR;
85123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "ancestor-or-self"))
85133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ANCESTOR_OR_SELF;
85143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "attribute"))
85153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ATTRIBUTE;
85163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
85173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'c':
85183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "child"))
85193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_CHILD;
85203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
85213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'd':
85223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "descendant"))
85233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_DESCENDANT;
85243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "descendant-or-self"))
85253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_DESCENDANT_OR_SELF;
85263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
85273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'f':
85283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "following"))
85293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_FOLLOWING;
85303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "following-sibling"))
85313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_FOLLOWING_SIBLING;
85323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
85333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'n':
85343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "namespace"))
85353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_NAMESPACE;
85363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
85373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'p':
85383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "parent"))
85393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PARENT;
85403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "preceding"))
85413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PRECEDING;
85423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "preceding-sibling"))
85433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PRECEDING_SIBLING;
85443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
85453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 's':
85463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "self"))
85473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_SELF;
85483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
85493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
85503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
85513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
85523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
85533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8554afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompStep:
85553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
85563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] Step ::=   AxisSpecifier NodeTest Predicate*
85583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | AbbreviatedStep
85593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [12] AbbreviatedStep ::=   '.' | '..'
85613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] AxisSpecifier ::= AxisName '::'
85633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | AbbreviatedAxisSpecifier
85643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [13] AbbreviatedAxisSpecifier ::= '@'?
85663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Modified for XPtr range support as:
85683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
85703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedStep
85713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | 'range-to' '(' Expr ')' Predicate*
85723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8573afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile one step in a Location Path
85743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A location step of . is short for self::node(). This is
85753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * particularly useful in conjunction with //. For example, the
85763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * location path .//para is short for
85773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * self::node()/descendant-or-self::node()/child::para
85783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and so will select all para descendant elements of the context
85793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node.
85803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Similarly, a location step of .. is short for parent::node().
85813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * For example, ../title is short for parent::node()/child::title
85823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and so will select the title children of the parent of the context
85833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node.
85843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8585afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8586afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
8587fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
8588fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    int rangeto = 0;
8589fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    int op2 = -1;
8590fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
8591fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard
85923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
85933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '.') && (NXT(1) == '.')) {
85943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP(2);
85953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
85969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT,
85979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
85983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '.') {
85993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
86003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
86013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
86023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlChar *name = NULL;
86033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	const xmlChar *prefix = NULL;
86043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathTestVal test;
860578637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
86063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathTypeVal type;
8607d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	int op1;
86083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
86103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * The modification needed for XPointer change to the production
86113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
86123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
8613fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	if (ctxt->xptr) {
86143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    name = xmlXPathParseNCName(ctxt);
86153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
8616fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard                op2 = ctxt->comp->last;
86173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
86183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
86193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (CUR != '(') {
86203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    XP_ERROR(XPATH_EXPR_ERROR);
86213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
86223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
86233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
86243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8625afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		xmlXPathCompileExpr(ctxt);
8626fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		/* PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, ctxt->comp->last, 0, 0); */
86273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		CHECK_ERROR;
86283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
86303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (CUR != ')') {
86313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    XP_ERROR(XPATH_EXPR_ERROR);
86323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
86333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
8634fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		rangeto = 1;
86353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		goto eval_predicates;
86363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
86373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
86383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
86392156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	if (CUR == '*') {
86402156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    axis = AXIS_CHILD;
86412156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	} else {
86422156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (name == NULL)
86432156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		name = xmlXPathParseNCName(ctxt);
86442156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (name != NULL) {
86452156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = xmlXPathIsAxisName(name);
86462156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		if (axis != 0) {
86472156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    SKIP_BLANKS;
86482156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    if ((CUR == ':') && (NXT(1) == ':')) {
86492156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			SKIP(2);
86502156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			xmlFree(name);
86512156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			name = NULL;
86522156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    } else {
86532156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			/* an element name can conflict with an axis one :-\ */
86542156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			axis = AXIS_CHILD;
86552156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    }
86563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
86573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    axis = AXIS_CHILD;
86583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
86592156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    } else if (CUR == '@') {
86602156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		NEXT;
86612156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = AXIS_ATTRIBUTE;
86623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else {
86632156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = AXIS_CHILD;
86643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
86653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
86663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
86683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8669afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
86703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (test == 0)
86713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
86723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
86743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
86753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"Basis : computing new set\n");
86763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
86779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
86783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
86793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Basis : ");
8680fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	if (ctxt->value == NULL)
8681fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "no value\n");
8682fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	else if (ctxt->value->nodesetval == NULL)
8683fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "Empty\n");
8684fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	else
8685fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval);
86863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
86873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86883473f88a7abdf4e585e267288fb77e898c580d2bOwen Tayloreval_predicates:
8689d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	op1 = ctxt->comp->last;
8690d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	ctxt->comp->last = -1;
8691d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
86923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
86933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (CUR == '[') {
8694d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    xmlXPathCompPredicate(ctxt, 0);
86953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8696d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8697fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
8698fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	if (rangeto) {
8699fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0);
8700fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	} else
8701fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
8702fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
8703fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard			   test, type, (void *)prefix, (void *)name);
8704d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
87053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
87063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
87073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext, "Step : ");
8708fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    if (ctxt->value == NULL)
8709fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "no value\n");
8710fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    else if (ctxt->value->nodesetval == NULL)
8711fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "Empty\n");
8712fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    else
8713fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericErrorContextNodeSet(xmlGenericErrorContext,
8714fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		ctxt->value->nodesetval);
87153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
87163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
87173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8719afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompRelativeLocationPath:
87203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
87213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [3]   RelativeLocationPath ::=   Step
87233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | RelativeLocationPath '/' Step
87243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedRelativeLocationPath
87253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [11]  AbbreviatedRelativeLocationPath ::=   RelativeLocationPath '//' Step
87263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8727afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a relative location path.
87283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8729afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8730afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelativeLocationPath
87313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor(xmlXPathParserContextPtr ctxt) {
87323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
87333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '/') && (NXT(1) == '/')) {
87343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP(2);
87353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
87369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
87379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		         NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
87383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '/') {
87393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
87403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
87413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8742afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompStep(ctxt);
87433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
87443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '/') {
87453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((CUR == '/') && (NXT(1) == '/')) {
87463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(2);
87473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
87489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
87493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
8750afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompStep(ctxt);
87513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == '/') {
87523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
87533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
8754afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompStep(ctxt);
87553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
87563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
87573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
87583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
87593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8761afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompLocationPath:
87623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
87633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [1]   LocationPath ::=   RelativeLocationPath
87653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbsoluteLocationPath
87663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [2]   AbsoluteLocationPath ::=   '/' RelativeLocationPath?
87673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedAbsoluteLocationPath
87683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [10]   AbbreviatedAbsoluteLocationPath ::=
87693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                           '//' RelativeLocationPath
87703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8771afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a location path
8772afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
87733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * // is short for /descendant-or-self::node()/. For example,
87743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * //para is short for /descendant-or-self::node()/child::para and
87753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * so will select any para element in the document (even a para element
87763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * that is a document element will be selected by //para since the
87773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * document element node is a child of the root node); div//para is
87783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * short for div/descendant-or-self::node()/child::para and so will
87793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * select all para descendants of div children.
87803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8781afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8782afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
87833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
87843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '/') {
8785afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompRelativeLocationPath(ctxt);
87863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
87873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (CUR == '/') {
87883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((CUR == '/') && (NXT(1) == '/')) {
87893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP(2);
87903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
87919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
87929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
8793afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		xmlXPathCompRelativeLocationPath(ctxt);
87943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else if (CUR == '/') {
87953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
8796608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		SKIP_BLANKS;
8797608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		if ((CUR != 0 ) &&
8798608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		    ((IS_LETTER(CUR)) || (CUR == '_') || (CUR == '.') ||
8799608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		     (CUR == '@') || (CUR == '*')))
8800afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		    xmlXPathCompRelativeLocationPath(ctxt);
88013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
88023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
88033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
88043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
88053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
88069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
88079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *									*
88089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 		XPath precompiled expression evaluation			*
88099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *									*
88109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
88119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8812f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
8813d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
8814d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
88159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
8816d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathNodeCollectAndTest:
8817d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
8818d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @op:  the XPath precompiled step operation
8819f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  pointer to the first element in document order
8820f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  pointer to the last element in document order
88219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
8822d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * This is the function implementing a step: based on the current list
8823d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * of nodes, it builds up a new list, looking at all nodes under that
8824d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * axis and selecting them it also do the predicate filtering
8825d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
8826d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Pushes the new NodeSet resulting from the search.
8827f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
8828f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
88299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
8830f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
8831d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
8832f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                           xmlXPathStepOpPtr op,
8833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard			   xmlNodePtr * first, xmlNodePtr * last)
8834f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
883578637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
883678637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
883778637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
8838d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    const xmlChar *prefix = op->value4;
8839d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    const xmlChar *name = op->value5;
8840e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    const xmlChar *URI = NULL;
88419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8842d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8843f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int n = 0;
8844d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8845f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int i, t = 0;
8846d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodeSetPtr ret, list;
8847d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathTraversalFunction next = NULL;
8848f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
884975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    xmlNodeSetPtr (*mergeNodeSet) (xmlNodeSetPtr, xmlNodeSetPtr);
8850d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodePtr cur = NULL;
8851d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathObjectPtr obj;
8852d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodeSetPtr nodelist;
8853d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodePtr tmp;
8854d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    CHECK_TYPE0(XPATH_NODESET);
8856d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    obj = valuePop(ctxt);
8857d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    addNode = xmlXPathNodeSetAdd;
885875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    mergeNodeSet = xmlXPathNodeSetMerge;
8859e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    if (prefix != NULL) {
8860f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        URI = xmlXPathNsLookup(ctxt->context, prefix);
8861f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (URI == NULL)
8862f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
8863e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    }
8864d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8865f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "new step : ");
8866d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8867d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (axis) {
8868d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ANCESTOR:
8869d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8870f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
8871d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8872f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8873f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestor;
8874f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8875d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ANCESTOR_OR_SELF:
8876d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8877f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8878f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'ancestors-or-self' ");
8879d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8880f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8881f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestorOrSelf;
8882f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8883d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ATTRIBUTE:
8884d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8885f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
8886d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8887f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8888f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8889f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAttribute;
889075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
8891f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8892d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_CHILD:
8893d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8894f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
8895d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextChild;
889875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
8899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8900d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_DESCENDANT:
8901d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
8903d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8905f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendant;
8906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8907d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_DESCENDANT_OR_SELF:
8908d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8910f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'descendant-or-self' ");
8911d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8912f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8913f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendantOrSelf;
8914f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8915d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_FOLLOWING:
8916d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8917f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
8918d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8919f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8920f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowing;
8921f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8922d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_FOLLOWING_SIBLING:
8923d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8924f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8925f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'following-siblings' ");
8926d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8928f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowingSibling;
8929f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8930d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_NAMESPACE:
8931d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
8933d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8934f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8935f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8936f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
893775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
8938f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8939d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PARENT:
8940d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
8942d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8944f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextParent;
8945f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8946d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PRECEDING:
8947d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8948f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
8949d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8950f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8951f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingInternal;
8952f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8953d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PRECEDING_SIBLING:
8954d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8955f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8956f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'preceding-sibling' ");
8957d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8959f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingSibling;
8960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8961d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_SELF:
8962d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
8964d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
8965f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
8966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
8967f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextSelf;
896875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
8969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8970d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
8971d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (next == NULL)
8972f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
8973d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8974d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    nodelist = obj->nodesetval;
8975d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (nodelist == NULL) {
8976f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlXPathFreeObject(obj);
8977f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
8978f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
8979d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
8980d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    addNode = xmlXPathNodeSetAddUnique;
8981d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ret = NULL;
8982d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
8983d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
8984f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    " context contains %d nodes\n", nodelist->nodeNr);
8985d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (test) {
8986f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NONE:
8987f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8988f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for none !!!\n");
8989f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8990f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_TYPE:
8991f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8992f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for type %d\n", type);
8993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8994f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_PI:
8995f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
8996f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for PI !!!\n");
8997f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
8998f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_ALL:
8999f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9000f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for *\n");
9001f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9002f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NS:
9003f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9004f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for namespace %s\n",
9005f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            prefix);
9006f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9007f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NAME:
9008f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9009f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for name %s\n", name);
9010f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (prefix != NULL)
9011f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlGenericError(xmlGenericErrorContext,
9012f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                "           with namespace %s\n", prefix);
9013f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9014d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
9015d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "Testing : ");
9016d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9017d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    /*
9018d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * 2.3 Node Tests
9019d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For the attribute axis, the principal node type is attribute.
9020d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For the namespace axis, the principal node type is namespace.
9021d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For other axes, the principal node type is element.
9022d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *
9023d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * A node test * is true for any node of the
9024cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard     * principal node type. For example, child::* will
9025d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * select all element children of the context node
9026d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     */
9027d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    tmp = ctxt->context->node;
9028f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < nodelist->nodeNr; i++) {
9029d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        ctxt->context->node = nodelist->nodeTab[i];
9030d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9031f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = NULL;
9032f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        list = xmlXPathNodeSetCreate(NULL);
9033f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        do {
9034f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur = next(ctxt, cur);
9035f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (cur == NULL)
9036f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9037f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((first != NULL) && (*first == cur))
9038f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9039f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9040f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (first != NULL) && (*first != NULL) &&
9041f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(*first, cur) >= 0))
9042f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9043f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((last != NULL) && (*last == cur))
9044f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9045f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9046f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(last != NULL) && (*last != NULL) &&
9047f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(cur, *last) >= 0))
9048f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9049d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard            t++;
9050f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP
9051d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard            xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
9052d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9053f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            switch (test) {
9054d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_NONE:
9055f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = tmp;
9056f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    STRANGE return(t);
9057d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_TYPE:
9058f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((cur->type == type) ||
9059f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ((type == NODE_TYPE_NODE) &&
9060f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         ((cur->type == XML_DOCUMENT_NODE) ||
9061f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_HTML_DOCUMENT_NODE) ||
9062f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_ELEMENT_NODE) ||
9063f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Sanin                          (cur->type == XML_NAMESPACE_DECL) ||
9064f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Sanin                          (cur->type == XML_ATTRIBUTE_NODE) ||
9065f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_PI_NODE) ||
9066f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_COMMENT_NODE) ||
9067f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_CDATA_SECTION_NODE) ||
90687583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard                          (cur->type == XML_TEXT_NODE))) ||
90697583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard			((type == NODE_TYPE_TEXT) &&
90707583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard			 (cur->type == XML_CDATA_SECTION_NODE))) {
9071d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9072d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                        n++;
9073d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9074f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        addNode(list, cur);
9075f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9076f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9077d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_PI:
9078f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (cur->type == XML_PI_NODE) {
9079f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((name != NULL) &&
9080f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (!xmlStrEqual(name, cur->name)))
9081f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9082d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9083f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9084d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9085f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        addNode(list, cur);
9086f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9087f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9088d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_ALL:
9089f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (axis == AXIS_ATTRIBUTE) {
9090f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ATTRIBUTE_NODE) {
9091d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9092f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9093d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9094f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9095f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9096f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else if (axis == AXIS_NAMESPACE) {
9097f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_NAMESPACE_DECL) {
9098d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9099f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9100d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9101044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard                            xmlXPathNodeSetAddNs(list, ctxt->context->node,
9102044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				                 (xmlNsPtr) cur);
9103f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9104f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else {
9105f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ELEMENT_NODE) {
9106f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (prefix == NULL) {
9107d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9108f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9109d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9111f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            } else if ((cur->ns != NULL) &&
9112f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                       (xmlStrEqual(URI, cur->ns->href))) {
9113d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9115d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9116f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9119f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9120f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9121f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NS:{
9122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        TODO;
9123f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        break;
9124f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9125d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_NAME:
9126f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    switch (cur->type) {
9127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ELEMENT_NODE:
9128f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (xmlStrEqual(name, cur->name)) {
9129f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (prefix == NULL) {
9130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (cur->ns == NULL) {
9131d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9132f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9133d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9134f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        addNode(list, cur);
9135f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9136f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                } else {
9137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if ((cur->ns != NULL) &&
9138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        (xmlStrEqual(URI,
9139f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     cur->ns->href))) {
9140d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9141f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9142d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9143f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        addNode(list, cur);
9144f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9145f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9146f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9147f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ATTRIBUTE_NODE:{
9149f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlAttrPtr attr = (xmlAttrPtr) cur;
9150f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9151f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (xmlStrEqual(name, attr->name)) {
9152f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (prefix == NULL) {
9153f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns == NULL) ||
9154f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (attr->ns->prefix == NULL)) {
9155d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9156f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9157d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9158f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list,
9159f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    (xmlNodePtr) attr);
9160f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9161f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    } else {
9162f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns != NULL) &&
9163f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (xmlStrEqual(URI,
9164f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         attr->ns->
9165f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         href))) {
9166d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9167f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9168d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9169f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list,
9170f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    (xmlNodePtr) attr);
9171f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9172f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9173f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9174f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                break;
9175f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9176f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_NAMESPACE_DECL:
9177f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (cur->type == XML_NAMESPACE_DECL) {
9178f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlNsPtr ns = (xmlNsPtr) cur;
9179f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9180f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if ((ns->prefix != NULL) && (name != NULL)
9181f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    && (xmlStrEqual(ns->prefix, name))) {
91828b8d2254fa1604efd37b3ba92eaeb2e40b2909a8Daniel Veillard#ifdef DEBUG_STEP
9183f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    n++;
91848b8d2254fa1604efd37b3ba92eaeb2e40b2909a8Daniel Veillard#endif
9185044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				    xmlXPathNodeSetAddNs(list,
9186044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					ctxt->context->node, (xmlNsPtr) cur);
9187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9188f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9189f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9190f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        default:
9191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9192f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9196f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } while (cur != NULL);
9197f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        /*
9199f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard         * If there is some predicate filtering do it now
9200f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard         */
92016fbcf42aa301dca50737c65fb738752328ca3a4cDaniel Veillard        if ((op->ch2 != -1) && (list != NULL) && (list->nodeNr > 0)) {
9202f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathObjectPtr obj2;
9203f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9204f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathWrapNodeSet(list));
9205f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch2]);
9206f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9207f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            obj2 = valuePop(ctxt);
9208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            list = obj2->nodesetval;
9209f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            obj2->nodesetval = NULL;
9210f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(obj2);
9211f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
9212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (ret == NULL) {
9213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ret = list;
9214f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } else {
921575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard            ret = mergeNodeSet(ret, list);
9216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeNodeSet(list);
9217f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
9218d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
9219d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ctxt->context->node = tmp;
9220d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9221d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9222f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "\nExamined %d nodes, found %d nodes at that step\n",
9223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    t, n);
9224d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9225d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
92260ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->boolval) && (obj->user != NULL)) {
92270ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->boolval = 1;
92280ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->user = obj->user;
92290ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->user = NULL;
92300ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->boolval = 0;
92310ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    }
92320ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    xmlXPathFreeObject(obj);
9233f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(t);
9234d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
9235d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9236d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
9237f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNodeCollectAndTestNth:
9238f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath Parser context
9239f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  the XPath precompiled step operation
9240f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @indx:  the index to collect
9241f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  pointer to the first element in document order
9242f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  pointer to the last element in document order
9243f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9244f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * This is the function implementing a step: based on the current list
9245f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * of nodes, it builds up a new list, looking at all nodes under that
9246f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * axis and selecting them it also do the predicate filtering
9247f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9248f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Pushes the new NodeSet resulting from the search.
9249f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
9250f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
9251f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9252f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNodeCollectAndTestNth(xmlXPathParserContextPtr ctxt,
9253f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlXPathStepOpPtr op, int indx,
9254f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlNodePtr * first, xmlNodePtr * last)
9255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
925678637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
925778637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
925878637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
9259f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *prefix = op->value4;
9260f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *name = op->value5;
9261f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *URI = NULL;
9262f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int n = 0, t = 0;
9263f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9264f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int i;
9265f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodeSetPtr list;
9266f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathTraversalFunction next = NULL;
9267f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
9268f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr cur = NULL;
9269f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr obj;
9270f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodeSetPtr nodelist;
9271f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr tmp;
9272f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9273f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    CHECK_TYPE0(XPATH_NODESET);
9274f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    obj = valuePop(ctxt);
9275f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    addNode = xmlXPathNodeSetAdd;
9276f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (prefix != NULL) {
9277f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        URI = xmlXPathNsLookup(ctxt->context, prefix);
9278f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (URI == NULL)
9279f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
9280f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9281f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9282f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "new step : ");
9283f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (first != NULL) {
9284f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (*first != NULL)
9285f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "first = %s ",
9286f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    (*first)->name);
9287f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	else
9288f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "first = NULL ");
9289f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9290f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (last != NULL) {
9291f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (*last != NULL)
9292f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "last = %s ",
9293f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    (*last)->name);
9294f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	else
9295f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "last = NULL ");
9296f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9297f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9298f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (axis) {
9299f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ANCESTOR:
9300f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9301f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
9302f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9303f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9304f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestor;
9305f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9306f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ANCESTOR_OR_SELF:
9307f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9308f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9309f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'ancestors-or-self' ");
9310f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9311f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9312f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestorOrSelf;
9313f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9314f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ATTRIBUTE:
9315f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9316f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
9317f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9318f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9320f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAttribute;
9321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_CHILD:
9323f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9324f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
9325f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9326f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9327f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextChild;
9328f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9329f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_DESCENDANT:
9330f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9331f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
9332f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9333f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9334f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendant;
9335f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9336f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_DESCENDANT_OR_SELF:
9337f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9338f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9339f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'descendant-or-self' ");
9340f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9341f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9342f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendantOrSelf;
9343f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9344f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_FOLLOWING:
9345f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9346f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
9347f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9348f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9349f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowing;
9350f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9351f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_FOLLOWING_SIBLING:
9352f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9353f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9354f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'following-siblings' ");
9355f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9356f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9357f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowingSibling;
9358f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9359f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_NAMESPACE:
9360f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9361f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
9362f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9363f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9364f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9365f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
9366f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9367f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PARENT:
9368f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9369f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
9370f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9371f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9372f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextParent;
9373f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9374f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PRECEDING:
9375f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9376f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
9377f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9378f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9379f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingInternal;
9380f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9381f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PRECEDING_SIBLING:
9382f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9383f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9384f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'preceding-sibling' ");
9385f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingSibling;
9388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_SELF:
9390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9391f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
9392f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextSelf;
9396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9397f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (next == NULL)
9399f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
9400f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    nodelist = obj->nodesetval;
9402f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (nodelist == NULL) {
9403f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlXPathFreeObject(obj);
9404f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
9405f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
9406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    addNode = xmlXPathNodeSetAddUnique;
9408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9409f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9410f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    " context contains %d nodes\n", nodelist->nodeNr);
9411f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (test) {
9412f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NONE:
9413f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for none !!!\n");
9415f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9416f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_TYPE:
9417f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9418f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for type %d\n", type);
9419f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9420f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_PI:
9421f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9422f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for PI !!!\n");
9423f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9424f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_ALL:
9425f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9426f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for *\n");
9427f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9428f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NS:
9429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for namespace %s\n",
9431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            prefix);
9432f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9433f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NAME:
9434f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9435f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for name %s\n", name);
9436f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (prefix != NULL)
9437f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlGenericError(xmlGenericErrorContext,
9438f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                "           with namespace %s\n", prefix);
9439f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9440f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9441f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "Testing : ");
9442f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9443f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    /*
9444f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * 2.3 Node Tests
9445f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For the attribute axis, the principal node type is attribute.
9446f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For the namespace axis, the principal node type is namespace.
9447f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For other axes, the principal node type is element.
9448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *
9449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * A node test * is true for any node of the
9450cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard     * principal node type. For example, child::* will
9451f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * select all element children of the context node
9452f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     */
9453f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    tmp = ctxt->context->node;
9454f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    list = xmlXPathNodeSetCreate(NULL);
9455f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < nodelist->nodeNr; i++) {
9456f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->context->node = nodelist->nodeTab[i];
9457f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9458f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = NULL;
9459f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        n = 0;
9460f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        do {
9461f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur = next(ctxt, cur);
9462f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (cur == NULL)
9463f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9464f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((first != NULL) && (*first == cur))
9465f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9466f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (first != NULL) && (*first != NULL) &&
9468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(*first, cur) >= 0))
9469f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((last != NULL) && (*last == cur))
9471f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9472f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9473f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (last != NULL) && (*last != NULL) &&
9474f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(cur, *last) >= 0))
9475f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9476f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            t++;
9477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            switch (test) {
9478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NONE:
9479f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = tmp;
9480f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    STRANGE return(0);
9481f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_TYPE:
9482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((cur->type == type) ||
9483f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ((type == NODE_TYPE_NODE) &&
9484f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         ((cur->type == XML_DOCUMENT_NODE) ||
9485f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_HTML_DOCUMENT_NODE) ||
9486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_ELEMENT_NODE) ||
9487f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_PI_NODE) ||
9488f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_COMMENT_NODE) ||
9489f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_CDATA_SECTION_NODE) ||
94908606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard                          (cur->type == XML_TEXT_NODE))) ||
94918606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard			((type == NODE_TYPE_TEXT) &&
94928606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard			 (cur->type == XML_CDATA_SECTION_NODE))) {
9493f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9494f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (n == indx)
9495f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9496f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9497f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_PI:
9499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (cur->type == XML_PI_NODE) {
9500f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((name != NULL) &&
9501f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (!xmlStrEqual(name, cur->name)))
9502f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (n == indx)
9505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9506f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9507f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9508f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_ALL:
9509f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (axis == AXIS_ATTRIBUTE) {
9510f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ATTRIBUTE_NODE) {
9511f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9512f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (n == indx)
9513f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9514f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9515f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else if (axis == AXIS_NAMESPACE) {
9516f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_NAMESPACE_DECL) {
9517f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9518f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (n == indx)
9519044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				xmlXPathNodeSetAddNs(list, ctxt->context->node,
9520044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard						     (xmlNsPtr) cur);
9521f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9522f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else {
9523f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ELEMENT_NODE) {
9524f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (prefix == NULL) {
9525f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9526f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (n == indx)
9527f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    addNode(list, cur);
9528f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            } else if ((cur->ns != NULL) &&
9529f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                       (xmlStrEqual(URI, cur->ns->href))) {
9530f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (n == indx)
9532f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    addNode(list, cur);
9533f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9534f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9535f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9536f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9537f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NS:{
9538f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        TODO;
9539f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        break;
9540f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9541f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NAME:
9542f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    switch (cur->type) {
9543f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ELEMENT_NODE:
9544f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (xmlStrEqual(name, cur->name)) {
9545f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (prefix == NULL) {
9546f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (cur->ns == NULL) {
9547f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9548f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if (n == indx)
9549f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list, cur);
9550f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9551f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                } else {
9552f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if ((cur->ns != NULL) &&
9553f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        (xmlStrEqual(URI,
9554f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     cur->ns->href))) {
9555f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9556f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if (n == indx)
9557f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list, cur);
9558f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9559f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9560f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9561f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9562f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ATTRIBUTE_NODE:{
9563f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlAttrPtr attr = (xmlAttrPtr) cur;
9564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9565f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (xmlStrEqual(name, attr->name)) {
9566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (prefix == NULL) {
9567f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns == NULL) ||
9568f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (attr->ns->prefix == NULL)) {
9569f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9570f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            if (n == indx)
9571f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                addNode(list, cur);
9572f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9573f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    } else {
9574f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns != NULL) &&
9575f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (xmlStrEqual(URI,
9576f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         attr->ns->
9577f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         href))) {
9578f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9579f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            if (n == indx)
9580f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                addNode(list, cur);
9581f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9582f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9583f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9584f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                break;
9585f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9586f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_NAMESPACE_DECL:
9587f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (cur->type == XML_NAMESPACE_DECL) {
9588f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlNsPtr ns = (xmlNsPtr) cur;
9589f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9590f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if ((ns->prefix != NULL) && (name != NULL)
9591f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    && (xmlStrEqual(ns->prefix, name))) {
9592f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    n++;
9593f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (n == indx)
9594044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					xmlXPathNodeSetAddNs(list,
9595044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					   ctxt->context->node, (xmlNsPtr) cur);
9596f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9597f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9598f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9599f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        default:
9600f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9601f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9602f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9603f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9604f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9605f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } while (n < indx);
9606f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9607f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    ctxt->context->node = tmp;
9608f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9609f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9610f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "\nExamined %d nodes, found %d nodes at that step\n",
9611f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    t, list->nodeNr);
9612f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9613f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(list));
96140ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->boolval) && (obj->user != NULL)) {
96150ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->boolval = 1;
96160ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->user = obj->user;
96170ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->user = NULL;
96180ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->boolval = 0;
96190ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    }
96200ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    xmlXPathFreeObject(obj);
9621f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(t);
9622f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
9623f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9624f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
9625f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEvalFirst:
9626d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
9627d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @op:  an XPath compiled operation
9628f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  the first elem found so far
9629d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
9630f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation searching only the first
9631f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * element in document order
9632f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9633f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of examined objects.
9634d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
9635f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9636f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
9637f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathStepOpPtr op, xmlNodePtr * first)
9638f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
9639f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0, cur;
9640d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathCompExprPtr comp;
9641d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
9642d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9643556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
9644d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    comp = ctxt->comp;
9645d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (op->op) {
9646f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
9647f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9648f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
9649f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total =
9650f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
9651f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        first);
9652556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9653f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9654f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9655f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
9656f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
9657f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9658f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * limit tree traversing to first node in the result
9659f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9660f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9661f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                *first = ctxt->value->nodesetval->nodeTab[0];
9662f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9663f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur =
9664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
9665f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        first);
9666556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9667f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9668f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
9669f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9670f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9671f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9672f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9673f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
9674f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
9675f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9676f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9677f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            /* optimizer */
9678f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (total > cur)
9679f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		xmlXPathCompSwap(op);
9680f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total + cur);
9681f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
9682f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
9683f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9684f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
9685f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9686f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9687556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9688f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9689f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9690556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9691f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
9692f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9693f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
9694f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9695f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9696556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9697f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9698f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9699556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9700f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
9701f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9702f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
9703f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
9704f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
9705f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9706f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9707556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
9708f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9709f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9710f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
9711f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9712f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
9713f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
9714f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
9715f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
9716f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
9717f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
9718f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
9719f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9720f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
9721f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
9722f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
9723f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9724f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
9725f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathNodeCollectAndTestNth(ctxt, op, indx,
9726f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                          first, NULL);
9727f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
9728f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9729f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9730f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
9731f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL);
9732f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9733f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9734f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
9735f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
9736f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
9737f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9738f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
9739f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9740f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total +=
9741f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
9742f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            first);
9743556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9744f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9745f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9746f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL))
9747f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9748f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9749f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        default:
9750f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (xmlXPathCompOpEval(ctxt, op));
9751f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9752f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
975342596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard
9754f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
9755f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEvalLast:
9756f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
9757f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  an XPath compiled operation
9758f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  the last elem found so far
9759f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9760f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation searching only the last
9761f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * element in document order
9762f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9763f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
9764f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
9765f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9766f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
9767f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                       xmlNodePtr * last)
9768f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
9769f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0, cur;
9770f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathCompExprPtr comp;
9771f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
97729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9773556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
9774f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp = ctxt->comp;
9775f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (op->op) {
9776f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
9777f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9778f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
9779f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total =
9780f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
9781556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9782f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9783f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9784f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
9785f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
9786f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9787f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * limit tree traversing to first node in the result
9788f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9789f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9790f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                *last =
9791f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->value->nodesetval->nodeTab[ctxt->value->
9792f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     nodesetval->nodeNr -
9793f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     1];
9794f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9795f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur =
9796f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
9797556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9799f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9800f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
9801f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
9802f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9803f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9804f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
9805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9808f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9809f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
9810f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
9811f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9812f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9813f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            /* optimizer */
9814f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (total > cur)
9815f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		xmlXPathCompSwap(op);
9816f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total + cur);
9817f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
9818f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
9819f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9820f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
9821f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9822f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9823556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9824f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9825f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9826556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9827f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
9828f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9829f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
9830f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9832556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9834f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9835556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9836f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
9837f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9838f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
9839f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
9840f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (0);
9841f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9842f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9843556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
9844f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9845f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9846f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
9847f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9848f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
9849f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
9850f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
9851f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
9852f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
9853f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
9854f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
9855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9856f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
9857f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
9858f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
9859f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9860f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
9861f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
9862f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathNodeCollectAndTestNth(ctxt, op,
9863f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              indx, NULL,
9864f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              last);
9865f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
9866f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9867f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9868f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
9869f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last);
9870f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9871f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9872f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
9873f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
9874f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
9875f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9876f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
9877f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9878f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total +=
9879f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1],
9880f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                           last);
9881556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9882f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9883f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9884f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL))
9885f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9886f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9887f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        default:
9888f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (xmlXPathCompOpEval(ctxt, op));
9889f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9890f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
98919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9892f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
9893f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEval:
9894f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
9895f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  an XPath compiled operation
9896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation
9898f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
9899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
9900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9901f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
9902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
9903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0;
9904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int equal, ret;
9905f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathCompExprPtr comp;
9906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
99077089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard    xmlNodePtr bak;
99087089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard    xmlDocPtr bakd;
99096000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack    int pp;
9910692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack    int cs;
99119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9912556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
9913f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp = ctxt->comp;
9914f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (op->op) {
9915f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
9916f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9917f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_AND:
99187089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
99197089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
99206000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9921692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9922f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9923556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9924f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
9925f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
9926f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
99287089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
99297089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
99306000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9931692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9933556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    if (ctxt->error) {
9934556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathFreeObject(arg2);
9935556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		return(0);
9936556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    }
9937f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
9938f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9939f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->boolval &= arg2->boolval;
9940f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9942f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_OR:
99447089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
99457089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
99466000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9947692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9948f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9949556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9950f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
9951f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
9952f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
9953f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
99547089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
99557089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
99566000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9957692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9959556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    if (ctxt->error) {
9960556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathFreeObject(arg2);
9961556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		return(0);
9962556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    }
9963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
9964f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9965f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->boolval |= arg2->boolval;
9966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9967f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9968f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_EQUAL:
99707089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
99717089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
99726000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9973692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9975556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
99767089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
99777089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
99786000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9979692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9980f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9981556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
99820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (op->value)
99830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        	equal = xmlXPathEqualValues(ctxt);
99840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    else
99850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		equal = xmlXPathNotEqualValues(ctxt);
99860c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    valuePush(ctxt, xmlXPathNewBoolean(equal));
9987f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9988f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_CMP:
99897089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
99907089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
99916000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
9992692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
9993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9994556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
99957089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
99967089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
99976000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
9998692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
9999f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10000556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10001f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
10002f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewBoolean(ret));
10003f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10004f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_PLUS:
100057089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
100067089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
100076000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10008692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10009f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10010556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
100117089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard            if (op->ch2 != -1) {
100127089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard		ctxt->context->doc = bakd;
100137089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard		ctxt->context->node = bak;
100146000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack		ctxt->context->proximityPosition = pp;
10015692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack		ctxt->context->contextSize = cs;
10016f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
100177089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    }
10018556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10019f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value == 0)
10020f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathSubValues(ctxt);
10021f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 1)
10022f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathAddValues(ctxt);
10023f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 2)
10024f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathValueFlipSign(ctxt);
10025f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 3) {
10026f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CAST_TO_NUMBER;
10027f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NUMBER);
10028f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10029f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10030f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_MULT:
100317089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
100327089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
100336000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10034692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10035f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10036556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
100377089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
100387089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
100396000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10040692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10041f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10042556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10043f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value == 0)
10044f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathMultValues(ctxt);
10045f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 1)
10046f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathDivValues(ctxt);
10047f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 2)
10048f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathModValues(ctxt);
10049f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10050f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
100517089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
100527089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
100536000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10054692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10055f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10056556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
100577089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
100587089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
100596000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10060692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10061f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10062556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10063f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10064f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
10065f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10066f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10067f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10068f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10069f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
10070f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
10071f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10072f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10073f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10074f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
10075f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
10076f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10077f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
10078f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10079f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10080556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10081f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10082f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10083556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10084f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
10085f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10086f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
10087f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10088f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10089556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10090f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10091f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10092556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10093f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
10094f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10095f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
10096f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
10097f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10098f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10099f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10100556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10101f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10102f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10103f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
10104f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10105f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
10106f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
10107f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
10108f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
10109f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
10110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
10111f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10112f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10113f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
10114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
10115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
10116f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
10118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10119f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathNodeCollectAndTestNth(ctxt, op,
10120f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              indx, NULL,
10121f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              NULL);
10122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10123f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10124f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10125f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10126f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL);
10127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10128f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10129f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
10130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
10131f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
10132f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10133f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VARIABLE:{
10134556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathObjectPtr val;
10135556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard
10136f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10139556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                if (op->value5 == NULL) {
10140556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    val = xmlXPathVariableLookup(ctxt->context, op->value4);
10141556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (val == NULL) {
10142556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
10143556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return(0);
10144556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10145556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                    valuePush(ctxt, val);
10146556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		} else {
10147f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    const xmlChar *URI;
10148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10149f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    URI = xmlXPathNsLookup(ctxt->context, op->value5);
10150f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (URI == NULL) {
10151f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlGenericError(xmlGenericErrorContext,
10152cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                        "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
10153f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        op->value4, op->value5);
10154f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10155f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10156556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    val = xmlXPathVariableLookupNS(ctxt->context,
10157556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                                                       op->value4, URI);
10158556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (val == NULL) {
10159556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
10160556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return(0);
10161556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10162556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                    valuePush(ctxt, val);
10163f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10164f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10165f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10166f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_FUNCTION:{
10167f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFunction func;
10168f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                const xmlChar *oldFunc, *oldFuncURI;
10169556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		int i;
10170f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10171f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10172f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10173f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10174556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		if (ctxt->valueNr < op->value) {
10175556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    xmlGenericError(xmlGenericErrorContext,
10176cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard			    "xmlXPathCompOpEval: parameter error\n");
10177556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    ctxt->error = XPATH_INVALID_OPERAND;
10178556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    return (total);
10179556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		}
10180556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		for (i = 0; i < op->value; i++)
10181556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
10182556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			xmlGenericError(xmlGenericErrorContext,
10183cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard				"xmlXPathCompOpEval: parameter error\n");
10184556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_INVALID_OPERAND;
10185556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return (total);
10186556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->cache != NULL)
10188f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    func = (xmlXPathFunction) op->cache;
10189f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                else {
10190f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    const xmlChar *URI = NULL;
10191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10192f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (op->value5 == NULL)
10193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        func =
10194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFunctionLookup(ctxt->context,
10195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   op->value4);
10196f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    else {
10197f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        URI = xmlXPathNsLookup(ctxt->context, op->value5);
10198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (URI == NULL) {
10199f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlGenericError(xmlGenericErrorContext,
10200cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                            "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
10201f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            op->value4, op->value5);
10202f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10203f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10204f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        func = xmlXPathFunctionLookupNS(ctxt->context,
10205f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                        op->value4, URI);
10206f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10207f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (func == NULL) {
10208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlGenericError(xmlGenericErrorContext,
10209cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                        "xmlXPathCompOpEval: function %s not found\n",
10210f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        op->value4);
10211f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
10212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    op->cache = (void *) func;
10214f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    op->cacheURI = (void *) URI;
10215f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldFunc = ctxt->context->function;
10217f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldFuncURI = ctxt->context->functionURI;
10218f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->function = op->value4;
10219f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->functionURI = op->cacheURI;
10220f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                func(ctxt, op->value);
10221f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->function = oldFunc;
10222f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->functionURI = oldFuncURI;
10223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10224f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10225f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ARG:
10226088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    bakd = ctxt->context->doc;
10227088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    bak = ctxt->context->node;
10228f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10229f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10230088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->doc = bakd;
10231088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->node = bak;
10232556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10233f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10234f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10235088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->doc = bakd;
10236088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->node = bak;
10237556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10238f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10239f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_PREDICATE:
10240f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_FILTER:{
10241f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr res;
10242f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr obj, tmp;
10243f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr newset = NULL;
10244f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr oldset;
10245f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodePtr oldnode;
10246f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                int i;
10247f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10248f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10249f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for ()[1] selection i.e. the first elem
10250f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10251f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch1 != -1) && (op->ch2 != -1) &&
10252f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
10253f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_VALUE)) {
10254f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10256f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[op->ch2].value4;
10257f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER) &&
10258f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (val->floatval == 1.0)) {
10259f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlNodePtr first = NULL;
10260f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10261f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10262f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEvalFirst(ctxt,
10263f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    &comp->steps[op->ch1],
10264f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    &first);
10265556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			CHECK_ERROR0;
10266f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10267f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The nodeset should be in document order,
10268f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Keep only the first value
10269f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10270f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((ctxt->value != NULL) &&
10271f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->type == XPATH_NODESET) &&
10272f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval != NULL) &&
10273f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeNr > 1))
10274f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeNr = 1;
10275f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10276f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10277f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10278f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10279f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for ()[last()] selection i.e. the last elem
10280f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10281f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch1 != -1) && (op->ch2 != -1) &&
10282f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
10283f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
10284f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    int f = comp->steps[op->ch2].ch1;
10285f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10286f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((f != -1) &&
10287f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].op == XPATH_OP_FUNCTION) &&
10288f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value5 == NULL) &&
10289f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value == 0) &&
10290f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value4 != NULL) &&
10291f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (xmlStrEqual
10292f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         (comp->steps[f].value4, BAD_CAST "last"))) {
10293f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlNodePtr last = NULL;
10294f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10295f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10296f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEvalLast(ctxt,
10297f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch1],
10298f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &last);
10299556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			CHECK_ERROR0;
10300f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10301f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The nodeset should be in document order,
10302f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Keep only the last value
10303f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10304f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((ctxt->value != NULL) &&
10305f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->type == XPATH_NODESET) &&
10306f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval != NULL) &&
10307f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeTab != NULL) &&
10308f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeNr > 1)) {
10309f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeTab[0] =
10310f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                ctxt->value->nodesetval->nodeTab[ctxt->
10311f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 value->
10312f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 nodesetval->
10313f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 nodeNr -
10314f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 1];
10315f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeNr = 1;
10316f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10317f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10318f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10320f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10323f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10324556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10325f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch2 == -1)
10326f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10327f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (ctxt->value == NULL)
10328f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10329f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10330f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldnode = ctxt->context->node;
103319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10332f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
10333f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10334f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Hum are we filtering the result of an XPointer expression
10335f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10336f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (ctxt->value->type == XPATH_LOCATIONSET) {
10337f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlLocationSetPtr newlocset = NULL;
10338f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlLocationSetPtr oldlocset;
10339f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10340f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10341f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * Extract the old locset, and then evaluate the result of the
10342f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * expression for all the element in the locset. use it to grow
10343f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * up a new locset.
10344f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10345f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    CHECK_TYPE0(XPATH_LOCATIONSET);
10346f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    obj = valuePop(ctxt);
10347f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    oldlocset = obj->user;
10348f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10349f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10350f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
10351f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = 0;
10352f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = 0;
10353f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10354f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10355f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10356f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10357f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10358f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10359f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10360f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, obj);
10361f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10362f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10363f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10364f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    newlocset = xmlXPtrLocationSetCreate(NULL);
10365f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10366f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldlocset->locNr; i++) {
10367f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10368f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of a
10369f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * single item in the nodelocset.
10370f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10371f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldlocset->locTab[i]->user;
10372f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10373f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
10374f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = oldlocset->locNr;
10375f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = i + 1;
10376f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10377f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10378f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10379f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10380f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10381f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10382f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10383f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10384f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The result of the evaluation need to be tested to
10385f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * decided whether the filter succeeded or not
10386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
10389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPtrLocationSetAdd(newlocset,
10390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                  xmlXPathObjectCopy
10391f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                  (oldlocset->locTab[i]));
10392f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10397f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10399f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10400f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10402f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10403f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10404f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10405f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * The result is used as the new evaluation locset.
10409f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10410f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathFreeObject(obj);
10411f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10412f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = -1;
10413f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = -1;
10414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
10415f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = oldnode;
10416f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10417f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
104189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
104199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10420f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10421f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Extract the old set, and then evaluate the result of the
10422f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * expression for all the element in the set. use it to grow
10423f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * up a new set.
10424f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10425f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NODESET);
10426f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                obj = valuePop(ctxt);
10427f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldset = obj->nodesetval;
10428f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldnode = ctxt->context->node;
10430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
10431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10432f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((oldset == NULL) || (oldset->nodeNr == 0)) {
10433f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = 0;
10434f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = 0;
10435f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (op->ch2 != -1)
10436f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10437f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEval(ctxt,
10438f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                               &comp->steps[op->ch2]);
10439556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    CHECK_ERROR0;
10440f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    res = valuePop(ctxt);
10441f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (res != NULL)
10442f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathFreeObject(res);
10443f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, obj);
10444f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = oldnode;
10445f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    CHECK_ERROR0;
10446f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                } else {
10447f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * Initialize the new set.
10449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10450f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    newset = xmlXPathNodeSetCreate(NULL);
10451f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10452f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldset->nodeNr; i++) {
10453f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10454f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of
10455f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * a single item in the nodeset.
10456f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10457f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldset->nodeTab[i];
10458f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10459f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
10460f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = oldset->nodeNr;
10461f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = i + 1;
10462f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10463f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10464f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10465f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10466f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10469f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The result of the evaluation need to be tested to
10471f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * decided whether the filter succeeded or not
10472f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10473f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10474f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
10475f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
10476f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10479f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10480f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10481f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10483f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10484f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10485f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10487f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10488f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10489f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10490f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10491f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10492f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * The result is used as the new evaluation set.
10493f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10494f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathFreeObject(obj);
10495f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10496f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = -1;
10497f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = -1;
10498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, xmlXPathWrapNodeSet(newset));
10499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10500f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = oldnode;
10501f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10502f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
10504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10506556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10507f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL) &&
10508f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                (ctxt->value->type == XPATH_NODESET) &&
10509f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                (ctxt->value->nodesetval != NULL))
10510f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10511f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
105129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#ifdef LIBXML_XPTR_ENABLED
10513f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RANGETO:{
10514f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr range;
10515f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr res, obj;
10516f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr tmp;
10517f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlLocationSetPtr newset = NULL;
10518f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr oldset;
10519f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                int i;
10520f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10521f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10522f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10523f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10524f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch2 == -1)
10525f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10526f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10527f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NODESET);
10528f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                obj = valuePop(ctxt);
10529f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldset = obj->nodesetval;
10530f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
10531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10532f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                newset = xmlXPtrLocationSetCreate(NULL);
10533f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10534f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (oldset != NULL) {
10535f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldset->nodeNr; i++) {
10536f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10537f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of a single item
10538f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * in the nodeset.
10539f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10540f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldset->nodeTab[i];
10541f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10542f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
10543f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10544f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10545f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10546f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10547f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10548f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10549f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10550f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10551f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The result of the evaluation need to be tested to
10552f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * decided whether the filter succeeded or not
10553f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10554f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10555f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        range =
10556f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPtrNewRangeNodeObject(oldset->nodeTab[i],
10557f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                      res);
10558f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (range != NULL) {
10559f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPtrLocationSetAdd(newset, range);
10560f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10561f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10562f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10563f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10565f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10567f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10568f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10569f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10570f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10571f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10572f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10573f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10574f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10575f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10576f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10577f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * The result is used as the new evaluation set.
10578f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10579f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFreeObject(obj);
10580f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
10581f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->contextSize = -1;
10582f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->proximityPosition = -1;
10583f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
10584f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10585f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
105869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
105879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
105889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlGenericError(xmlGenericErrorContext,
10589f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "XPath: unknown precompiled operation %d\n", op->op);
10590f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (total);
105919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
105929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
105939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
105949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathRunEval:
105959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctxt:  the XPath parser context with the compiled expression
105969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
105979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Evaluate the Precompiled XPath expression in the given context.
105989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
10599fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardstatic void
106009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathRunEval(xmlXPathParserContextPtr ctxt) {
106019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprPtr comp;
106029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
106039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((ctxt == NULL) || (ctxt->comp == NULL))
106049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
106059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
106069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->valueTab == NULL) {
106079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	/* Allocate the value stack */
106089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueTab = (xmlXPathObjectPtr *)
106099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
106109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (ctxt->valueTab == NULL) {
106119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlFree(ctxt);
106129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
106139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueNr = 0;
106149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueMax = 10;
106159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->value = NULL;
106169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
106179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp = ctxt->comp;
1061829b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin    if(comp->last < 0) {
1061929b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	xmlGenericError(xmlGenericErrorContext,
1062029b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	    "xmlXPathRunEval: last is less than zero\n");
1062129b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	return;
1062229b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin    }
106239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
106249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
106259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10626afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/************************************************************************
10627afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *									*
10628afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * 			Public interfaces				*
10629afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *									*
10630afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard ************************************************************************/
10631afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
10632afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
10633fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathEvalPredicate:
10634fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath context
10635fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @res:  the Predicate Expression evaluation result
10636fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
10637fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Evaluate a predicate result for the current node.
10638fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * A PredicateExpr is evaluated by evaluating the Expr and converting
10639fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * the result to a boolean. If the result is a number, the result will
10640fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * be converted to true if the number is equal to the position of the
10641fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * context node in the context node list (as returned by the position
10642fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * function) and will be converted to false otherwise; if the result
10643fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * is not a number, then the result will be converted as if by a call
10644fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * to the boolean function.
10645fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
10646cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if predicate is true, 0 otherwise
10647fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
10648fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardint
10649fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
10650fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (res == NULL) return(0);
10651fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    switch (res->type) {
10652fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_BOOLEAN:
10653fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->boolval);
10654fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_NUMBER:
10655fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->floatval == ctxt->proximityPosition);
10656fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_NODESET:
10657fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_XSLT_TREE:
10658d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    if (res->nodesetval == NULL)
10659d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		return(0);
10660fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->nodesetval->nodeNr != 0);
10661fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_STRING:
10662fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return((res->stringval != NULL) &&
10663fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	           (xmlStrlen(res->stringval) != 0));
10664fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        default:
10665fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    STRANGE
10666fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    }
10667fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    return(0);
10668fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard}
10669fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
10670fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
10671afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathEvaluatePredicateResult:
10672afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @ctxt:  the XPath Parser context
10673afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @res:  the Predicate Expression evaluation result
10674afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10675afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Evaluate a predicate result for the current node.
10676afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * A PredicateExpr is evaluated by evaluating the Expr and converting
10677afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * the result to a boolean. If the result is a number, the result will
10678afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * be converted to true if the number is equal to the position of the
10679afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * context node in the context node list (as returned by the position
10680afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * function) and will be converted to false otherwise; if the result
10681afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * is not a number, then the result will be converted as if by a call
10682afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * to the boolean function.
10683afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10684cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if predicate is true, 0 otherwise
10685afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
10686afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardint
10687afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
10688afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard                                xmlXPathObjectPtr res) {
10689afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    if (res == NULL) return(0);
10690afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    switch (res->type) {
10691afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_BOOLEAN:
10692afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->boolval);
10693afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_NUMBER:
10694afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->floatval == ctxt->context->proximityPosition);
10695afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_NODESET:
10696afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_XSLT_TREE:
1069773639a73c5a51c3739595f54c338bb531c1319c2Daniel Veillard	    if (res->nodesetval == NULL)
10698911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		return(0);
10699afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->nodesetval->nodeNr != 0);
10700afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_STRING:
10701afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return((res->stringval != NULL) &&
10702afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	           (xmlStrlen(res->stringval) != 0));
10703afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        default:
10704afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    STRANGE
10705afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    }
10706afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    return(0);
10707afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
10708afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
10709afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
10710afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompile:
10711afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @str:  the XPath expression
10712afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10713afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an XPath expression
10714afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10715591b4be0fe1986b5e71d54c5c063493987ef4285Daniel Veillard * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
10716afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *         the caller has to free the object.
10717afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
10718afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompExprPtr
10719afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompile(const xmlChar *str) {
10720afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathParserContextPtr ctxt;
10721afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompExprPtr comp;
10722afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
10723afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathInit();
10724afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
10725afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    ctxt = xmlXPathNewParserContext(str, NULL);
10726afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompileExpr(ctxt);
1072750fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin
1072840af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    if (*ctxt->cur != 0) {
1072950fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	/*
1073050fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * aleksey: in some cases this line prints *second* error message
1073150fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * (see bug #78858) and probably this should be fixed.
1073250fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * However, we are not sure that all error messages are printed
1073350fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * out in other places. It's not critical so we leave it as-is for now
1073450fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 */
1073540af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
1073640af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	comp = NULL;
1073740af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    } else {
1073840af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	comp = ctxt->comp;
1073940af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	ctxt->comp = NULL;
1074040af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    }
10741afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathFreeParserContext(ctxt);
10742f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (comp != NULL) {
10743ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard	comp->expr = xmlStrdup(str);
10744ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
10745f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->string = xmlStrdup(str);
10746f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->nb = 0;
10747f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
10748ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard    }
10749afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    return(comp);
10750afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
10751afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
107529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
107539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompiledEval:
107549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the compiled XPath expression
107559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctx:  the XPath context
107569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
107579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Evaluate the Precompiled XPath expression in the given context.
107589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
10759cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
107609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *         the caller has to free the object.
107619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
107629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathObjectPtr
107639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx) {
107649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathParserContextPtr ctxt;
107659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathObjectPtr res, tmp, init = NULL;
107669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int stack = 0;
107678146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
107688146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    static int reentance = 0;
107698146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
107709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
107719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((comp == NULL) || (ctx == NULL))
107729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
107739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathInit();
107749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
107759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    CHECK_CONTEXT(ctx)
107769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
107778146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
107788146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    reentance++;
107798146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    if (reentance > 1)
107808146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard	xmlXPathDisableOptimizer = 1;
107818146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
107828146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard
10783f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
10784f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp->nb++;
10785f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((comp->string != NULL) && (comp->nb > 100)) {
10786f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	fprintf(stderr, "100 x %s\n", comp->string);
10787f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->nb = 0;
10788f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10789f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
107909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt = xmlXPathCompParserContext(comp, ctx);
107919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathRunEval(ctxt);
107929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
107939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->value == NULL) {
107949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlGenericError(xmlGenericErrorContext,
10795cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompiledEval: evaluation failed\n");
107969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = NULL;
107979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    } else {
107989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = valuePop(ctxt);
107999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
108009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10801f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
108029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    do {
108039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        tmp = valuePop(ctxt);
108049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (tmp != NULL) {
108059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (tmp != init)
108069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		stack++;
108079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathFreeObject(tmp);
108089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        }
108099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    } while (tmp != NULL);
108109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((stack != 0) && (res != NULL)) {
108119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlGenericError(xmlGenericErrorContext,
10812cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompiledEval: %d object left on the stack\n",
108139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	        stack);
108149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
108159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->error != XPATH_EXPRESSION_OK) {
108169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathFreeObject(res);
108179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = NULL;
108189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
108199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
108209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10821afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    ctxt->comp = NULL;
108229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathFreeParserContext(ctxt);
108238146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
108248146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    reentance--;
108258146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
108269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(res);
108279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
108289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10829afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
10830afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathEvalExpr:
10831afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @ctxt:  the XPath Parser context
10832afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
10833afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Parse and evaluate an XPath expression in the given context,
10834afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * then push the result on the context stack
10835afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
10836afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardvoid
10837afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
10838afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompileExpr(ctxt);
1083950fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin    CHECK_ERROR;
10840afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathRunEval(ctxt);
10841afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
108429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
108433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
108443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEval:
108453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
108463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctx:  the XPath context
108473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
108483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Evaluate the XPath Location Path in the given context.
108493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
10850cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
108513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         the caller has to free the object.
108523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
108533473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
108543473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
108553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr ctxt;
108563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr res, tmp, init = NULL;
108573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int stack = 0;
108583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
108593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathInit();
108603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
108613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_CONTEXT(ctx)
108623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
108633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt = xmlXPathNewParserContext(str, ctx);
108643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathEvalExpr(ctxt);
108653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
108663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->value == NULL) {
108673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
108683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEval: evaluation failed\n");
108693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
108703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (*ctxt->cur != 0) {
108713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
108723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
108733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
108743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = valuePop(ctxt);
108753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
108763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
108773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
108783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        tmp = valuePop(ctxt);
108793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (tmp != NULL) {
108803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (tmp != init)
108813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		stack++;
108823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(tmp);
108833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
108843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (tmp != NULL);
108853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((stack != 0) && (res != NULL)) {
108863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
108873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEval: %d object left on the stack\n",
108883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        stack);
108893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
108903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->error != XPATH_EXPRESSION_OK) {
108913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(res);
108923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
108933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
108949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
108953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeParserContext(ctxt);
108963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(res);
108973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
108983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
108993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
109003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEvalExpression:
109013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
109023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
109033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
109043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Evaluate the XPath expression in the given context.
109053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
109063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
109073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         the caller has to free the object.
109083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
109093473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
109103473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
109113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr pctxt;
109123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr res, tmp;
109133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int stack = 0;
109143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
109153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathInit();
109163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
109173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_CONTEXT(ctxt)
109183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
109193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    pctxt = xmlXPathNewParserContext(str, ctxt);
109203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathEvalExpr(pctxt);
109213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
109223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*pctxt->cur != 0) {
109233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
109243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
109253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
109263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = valuePop(pctxt);
109273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
109283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
109293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        tmp = valuePop(pctxt);
109303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (tmp != NULL) {
109313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(tmp);
109323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    stack++;
109333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
109343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (tmp != NULL);
109353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((stack != 0) && (res != NULL)) {
109363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
109373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEvalExpression: %d object left on the stack\n",
109383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        stack);
109393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
109403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeParserContext(pctxt);
109413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(res);
109423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
109433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1094442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard/************************************************************************
1094542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *									*
1094642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *	Extra functions not pertaining to the XPath spec		*
1094742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *									*
1094842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard ************************************************************************/
1094942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard/**
1095042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * xmlXPathEscapeUriFunction:
1095142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * @ctxt:  the XPath Parser context
1095242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * @nargs:  the number of arguments
1095342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1095442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Implement the escape-uri() XPath function
1095542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *    string escape-uri(string $str, bool $escape-reserved)
1095642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1095742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * This function applies the URI escaping rules defined in section 2 of [RFC
1095842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * 2396] to the string supplied as $uri-part, which typically represents all
1095942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * or part of a URI. The effect of the function is to replace any special
1096042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * character in the string by an escape sequence of the form %xx%yy...,
1096142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * where xxyy... is the hexadecimal representation of the octets used to
1096242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * represent the character in UTF-8.
1096342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1096442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * The set of characters that are escaped depends on the setting of the
1096542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * boolean argument $escape-reserved.
1096642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1096742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * If $escape-reserved is true, all characters are escaped other than lower
1096842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * case letters a-z, upper case letters A-Z, digits 0-9, and the characters
1096942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!"
1097042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only
1097142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and
1097242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * A-F).
1097342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1097442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * If $escape-reserved is false, the behavior differs in that characters
1097542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * referred to in [RFC 2396] as reserved characters are not escaped. These
1097642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",".
1097742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1097842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * [RFC 2396] does not define whether escaped URIs should use lower case or
1097942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * upper case for hexadecimal digits. To ensure that escaped URIs can be
1098042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * compared using string comparison functions, this function must always use
1098142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * the upper-case letters A-F.
1098242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1098342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Generally, $escape-reserved should be set to true when escaping a string
1098442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * that is to form a single part of a URI, and to false when escaping an
1098542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * entire URI or URI reference.
1098642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1098742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * In the case of non-ascii characters, the string is encoded according to
1098842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * utf-8 and then converted according to RFC 2396.
1098942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1099042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Examples
1099142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), true())
1099242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%2FLos%20Angeles%23ocean"
1099342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), false())
1099442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles%23ocean"
1099542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1099642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard */
10997118aed78f360f51d182770e62b251ef324707aa2Daniel Veillardstatic void
1099842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel VeillardxmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1099942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathObjectPtr str;
1100042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    int escape_reserved;
1100142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlBufferPtr target;
1100242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlChar *cptr;
1100342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlChar escape[4];
1100442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1100542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    CHECK_ARITY(2);
1100642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1100742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape_reserved = xmlXPathPopBoolean(ctxt);
1100842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1100942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    CAST_TO_STRING;
1101042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    str = valuePop(ctxt);
1101142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1101242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    target = xmlBufferCreate();
1101342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1101442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape[0] = '%';
1101542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape[3] = 0;
1101642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1101742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    if (target) {
1101842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	for (cptr = str->stringval; *cptr; cptr++) {
1101942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    if ((*cptr >= 'A' && *cptr <= 'Z') ||
1102042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr >= 'a' && *cptr <= 'z') ||
1102142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr >= '0' && *cptr <= '9') ||
1102242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '-' || *cptr == '_' || *cptr == '.' ||
1102342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '!' || *cptr == '~' || *cptr == '*' ||
1102442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '\''|| *cptr == '(' || *cptr == ')' ||
1102542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr == '%' &&
1102642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 ((cptr[1] >= 'A' && cptr[1] <= 'F') ||
1102742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[1] >= 'a' && cptr[1] <= 'f') ||
1102842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[1] >= '0' && cptr[1] <= '9')) &&
1102942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 ((cptr[2] >= 'A' && cptr[2] <= 'F') ||
1103042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[2] >= 'a' && cptr[2] <= 'f') ||
1103142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[2] >= '0' && cptr[2] <= '9'))) ||
1103242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(!escape_reserved &&
1103342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 (*cptr == ';' || *cptr == '/' || *cptr == '?' ||
1103442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == ':' || *cptr == '@' || *cptr == '&' ||
1103542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == '=' || *cptr == '+' || *cptr == '$' ||
1103642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == ','))) {
1103742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		xmlBufferAdd(target, cptr, 1);
1103842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    } else {
1103942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		if ((*cptr >> 4) < 10)
1104042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[1] = '0' + (*cptr >> 4);
1104142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		else
1104242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[1] = 'A' - 10 + (*cptr >> 4);
1104342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		if ((*cptr & 0xF) < 10)
1104442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[2] = '0' + (*cptr & 0xF);
1104542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		else
1104642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[2] = 'A' - 10 + (*cptr & 0xF);
1104742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1104842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		xmlBufferAdd(target, &escape[0], 3);
1104942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    }
1105042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	}
1105142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    }
1105242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
1105342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlBufferFree(target);
1105442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathFreeObject(str);
1105542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard}
1105642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
110573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
110583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterAllFunctions:
110593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
110603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
110613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Registers all default XPath functions in this context
110623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
110633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
110643473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
110653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor{
110663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
110673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathBooleanFunction);
110683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
110693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathCeilingFunction);
110703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
110713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathCountFunction);
110723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
110733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathConcatFunction);
110743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
110753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathContainsFunction);
110763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
110773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathIdFunction);
110783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
110793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathFalseFunction);
110803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
110813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathFloorFunction);
110823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
110833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLastFunction);
110843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
110853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLangFunction);
110863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
110873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLocalNameFunction);
110883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
110893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNotFunction);
110903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
110913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNameFunction);
110923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
110933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNamespaceURIFunction);
110943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
110953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNormalizeFunction);
110963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
110973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNumberFunction);
110983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
110993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathPositionFunction);
111003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
111013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathRoundFunction);
111023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
111033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStringFunction);
111043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
111053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStringLengthFunction);
111063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
111073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStartsWithFunction);
111083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
111093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringFunction);
111103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
111113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringBeforeFunction);
111123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
111133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringAfterFunction);
111143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
111153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSumFunction);
111163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
111173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathTrueFunction);
111183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
111193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathTranslateFunction);
1112042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1112142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
1112242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
1112342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard                         xmlXPathEscapeUriFunction);
111243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
111253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
111263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* LIBXML_XPATH_ENABLED */
11127