xpath.c revision ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1
13473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
23473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xpath.c: XML Path Language implementation
33473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *          XPath is a language for addressing parts of an XML document,
43473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *          designed to be used by both XSLT and XPointer
53473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Reference: W3C Recommendation 16 November 1999
73473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     http://www.w3.org/TR/1999/REC-xpath-19991116
83473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Public reference:
93473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     http://www.w3.org/TR/xpath
103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
11cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * See Copyright for the status of this software
123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13c5d64345cf19bfd72418eb0a837869b0462e9130Daniel Veillard * Author: daniel@veillard.com
143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1734ce8bece2f22cc99d25221b77315cd008f4866bDaniel Veillard#define IN_LIBXML
1870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese#include "libxml.h"
193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <string.h>
213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_SYS_TYPES_H
233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <sys/types.h>
243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_MATH_H
263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <math.h>
273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_FLOAT_H
293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <float.h>
303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_CTYPE_H
323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <ctype.h>
333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
345792e16f0562d206e1ef4e611f7b43ec53c92149Daniel Veillard#ifdef HAVE_SIGNAL_H
35b45c43be206b8c824558269731128c6a64599a54Daniel Veillard#include <signal.h>
36b45c43be206b8c824558269731128c6a64599a54Daniel Veillard#endif
373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlmemory.h>
393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/tree.h>
403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/valid.h>
413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpath.h>
423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpathInternals.h>
433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/parserInternals.h>
443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/hash.h>
453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xpointer.h>
473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_DEBUG_ENABLED
493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/debugXML.h>
503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlerror.h>
528146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#include <libxml/threads.h>
533c01b1d81b696fe8624b6d7e26ec0ebffcc7c06bDaniel Veillard#include <libxml/globals.h>
5456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef LIBXML_PATTERN_ENABLED
5556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#include <libxml/pattern.h>
5656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
5756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
5856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef LIBXML_PATTERN_ENABLED
59fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#define XPATH_STREAMING
6056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard#define TODO 								\
63d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    xmlGenericError(xmlGenericErrorContext,				\
64d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    "Unimplemented block at %s:%d\n",				\
65d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            __FILE__, __LINE__);
66d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
67d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack/*
68d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack * TODO:
69d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack * There are a few spots where some tests are done which depend upon ascii
70d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack * data.  These should be enhanced for full UTF8 support (see particularly
71d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
72d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack */
73d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack
7421e4ef20f64ebd740ebac0ead5d85a5631d2db5eWilliam M. Brack#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Floating point stuff				*
789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
81c0631a608f62902eca453096f0b2fc5b449b0b0aDaniel Veillard#ifndef TRIO_REPLACE_STDIO
82cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard#define TRIO_PUBLIC static
83c0631a608f62902eca453096f0b2fc5b449b0b0aDaniel Veillard#endif
84cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard#include "trionan.c"
85cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The lack of portability of this section of the libc is annoying !
883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathNAN = 0;
903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathPINF = 1;
913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble xmlXPathNINF = -1;
925fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillarddouble xmlXPathNZERO = 0;
9320ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillardstatic int xmlXPathInitialized = 0;
943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathInit:
973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initialize the XPath environment
993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
1013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathInit(void) {
10220ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    if (xmlXPathInitialized) return;
1033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
104450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathPINF = trio_pinf();
105450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathNINF = trio_ninf();
106450296070e14629141738fbb34b9a0ad13af1f02Bjorn Reese    xmlXPathNAN = trio_nan();
1075fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    xmlXPathNZERO = trio_nzero();
1083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
10920ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard    xmlXPathInitialized = 1;
1103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
1113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
112cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard/**
113cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * xmlXPathIsNaN:
114cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * @val:  a double value
115cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
116cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Provides a portable isnan() function to detect whether a double
117cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * is a NotaNumber. Based on trio code
118cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * http://sourceforge.net/projects/ctrio/
119cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
120cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Returns 1 if the value is a NaN, 0 otherwise
121cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard */
122cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillardint
123cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel VeillardxmlXPathIsNaN(double val) {
124cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    return(trio_isnan(val));
125cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard}
126cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
127cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard/**
128cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * xmlXPathIsInf:
129cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * @val:  a double value
130cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
131cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Provides a portable isinf() function to detect whether a double
132cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * is a +Infinite or -Infinite. Based on trio code
133cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * http://sourceforge.net/projects/ctrio/
134cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard *
135cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard * Returns 1 vi the value is +Infinite, -1 if -Infinite, 0 otherwise
136cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard */
137cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillardint
138cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel VeillardxmlXPathIsInf(double val) {
139cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    return(trio_isinf(val));
140cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard}
141cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard
1424432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#endif /* SCHEMAS or XPATH */
1434432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#ifdef LIBXML_XPATH_ENABLED
1445fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard/**
1455fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * xmlXPathGetSign:
1465fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * @val:  a double value
1475fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard *
1485fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Provides a portable function to detect the sign of a double
1495fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Modified from trio code
1505fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * http://sourceforge.net/projects/ctrio/
1515fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard *
1525fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard * Returns 1 if the value is Negative, 0 if positive
1535fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard */
15421458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillardstatic int
1555fc1f0893af6ffe76453ac16817204a866bdeab2Daniel VeillardxmlXPathGetSign(double val) {
15621458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    return(trio_signbit(val));
1575fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard}
1585fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
1595fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
160d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/*
161d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * TODO: when compatibility allows remove all "fake node libxslt" strings
162d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard *       the test should just be name[0] = ' '
163d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard */
164d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG */
165d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_STEP */
166d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_STEP_NTH */
167d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_EXPR */
168d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/* #define DEBUG_EVAL_COUNTS */
169d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard
170d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic xmlNs xmlXPathXMLNamespaceStruct = {
171d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    NULL,
172d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    XML_NAMESPACE_DECL,
173d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    XML_XML_NAMESPACE,
174d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    BAD_CAST "xml",
175d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard    NULL
176d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard};
177d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
178d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard#ifndef LIBXML_THREAD_ENABLED
179d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard/*
180d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * Optimizer is disabled only when threaded apps are detected while
181d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard * the library ain't compiled for thread safety.
182d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard */
183d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillardstatic int xmlXPathDisableOptimizer = 0;
184d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard#endif
185d9d32aebd3d09df9431859c3d9e7f7de781c73d4Daniel Veillard
1863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
187d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *									*
188d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *			Error handling routines				*
189d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *									*
190d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard ************************************************************************/
191d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
192081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack/*
193081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * The array xmlXPathErrorMessages corresponds to the enum xmlXPathError
194081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack */
195d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardstatic const char *xmlXPathErrorMessages[] = {
196d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Ok\n",
197d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Number encoding\n",
198d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Unfinished literal\n",
199d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Start of literal\n",
200d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Expected $ for variable reference\n",
201d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Undefined variable\n",
202d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid predicate\n",
203d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid expression\n",
204d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Missing closing curly brace\n",
205d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Unregistered function\n",
206d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid operand\n",
207d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid type\n",
208d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid number of arguments\n",
209d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid context size\n",
210d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Invalid context position\n",
211d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Memory allocation error\n",
212d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Syntax error\n",
213d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Resource error\n",
214d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Sub resource error\n",
215d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Undefined namespace prefix\n",
216d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    "Encoding error\n",
21757b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard    "Char out of XML range\n",
218cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack    "Invalid or incomplete context\n",
219cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack    "?? Unknown error ??\n"	/* Must be last in the list! */
220d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard};
221cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack#define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) /	\
222cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack		   sizeof(xmlXPathErrorMessages[0])) - 1)
223d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/**
224d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * xmlXPathErrMemory:
225d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @ctxt:  an XPath context
226d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @extra:  extra informations
227d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *
228d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * Handle a redefinition of attribute error
229d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard */
230d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardstatic void
231d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel VeillardxmlXPathErrMemory(xmlXPathContextPtr ctxt, const char *extra)
232d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard{
233d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    if (ctxt != NULL) {
234d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        if (extra) {
235d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            xmlChar buf[200];
236d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
237d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            xmlStrPrintf(buf, 200,
238d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                         BAD_CAST "Memory allocation failed : %s\n",
239d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                         extra);
240d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            ctxt->lastError.message = (char *) xmlStrdup(buf);
241d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        } else {
242d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard            ctxt->lastError.message = (char *)
243d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	       xmlStrdup(BAD_CAST "Memory allocation failed\n");
244d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        }
245d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        ctxt->lastError.domain = XML_FROM_XPATH;
246d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        ctxt->lastError.code = XML_ERR_NO_MEMORY;
247d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	if (ctxt->error != NULL)
248d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    ctxt->error(ctxt->userData, &ctxt->lastError);
249d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    } else {
250d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        if (extra)
251659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard            __xmlRaiseError(NULL, NULL, NULL,
252d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            NULL, NULL, XML_FROM_XPATH,
253d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
254d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            extra, NULL, NULL, 0, 0,
255d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            "Memory allocation failed : %s\n", extra);
256d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        else
257659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard            __xmlRaiseError(NULL, NULL, NULL,
258d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            NULL, NULL, XML_FROM_XPATH,
259d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
260d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            NULL, NULL, NULL, 0, 0,
261d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                            "Memory allocation failed\n");
262d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    }
263d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard}
264d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
265d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/**
2668de5c0bd79cceeca3d55d6dbf8f0248b7239e050Daniel Veillard * xmlXPathPErrMemory:
267d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @ctxt:  an XPath parser context
268d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @extra:  extra informations
269d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *
270d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * Handle a redefinition of attribute error
271d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard */
272d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardstatic void
273d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel VeillardxmlXPathPErrMemory(xmlXPathParserContextPtr ctxt, const char *extra)
274d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard{
275d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->error = XPATH_MEMORY_ERROR;
276d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    if (ctxt == NULL)
277d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	xmlXPathErrMemory(NULL, extra);
278d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    else
279d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	xmlXPathErrMemory(ctxt->context, extra);
280d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard}
281d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
282d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/**
283d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * xmlXPathErr:
284d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @ctxt:  a XPath parser context
285d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @error:  the error code
286d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *
287cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack * Handle an XPath error
288d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard */
289d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardvoid
290d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel VeillardxmlXPathErr(xmlXPathParserContextPtr ctxt, int error)
291d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard{
292cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack    if ((error < 0) || (error > MAXERRNO))
293cd65bc9a49b406899c78e9e8f6757acca54fc04eWilliam M. Brack	error = MAXERRNO;
294f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard    if (ctxt == NULL) {
295659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard	__xmlRaiseError(NULL, NULL, NULL,
296d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			NULL, NULL, XML_FROM_XPATH,
297d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
298d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			XML_ERR_ERROR, NULL, 0,
299d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			NULL, NULL, NULL, 0, 0,
300d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			xmlXPathErrorMessages[error]);
301d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	return;
302d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    }
303f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard    ctxt->error = error;
304f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard    if (ctxt->context == NULL) {
305f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard	__xmlRaiseError(NULL, NULL, NULL,
306f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			NULL, NULL, XML_FROM_XPATH,
307f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
308f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			XML_ERR_ERROR, NULL, 0,
309f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			(const char *) ctxt->base, NULL, NULL,
310f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			ctxt->cur - ctxt->base, 0,
311f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard			xmlXPathErrorMessages[error]);
312f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard	return;
313f88d8cf9f1c9538dba187290ad5add003dc22bc7Daniel Veillard    }
314d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.domain = XML_FROM_XPATH;
315d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.code = error + XML_XPATH_EXPRESSION_OK -
316d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard                           XPATH_EXPRESSION_OK;
317fcf719ce0a94f0d438f69b73cd1ca31a7000da81Daniel Veillard    ctxt->context->lastError.level = XML_ERR_ERROR;
318d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
319d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
320d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    ctxt->context->lastError.node = ctxt->context->debugNode;
321d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    if (ctxt->context->error != NULL) {
322d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	ctxt->context->error(ctxt->context->userData,
323d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	                     &ctxt->context->lastError);
324d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    } else {
325659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard	__xmlRaiseError(NULL, NULL, NULL,
326d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			NULL, ctxt->context->debugNode, XML_FROM_XPATH,
327d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			error + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
328d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			XML_ERR_ERROR, NULL, 0,
329d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			(const char *) ctxt->base, NULL, NULL,
330d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			ctxt->cur - ctxt->base, 0,
331d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard			xmlXPathErrorMessages[error]);
332d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    }
333d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
334d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard}
335d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
336d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/**
337d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * xmlXPatherror:
338d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @ctxt:  the XPath Parser context
339d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @file:  the file name
340d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @line:  the line number
341d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * @no:  the error number
342d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard *
343d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard * Formats an error message.
344d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard */
345d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillardvoid
346d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel VeillardxmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED,
347d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard              int line ATTRIBUTE_UNUSED, int no) {
348d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    xmlXPathErr(ctxt, no);
349d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard}
350d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
351d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard
352d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard/************************************************************************
3539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
3549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Parser Types					*
3559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
3569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
3579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/*
3599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Types are private:
3609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
3619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
3639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_END=0,
3649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_AND,
3659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_OR,
3669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_EQUAL,
3679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_CMP,
3689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_PLUS,
3699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_MULT,
3709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_UNION,
3719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_ROOT,
3729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_NODE,
3739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_RESET,
3749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_COLLECT,
3759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_VALUE,
3769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_VARIABLE,
3779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_FUNCTION,
3789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_ARG,
3799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_PREDICATE,
380d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    XPATH_OP_FILTER,
3819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    XPATH_OP_SORT
3829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#ifdef LIBXML_XPTR_ENABLED
3839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ,XPATH_OP_RANGETO
3849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif
3859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathOp;
3869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
3879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
3889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ANCESTOR = 1,
3899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ANCESTOR_OR_SELF,
3909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_ATTRIBUTE,
3919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_CHILD,
3929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_DESCENDANT,
3939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_DESCENDANT_OR_SELF,
3949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_FOLLOWING,
3959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_FOLLOWING_SIBLING,
3969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_NAMESPACE,
3979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PARENT,
3989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PRECEDING,
3999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_PRECEDING_SIBLING,
4009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    AXIS_SELF
4019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathAxisVal;
4029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
4049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NONE = 0,
4059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_TYPE = 1,
4069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_PI = 2,
4079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_ALL = 3,
4089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NS = 4,
4099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TEST_NAME = 5
4109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathTestVal;
4119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef enum {
4139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_NODE = 0,
4149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_COMMENT = XML_COMMENT_NODE,
4159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_TEXT = XML_TEXT_NODE,
4169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NODE_TYPE_PI = XML_PI_NODE
4179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard} xmlXPathTypeVal;
4189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef struct _xmlXPathStepOp xmlXPathStepOp;
4219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardtypedef xmlXPathStepOp *xmlXPathStepOpPtr;
4229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardstruct _xmlXPathStepOp {
423081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    xmlXPathOp op;		/* The identifier of the operation */
424081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int ch1;			/* First child */
425081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int ch2;			/* Second child */
4269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value;
4279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value2;
4289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int value3;
4299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    void *value4;
4309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    void *value5;
431e39a93d0d3df9907cf3538cd3f1fbbe4106e893dDaniel Veillard    void *cache;
43242596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard    void *cacheURI;
4339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard};
4349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardstruct _xmlXPathCompExpr {
436081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int nbStep;			/* Number of steps in this expression */
437081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int maxStep;		/* Maximum number of steps allocated */
438081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    xmlXPathStepOp *steps;	/* ops for computation of this expression */
439081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    int last;			/* index of last step in expression */
440081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    xmlChar *expr;		/* the expression being computed */
4414773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    xmlDictPtr dict;		/* the dictionnary to use if any */
442f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
443f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int nb;
444f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlChar *string;
445f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
44656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
44756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlPatternPtr stream;
44856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
4499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard};
4509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
4529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
4539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 			Parser Type functions 				*
4549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 									*
4559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
4569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
4589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathNewCompExpr:
4599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
4609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Create a new Xpath component
4619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
4629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error
4639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
46456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathCompExprPtr
4659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathNewCompExpr(void) {
4669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprPtr cur;
4679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
4699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (cur == NULL) {
470d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "allocating component\n");
4719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
4729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
4739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(cur, 0, sizeof(xmlXPathCompExpr));
4749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->maxStep = 10;
4759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->nbStep = 0;
4769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
4779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                                   sizeof(xmlXPathStepOp));
4789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (cur->steps == NULL) {
479d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "allocating steps\n");
4809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(cur);
4819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
4829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
4839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
4849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    cur->last = -1;
485f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    cur->nb = 0;
487f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
4889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(cur);
4899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
4909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
4929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathFreeCompExpr:
4939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  an XPATH comp
4949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
4959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Free up the memory allocated by @comp
4969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
4979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardvoid
498f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
5009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathStepOpPtr op;
5019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
5029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
5039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp == NULL)
504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return;
5054773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if (comp->dict == NULL) {
5064773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	for (i = 0; i < comp->nbStep; i++) {
5074773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    op = &comp->steps[i];
5084773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    if (op->value4 != NULL) {
5094773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		if (op->op == XPATH_OP_VALUE)
5104773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		    xmlXPathFreeObject(op->value4);
5114773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		else
5124773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		    xmlFree(op->value4);
5134773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    }
5144773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    if (op->value5 != NULL)
5154773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		xmlFree(op->value5);
5164773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	}
5174773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    } else {
5184773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	for (i = 0; i < comp->nbStep; i++) {
5194773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    op = &comp->steps[i];
5204773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    if (op->value4 != NULL) {
5214773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		if (op->op == XPATH_OP_VALUE)
5224773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard		    xmlXPathFreeObject(op->value4);
5234773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    }
5244773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	}
5254773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        xmlDictFree(comp->dict);
5269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
5279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp->steps != NULL) {
528f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlFree(comp->steps);
5299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
530f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (comp->string != NULL) {
532f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlFree(comp->string);
533f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
534f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
53556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
53656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp->stream != NULL) {
53756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        xmlFreePatternList(comp->stream);
53856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
53956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
540118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    if (comp->expr != NULL) {
541118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard        xmlFree(comp->expr);
542118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    }
543f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
5449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlFree(comp);
5459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
5469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
5479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
5489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompExprAdd:
5499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the compiled expression
5509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ch1: first child index
5519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ch2: second child index
5529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @op:  an op
5539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value:  the first int value
5549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value2:  the second int value
5559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value3:  the third int value
5569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value4:  the first string value
5579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @value5:  the second string value
5589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
559081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Add a step to an XPath Compiled Expression
5609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
5619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns -1 in case of failure, the index otherwise
5629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
56356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
5649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
5659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard   xmlXPathOp op, int value,
5669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard   int value2, int value3, void *value4, void *value5) {
5679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp->nbStep >= comp->maxStep) {
5689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathStepOp *real;
5699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
5709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	comp->maxStep *= 2;
5719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
5729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		                      comp->maxStep * sizeof(xmlXPathStepOp));
5739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (real == NULL) {
5749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    comp->maxStep /= 2;
575d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "adding step\n");
5769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    return(-1);
5779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
5789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	comp->steps = real;
5799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
5809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->last = comp->nbStep;
5819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].ch1 = ch1;
5829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].ch2 = ch2;
5839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].op = op;
5849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value = value;
5859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value2 = value2;
5869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp->steps[comp->nbStep].value3 = value3;
5874773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if ((comp->dict != NULL) &&
5884773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) ||
5894773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	 (op == XPATH_OP_COLLECT))) {
5904773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        if (value4 != NULL) {
591b337795500cbe3fc47ac2b81f3d955126c6fbfdeDaniel Veillard	    comp->steps[comp->nbStep].value4 = (xmlChar *)
592c07ed5e6a14fb801cfd6bbb2a582caf726e5324eWilliam M. Brack	        (void *)xmlDictLookup(comp->dict, value4, -1);
5934773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    xmlFree(value4);
5944773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	} else
5954773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    comp->steps[comp->nbStep].value4 = NULL;
5964773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        if (value5 != NULL) {
597b337795500cbe3fc47ac2b81f3d955126c6fbfdeDaniel Veillard	    comp->steps[comp->nbStep].value5 = (xmlChar *)
598c07ed5e6a14fb801cfd6bbb2a582caf726e5324eWilliam M. Brack	        (void *)xmlDictLookup(comp->dict, value5, -1);
5994773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    xmlFree(value5);
6004773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	} else
6014773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	    comp->steps[comp->nbStep].value5 = NULL;
6024773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    } else {
6034773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	comp->steps[comp->nbStep].value4 = value4;
6044773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	comp->steps[comp->nbStep].value5 = value5;
6054773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    }
606e39a93d0d3df9907cf3538cd3f1fbbe4106e893dDaniel Veillard    comp->steps[comp->nbStep].cache = NULL;
6079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(comp->nbStep++);
6089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
6099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
610f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
611f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompSwap:
612f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @comp:  the compiled expression
613f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op: operation index
614f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
615f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Swaps 2 operations in the compiled expression
616f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
617f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic void
618f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompSwap(xmlXPathStepOpPtr op) {
619f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int tmp;
620f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
621bc6f759ac9b41773e3643ad288b5214732051c98Daniel Veillard#ifndef LIBXML_THREAD_ENABLED
6228146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    /*
6238146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * Since this manipulates possibly shared variables, this is
624081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * disabled if one detects that the library is used in a multithreaded
6258146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     * application
6268146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard     */
6278146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    if (xmlXPathDisableOptimizer)
6288146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard	return;
6298146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
6308146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard
631f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    tmp = op->ch1;
632f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    op->ch1 = op->ch2;
633f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    op->ch2 = tmp;
634f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
635f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
636d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5)	\
637d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathCompExprAdd(ctxt->comp, (op1), (op2),			\
638d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	                (op), (val), (val2), (val3), (val4), (val5))
6399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5)			\
6409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1,		\
6419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                (op), (val), (val2), (val3), (val4), (val5))
6429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_LEAVE_EXPR(op, val, val2) 					\
6449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
6459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_UNARY_EXPR(op, ch, val, val2) 				\
6479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompExprAdd(ctxt->comp, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
6489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) 			\
650081719182de3d15e6a438f32fdc3d1ca240a08e8William M. BrackxmlXPathCompExprAdd(ctxt->comp, (ch1), (ch2), (op),			\
651081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack			(val), (val2), 0 ,NULL ,NULL)
6529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
6539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
6543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
6553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 		Debugging related functions				*
6563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
6573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
6583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define STRANGE 							\
6603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext,				\
6613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    "Internal error at %s:%d\n",				\
6623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            __FILE__, __LINE__);
6633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_DEBUG_ENABLED
66556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
66656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
6673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
6683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
6693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
6713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
6723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
6733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
6743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
6753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "Node is NULL !\n");
6763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
6773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur->type == XML_DOCUMENT_NODE) ||
6813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     (cur->type == XML_HTML_DOCUMENT_NODE)) {
6823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
6833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, " /\n");
6843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->type == XML_ATTRIBUTE_NODE)
6853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
6863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
6873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlDebugDumpOneNode(output, cur, depth);
6883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
69056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) {
691f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    xmlNodePtr tmp;
692f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    int i;
693f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    char shift[100];
694f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
695f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
696f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
697f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
698f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    if (cur == NULL) {
699f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, shift);
700f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, "Node is NULL !\n");
701f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	return;
702f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
703f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
704f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
705f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    while (cur != NULL) {
706f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	tmp = cur;
707f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	cur = cur->next;
708f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	xmlDebugDumpOneNode(output, tmp, depth);
709f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
710f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard}
7113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
71356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
7143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
7153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
7163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
7183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
7193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
7203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
7223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
7233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "NodeSet is NULL !\n");
7243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
7253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
728911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (cur != NULL) {
729911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
730911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < cur->nodeNr;i++) {
731911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    fprintf(output, shift);
732911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    fprintf(output, "%d", i + 1);
733911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
734911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
7353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
7373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
73956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) {
740f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    int i;
741f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    char shift[100];
742f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
743f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
744f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
745f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
746f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
747f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) {
748f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, shift);
749f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	fprintf(output, "Value Tree is NULL !\n");
750f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	return;
751f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
752f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    }
753f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard
754f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    fprintf(output, shift);
755f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    fprintf(output, "%d", i + 1);
756f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard    xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);
757f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard}
7583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(LIBXML_XPTR_ENABLED)
75956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
76056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
7613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
7623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
7633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
7653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
7663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
7673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
7693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
7703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, "LocationSet is NULL !\n");
7713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
7723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->locNr;i++) {
7763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, shift);
7773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "%d : ", i + 1);
7783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1);
7793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
781017b108fcf16dbce05ca7ebd75763f3d888abb5fDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
7823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
783afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
784afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathDebugDumpObject:
785afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @output:  the FILE * to dump the output
786afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @cur:  the object to inspect
787afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @depth:  indentation level
788afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
789afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Dump the content of the object for debugging purposes
790afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
791afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardvoid
792afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
7933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
7943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    char shift[100];
7953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
796a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (output == NULL) return;
797a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
7983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;((i < depth) && (i < 25));i++)
7993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        shift[2 * i] = shift[2 * i + 1] = ' ';
8003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    shift[2 * i] = shift[2 * i + 1] = 0;
8013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fprintf(output, shift);
8033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
8053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "Object is empty (NULL)\n");
8063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
8073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(cur->type) {
8093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_UNDEFINED:
8103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is uninitialized\n");
8113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
8133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Node Set :\n");
8143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
8153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_XSLT_TREE:
8173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is an XSLT value tree :\n");
818f7cd48176c8333c0d487b7b4a12ff24f2db81aceDaniel Veillard	    xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth);
8193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
8213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Boolean : ");
8223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (cur->boolval) fprintf(output, "true\n");
8233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else fprintf(output, "false\n");
8243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
826cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	    switch (xmlXPathIsInf(cur->floatval)) {
827357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    case 1:
8285fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard		fprintf(output, "Object is a number : Infinity\n");
829357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		break;
830357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    case -1:
831357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		fprintf(output, "Object is a number : -Infinity\n");
832357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		break;
833357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    default:
834cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard		if (xmlXPathIsNaN(cur->floatval)) {
835357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		    fprintf(output, "Object is a number : NaN\n");
836d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		} else if (cur->floatval == 0 && xmlXPathGetSign(cur->floatval) != 0) {
837d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    fprintf(output, "Object is a number : 0\n");
838357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		} else {
839357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		    fprintf(output, "Object is a number : %0g\n", cur->floatval);
840357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard		}
841357c960e4035ee2fb40d0072bb7bde4533be76f8Daniel Veillard	    }
8423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
8443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a string : ");
8453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlDebugDumpString(output, cur->stringval);
8463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "\n");
8473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
8493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a point : index %d in node", cur->index);
8503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
8513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "\n");
8523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
8543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((cur->user2 == NULL) ||
8553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		((cur->user2 == cur->user) && (cur->index == cur->index2))) {
8563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "Object is a collapsed range :\n");
8573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
8583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index >= 0)
8593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index);
8603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
8613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
8623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
8633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else  {
8643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "Object is a range :\n");
8653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
8663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "From ");
8673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index >= 0)
8683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index);
8693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
8703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
8713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
8723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, shift);
8733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "To ");
8743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (cur->index2 >= 0)
8753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    fprintf(output, "index %d in ", cur->index2);
8763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "node\n");
8773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2,
8783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			              depth + 1);
8793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		fprintf(output, "\n");
8803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
8813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
8833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(LIBXML_XPTR_ENABLED)
8843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is a Location Set:\n");
8853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathDebugDumpLocationSet(output,
8863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    (xmlLocationSetPtr) cur->user, depth);
8873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
8883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_USERS:
8903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, "Object is user defined\n");
8913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
8923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
8949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
89556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
89656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
8979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	                     xmlXPathStepOpPtr op, int depth) {
8989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
8999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    char shift[100];
9009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
9029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
9039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
9049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, shift);
9069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op == NULL) {
9079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	fprintf(output, "Step is NULL\n");
9089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
9099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
9109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    switch (op->op) {
9119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_END:
9129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "END"); break;
9139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_AND:
9149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "AND"); break;
9159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_OR:
9169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "OR"); break;
9179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_EQUAL:
9189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value)
9199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "EQUAL =");
9209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
9219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "EQUAL !=");
9229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
9239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_CMP:
9249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value)
9259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "CMP <");
9269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
9279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "CMP >");
9289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (!op->value2)
9299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "=");
9309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
9319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_PLUS:
9329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value == 0)
9339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS -");
9349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 1)
9359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS +");
9369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 2)
9379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS unary -");
9389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 3)
9399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "PLUS unary - -");
9409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
9419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_MULT:
9429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     if (op->value == 0)
9439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT *");
9449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else if (op->value == 1)
9459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT div");
9469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     else
9479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		 fprintf(output, "MULT mod");
9489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     break;
9499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_UNION:
9509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "UNION"); break;
9519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_ROOT:
9529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "ROOT"); break;
9539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_NODE:
9549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "NODE"); break;
9559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_RESET:
9569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "RESET"); break;
9579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_SORT:
9589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	     fprintf(output, "SORT"); break;
9599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_COLLECT: {
96078637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathAxisVal axis = (xmlXPathAxisVal)op->value;
96178637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathTestVal test = (xmlXPathTestVal)op->value2;
96278637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	    xmlXPathTypeVal type = (xmlXPathTypeVal)op->value3;
9639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value4;
9649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value5;
9659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "COLLECT ");
9679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (axis) {
9689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ANCESTOR:
9699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'ancestors' "); break;
9709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ANCESTOR_OR_SELF:
9719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'ancestors-or-self' "); break;
9729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_ATTRIBUTE:
9739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'attributes' "); break;
9749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_CHILD:
9759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'child' "); break;
9769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_DESCENDANT:
9779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'descendant' "); break;
9789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_DESCENDANT_OR_SELF:
9799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'descendant-or-self' "); break;
9809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_FOLLOWING:
9819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'following' "); break;
9829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_FOLLOWING_SIBLING:
9839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'following-siblings' "); break;
9849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_NAMESPACE:
9859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'namespace' "); break;
9869e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PARENT:
9879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'parent' "); break;
9889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PRECEDING:
9899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'preceding' "); break;
9909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_PRECEDING_SIBLING:
9919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'preceding-sibling' "); break;
9929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		case AXIS_SELF:
9939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, " 'self' "); break;
9949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
9959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (test) {
9969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NONE:
9979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'none' "); break;
9989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_TYPE:
9999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'type' "); break;
10009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_PI:
10019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'PI' "); break;
10029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_ALL:
10039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'all' "); break;
10049e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NS:
10059e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'namespace' "); break;
10069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TEST_NAME:
10079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'name' "); break;
10089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
10099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    switch (type) {
10109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_NODE:
10119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'node' "); break;
10129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_COMMENT:
10139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'comment' "); break;
10149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_TEXT:
10159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'text' "); break;
10169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard                case NODE_TYPE_PI:
10179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    fprintf(output, "'PI' "); break;
10189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    }
10199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
10209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "%s:", prefix);
10219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (name != NULL)
1022580ced8ee28ecd99374da9383897678e4ba6c358Daniel Veillard		fprintf(output, "%s", (const char *) name);
10239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
10249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        }
10269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_VALUE: {
10279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4;
10289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    fprintf(output, "ELEM ");
10309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathDebugDumpObject(output, object, 0);
10319e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    goto finish;
10329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
10339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_VARIABLE: {
10349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value5;
10359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value4;
10369e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
10389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "VARIABLE %s:%s", prefix, name);
10399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    else
10409e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "VARIABLE %s", name);
10419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
10429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
10439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	case XPATH_OP_FUNCTION: {
10449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    int nbargs = op->value;
10459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *prefix = op->value5;
10469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    const xmlChar *name = op->value4;
10479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (prefix != NULL)
10499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "FUNCTION %s:%s(%d args)",
10509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			prefix, name, nbargs);
10519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    else
10529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		fprintf(output, "FUNCTION %s(%d args)", name, nbargs);
10539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    break;
10549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
10559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_ARG: fprintf(output, "ARG"); break;
10569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
1057d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
1058fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
1059fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard        case XPATH_OP_RANGETO: fprintf(output, "RANGETO"); break;
1060fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
10619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	default:
10629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        fprintf(output, "UNKNOWN %d\n", op->op); return;
10639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
10649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, "\n");
10659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillardfinish:
10669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op->ch1 >= 0)
10679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1);
10689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (op->ch2 >= 0)
10699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1);
10709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
107156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard
10725e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
10735e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathDebugDumpCompExpr:
10745e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @output:  the FILE * for the output
10755e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @comp:  the precompiled XPath expression
10765e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @depth:  the indentation level.
10775e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
10785e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Dumps the tree of the compiled XPath expression.
10795e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
108056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardvoid
108156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
108256a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	                  int depth) {
10839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int i;
10849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    char shift[100];
10859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1086a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((output == NULL) || (comp == NULL)) return;
1087a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
10889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    for (i = 0;((i < depth) && (i < 25));i++)
10899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        shift[2 * i] = shift[2 * i + 1] = ' ';
10909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    shift[2 * i] = shift[2 * i + 1] = 0;
10919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, shift);
10939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (comp == NULL) {
10959e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	fprintf(output, "Compiled Expression is NULL\n");
10969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
10979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
10989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    fprintf(output, "Compiled Expression : %d elements\n",
10999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    comp->nbStep);
11009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    i = comp->last;
11019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
11029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
1103017b108fcf16dbce05ca7ebd75763f3d888abb5fDaniel Veillard#endif /* LIBXML_DEBUG_ENABLED */
11043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
11063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
11073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 		Parser stacks related functions and macros		*
11083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
11093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
11103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11115e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
11125e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * valuePop:
11135e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @ctxt: an XPath evaluation context
11145e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
11155e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Pops the top XPath object from the value stack
11165e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
11175e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Returns the XPath object just removed
11185e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
11191c732d2e10935529b717864b6fa4296f80edace1Daniel Veillardextern xmlXPathObjectPtr
11201c732d2e10935529b717864b6fa4296f80edace1Daniel VeillardvaluePop(xmlXPathParserContextPtr ctxt)
11211c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard{
11221c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    xmlXPathObjectPtr ret;
11231c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard
1124a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->valueNr <= 0))
11251c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        return (0);
11261c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->valueNr--;
11271c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    if (ctxt->valueNr > 0)
11281c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
11291c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    else
11301c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        ctxt->value = NULL;
11311c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ret = ctxt->valueTab[ctxt->valueNr];
11321c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->valueTab[ctxt->valueNr] = 0;
11331c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    return (ret);
11341c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard}
11355e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard/**
11365e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * valuePush:
11375e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @ctxt:  an XPath evaluation context
11385e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * @value:  the XPath object
11395e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard *
11405e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * Pushes a new XPath object on top of the value stack
1141cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *
1142cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * returns the number of items on the value stack
11435e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard */
11441c732d2e10935529b717864b6fa4296f80edace1Daniel Veillardextern int
11451c732d2e10935529b717864b6fa4296f80edace1Daniel VeillardvaluePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
11461c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard{
1147a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (value == NULL)) return(-1);
11481c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    if (ctxt->valueNr >= ctxt->valueMax) {
1149a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard        xmlXPathObjectPtr *tmp;
1150a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard
1151a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard        tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
1152a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard                                             2 * ctxt->valueMax *
11531c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard                                             sizeof(ctxt->valueTab[0]));
1154a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard        if (tmp == NULL) {
11551c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
11561c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard            return (0);
11571c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard        }
1158a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard        ctxt->valueMax *= 2;
1159a918b5b08ac20d4e7c765bdce653969ebad6c315Daniel Veillard	ctxt->valueTab = tmp;
11601c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    }
11611c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->valueTab[ctxt->valueNr] = value;
11621c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    ctxt->value = value;
11631c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard    return (ctxt->valueNr++);
11641c732d2e10935529b717864b6fa4296f80edace1Daniel Veillard}
11653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1166f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1167f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopBoolean:
1168f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1169f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1170f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a boolean from the stack, handling conversion if needed.
1171f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1172f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1173f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the boolean
1174f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1175f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
1176f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
1177f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1178f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int ret;
1179f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1180f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1181f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
1182f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1183f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
1184f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1185081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    if (obj->type != XPATH_BOOLEAN)
1186081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	ret = xmlXPathCastToBoolean(obj);
1187081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    else
1188081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack        ret = obj->boolval;
1189f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1190f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1191f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1192f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1193f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1194f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopNumber:
1195f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1196f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1197f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a number from the stack, handling conversion if needed.
1198f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1199f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1200f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the number
1201f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1202f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerdouble
1203f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
1204f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1205f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    double ret;
1206f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1207f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1208f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
1209f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1210f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
1211f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1212081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    if (obj->type != XPATH_NUMBER)
1213081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	ret = xmlXPathCastToNumber(obj);
1214081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    else
1215081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack        ret = obj->floatval;
1216f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1217f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1218f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1219f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1220f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1221f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopString:
1222f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1223f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1224f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a string from the stack, handling conversion if needed.
1225f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1226f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1227f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the string
1228f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1229f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlChar *
1230f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopString (xmlXPathParserContextPtr ctxt) {
1231f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1232f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlChar * ret;
1233f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1234f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1235f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj == NULL) {
1236f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1237f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1238f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1239081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    ret = xmlXPathCastToString(obj);	/* this does required strdup */
1240f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    /* TODO: needs refactoring somewhere else */
1241f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (obj->stringval == ret)
1242f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	obj->stringval = NULL;
1243f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1244f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1245f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1246f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1247f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1248f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopNodeSet:
1249f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1250f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1251f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Pops a node-set from the stack, handling conversion if needed.
1252f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1253f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1254f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the node-set
1255f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1256f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
1257f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
1258f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1259f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
1260f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1261f2a36f98e16efa8a89d9bed359d59be10e5d33cdDaniel Veillard    if (ctxt == NULL) return(NULL);
1262f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value == NULL) {
1263f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1264f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1265f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1266f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (!xmlXPathStackIsNodeSet(ctxt)) {
1267f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetTypeError(ctxt);
1268f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1269f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1270f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1271f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = obj->nodesetval;
1272e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#if 0
12739deb242b558cbcff45165866e0634a1962404885Daniel Veillard    /* to fix memory leak of not clearing obj->user */
12749deb242b558cbcff45165866e0634a1962404885Daniel Veillard    if (obj->boolval && obj->user != NULL)
12759deb242b558cbcff45165866e0634a1962404885Daniel Veillard        xmlFreeNodeList((xmlNodePtr) obj->user);
1276e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#endif
1277f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeNodeSetList(obj);
1278f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1279f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1280f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1281f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1282f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathPopExternal:
1283f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @ctxt:  an XPath parser context
1284f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1285cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Pops an external object from the stack, handling conversion if needed.
1286f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Check error with #xmlXPathCheckError.
1287f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1288f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the object
1289f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1290f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyervoid *
1291f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
1292f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr obj;
1293f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    void * ret;
1294f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1295a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->value == NULL)) {
1296f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
1297f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1298f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1299f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ctxt->value->type != XPATH_USERS) {
1300f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathSetTypeError(ctxt);
1301f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
1302f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1303f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    obj = valuePop(ctxt);
1304f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = obj->user;
1305f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathFreeObject(obj);
1306f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
1307f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1308f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
13093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
13103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Macros for accessing the content. Those should be used only by the parser,
13113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and not exported.
13123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Dirty macros, i.e. one need to make assumption on the context to use them
13143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
13153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CUR_PTR return the current pointer to the xmlChar to be parsed.
13163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CUR     returns the current xmlChar value, i.e. a 8 bit value
13173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           in ISO-Latin or UTF-8.
13183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           This should be used internally by the parser
13193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           only to compare to ASCII values otherwise it would break when
13203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           running with UTF-8 encoding.
13213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
13223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           to compare on ASCII based substring.
13233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
13243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           strings within the parser.
13253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   CURRENT Returns the current char value, with the full decoding of
13263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           UTF-8 if we are using this mode. It returns an int.
13273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   NEXT    Skip to the next character, this does the proper decoding
13283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
13293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           It returns the pointer to the current xmlChar.
13303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
13313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CUR (*ctxt->cur)
13333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SKIP(val) ctxt->cur += (val)
13343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define NXT(val) ctxt->cur[(val)]
13353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CUR_PTR ctxt->cur
133661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
133761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
133861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define COPY_BUF(l,b,i,v)                                              \
133961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (l == 1) b[i++] = (xmlChar) v;                                  \
134061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    else i += xmlCopyChar(l,&b[i],v)
134161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
134261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard#define NEXTL(l)  ctxt->cur += l
13433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define SKIP_BLANKS 							\
134576e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*(ctxt->cur))) NEXT
13463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CURRENT (*ctxt->cur)
13483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)
13493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1350e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1351e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#ifndef DBL_DIG
1352e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define DBL_DIG 16
1353e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#endif
1354e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#ifndef DBL_EPSILON
1355e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define DBL_EPSILON 1E-9
1356e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#endif
1357e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1358e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define UPPER_DOUBLE 1E9
1359e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define LOWER_DOUBLE 1E-5
1360e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1361e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define INTEGER_DIGITS DBL_DIG
1362e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define FRACTION_DIGITS (DBL_DIG + 1)
1363e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese#define EXPONENT_DIGITS (3 + 2)
1364e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
1365e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese/**
1366e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * xmlXPathFormatNumber:
1367e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @number:     number to format
1368e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @buffer:     output buffer
1369e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * @buffersize: size of output buffer
1370e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese *
1371e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese * Convert the number into a string representation.
1372e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese */
1373e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reesestatic void
1374e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn ReesexmlXPathFormatNumber(double number, char buffer[], int buffersize)
1375e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese{
1376cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    switch (xmlXPathIsInf(number)) {
1377e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    case 1:
13785fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (buffersize > (int)sizeof("Infinity"))
137949cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "Infinity");
1380e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1381e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    case -1:
1382e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	if (buffersize > (int)sizeof("-Infinity"))
138349cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "-Infinity");
1384e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1385e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    default:
1386cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(number)) {
1387e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    if (buffersize > (int)sizeof("NaN"))
138849cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin		snprintf(buffer, buffersize, "NaN");
1389d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	} else if (number == 0 && xmlXPathGetSign(number) != 0) {
139049cc97565fbe2928388a1e437c44429097a504aeAleksey Sanin	    snprintf(buffer, buffersize, "0");
139128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	} else if (number == ((int) number)) {
139228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    char work[30];
139328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    char *ptr, *cur;
139428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    int res, value = (int) number;
139528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard
139628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard            ptr = &buffer[0];
139728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (value < 0) {
139828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr++ = '-';
139928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		value = -value;
140028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
140128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (value == 0) {
140228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr++ = '0';
140328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    } else {
140428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		cur = &work[0];
140528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		while (value != 0) {
140628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    res = value % 10;
140728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    value = value / 10;
140828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    *cur++ = '0' + res;
140928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		}
141028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		cur--;
141128cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		while ((cur >= &work[0]) && (ptr - buffer < buffersize)) {
141228cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		    *ptr++ = *cur--;
141328cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		}
141428cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
141528cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    if (ptr - buffer < buffersize) {
141628cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr = 0;
141728cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    } else if (buffersize > 0) {
141828cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		ptr--;
141928cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard		*ptr = 0;
142028cac6b5a9558001844e02f00bfddda211b466d2Daniel Veillard	    }
1421e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	} else {
142270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* 3 is sign, decimal point, and terminating zero */
142370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
142470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    int integer_place, fraction_place;
142570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char *ptr;
142670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    char *after_fraction;
142770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    double absolute_value;
142870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    int size;
142970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
143070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    absolute_value = fabs(number);
143170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
143270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /*
143370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * First choose format - scientific or regular floating point.
143470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * In either case, result is in work, and after_fraction points
143570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	     * just past the fractional part.
143670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    */
143770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if ( ((absolute_value > UPPER_DOUBLE) ||
143870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		  (absolute_value < LOWER_DOUBLE)) &&
143970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		 (absolute_value != 0.0) ) {
144070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		/* Use scientific notation */
144170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
144270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		fraction_place = DBL_DIG - 1;
144370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		snprintf(work, sizeof(work),"%*.*e",
144470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese			 integer_place, fraction_place, number);
144570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		after_fraction = strchr(work + DBL_DIG, 'e');
1446e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    }
144770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    else {
144870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		/* Use regular notation */
144956f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		if (absolute_value > 0.0)
145056f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		    integer_place = 1 + (int)log10(absolute_value);
145156f0646e734ffbdd6945d86cc28b69b6569a82fcDaniel Veillard		else
1452a3067d19ec3a96fd6e7997753e27a5422a2856f7Daniel Veillard		    integer_place = 0;
145370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		fraction_place = (integer_place > 0)
145470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		    ? DBL_DIG - integer_place
145570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		    : DBL_DIG;
145670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		size = snprintf(work, sizeof(work), "%0.*f",
145770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese				fraction_place, number);
145870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		after_fraction = work + size;
1459e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	    }
1460e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
146170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* Remove fractional trailing zeroes */
146270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    ptr = after_fraction;
146370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    while (*(--ptr) == '0')
146470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		;
146570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if (*ptr != '.')
146670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	        ptr++;
14675dd3c9622ab6a8e75870bc5351499155e7963abcDaniel Veillard	    while ((*ptr++ = *after_fraction++) != 0);
146870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
146970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    /* Finally copy result back to caller */
147070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    size = strlen(work) + 1;
147170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    if (size > buffersize) {
147270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		work[buffersize - 1] = 0;
147370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese		size = buffersize;
147470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	    }
14755dd3c9622ab6a8e75870bc5351499155e7963abcDaniel Veillard	    memmove(buffer, work, size);
1476e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	}
1477e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese	break;
1478e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    }
1479e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese}
1480e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese
14813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
14833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
14843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle NodeSets			*
14853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
14863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
14873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
14883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1489e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * xmlXPathOrderDocElems:
1490e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * @doc:  an input document
1491e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *
1492e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * Call this routine to speed up XPath computation on static documents.
1493e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * This stamps all the element nodes with the document order
1494e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard * Like for line information, the order is kept in the element->content
1495081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * field, the value stored is actually - the node number (starting at -1)
1496081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * to be able to differentiate from line numbers.
1497e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *
1498081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the number of elements found in the document or -1 in case
1499e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard *    of error.
1500e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard */
1501e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillardlong
1502e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel VeillardxmlXPathOrderDocElems(xmlDocPtr doc) {
1503e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    long count = 0;
1504e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    xmlNodePtr cur;
1505e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1506e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    if (doc == NULL)
1507e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	return(-1);
1508e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    cur = doc->children;
1509e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    while (cur != NULL) {
1510e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	if (cur->type == XML_ELEMENT_NODE) {
1511e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur->content = (void *) (-(++count));
1512e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur->children != NULL) {
1513e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = cur->children;
1514e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		continue;
1515e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1516e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	}
1517e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	if (cur->next != NULL) {
1518e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur = cur->next;
1519e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    continue;
1520e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	}
1521e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	do {
1522e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    cur = cur->parent;
1523e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur == NULL)
1524e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1525e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur == (xmlNodePtr) doc) {
1526e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = NULL;
1527e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1528e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1529e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    if (cur->next != NULL) {
1530e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		cur = cur->next;
1531e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard		break;
1532e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	    }
1533e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	} while (cur != NULL);
1534e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    }
1535e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard    return(count);
1536e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard}
1537e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1538e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard/**
15393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCmpNodes:
15403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node1:  the first node
15413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node2:  the second node
15423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
15433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Compare two nodes w.r.t document order
15443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
15453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns -2 in case of error 1 if first point < second point, 0 if
1546081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack *         it's the same node, -1 otherwise
15473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
15483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
15493473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
15503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int depth1, depth2;
1551edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    int attr1 = 0, attr2 = 0;
1552e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack    xmlNodePtr attrNode1 = NULL, attrNode2 = NULL;
15533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodePtr cur, root;
15543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((node1 == NULL) || (node2 == NULL))
15563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-2);
15573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
15583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * a couple of optimizations which will avoid computations in most cases
15593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1560edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node1->type == XML_ATTRIBUTE_NODE) {
1561edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	attr1 = 1;
1562e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	attrNode1 = node1;
1563edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	node1 = node1->parent;
1564edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1565edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node2->type == XML_ATTRIBUTE_NODE) {
1566edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	attr2 = 1;
1567e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	attrNode2 = node2;
1568edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	node2 = node2->parent;
1569edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1570edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    if (node1 == node2) {
1571e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	if (attr1 == attr2) {
1572e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	    /* not required, but we keep attributes in order */
1573e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	    if (attr1 != 0) {
1574e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	        cur = attrNode2->prev;
1575e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		while (cur != NULL) {
1576e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		    if (cur == attrNode1)
1577e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		        return (1);
1578e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		    cur = cur->prev;
1579e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		}
1580e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack		return (-1);
1581e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	    }
1582edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	    return(0);
1583e8d1bd9daa881b01259e83eab60df8cbb56785c6William M. Brack	}
1584edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	if (attr2 == 1)
1585edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	    return(1);
1586edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard	return(-1);
1587edfd588e95d7c4690b5e85880521a32c20ed4fdeDaniel Veillard    }
1588b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard    if ((node1->type == XML_NAMESPACE_DECL) ||
1589b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard        (node2->type == XML_NAMESPACE_DECL))
1590b33c201978ed1c434877cdc6e2000b7012cc26f9Daniel Veillard	return(1);
15913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->prev)
15923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
15933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->next)
15943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
15953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
1597e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard     * Speedup using document order if availble.
15987216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard     */
15997216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    if ((node1->type == XML_ELEMENT_NODE) &&
16007216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	(node2->type == XML_ELEMENT_NODE) &&
1601e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(0 > (long) node1->content) &&
1602e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(0 > (long) node2->content) &&
1603e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	(node1->doc == node2->doc)) {
1604e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	long l1, l2;
1605e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
1606e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	l1 = -((long) node1->content);
1607e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard	l2 = -((long) node2->content);
16087216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	if (l1 < l2)
16097216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	    return(1);
16107216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	if (l1 > l2)
16117216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard	    return(-1);
16127216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    }
1613e4fa293265c935365717dc9accf6c6ec23d5f22fDaniel Veillard
16147216cfd6622d947695c67b7b430edef8cc0af967Daniel Veillard    /*
16153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * compute depth to root
16163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
16173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
16183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node1)
16193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(1);
16203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth2++;
16213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    root = cur;
16233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
16243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node2)
16253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-1);
16263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth1++;
16273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
16293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Distinct document (or distinct entities :-( ) case.
16303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
16313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (root != cur) {
16323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-2);
16333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
16353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * get the nearest common ancestor.
16363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
16373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (depth1 > depth2) {
16383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth1--;
16393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node1 = node1->parent;
16403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (depth2 > depth1) {
16423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	depth2--;
16433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node2 = node2->parent;
16443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (node1->parent != node2->parent) {
16463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node1 = node1->parent;
16473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node2 = node2->parent;
16483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* should not happen but just in case ... */
16493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((node1 == NULL) || (node2 == NULL))
16503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(-2);
16513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
16523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
16533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Find who's first.
16543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1655f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard    if (node1 == node2->prev)
1656f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	return(1);
16573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node1 == node2->next)
16583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
1659f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard    /*
1660f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard     * Speedup using document order if availble.
1661f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard     */
1662f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard    if ((node1->type == XML_ELEMENT_NODE) &&
1663f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	(node2->type == XML_ELEMENT_NODE) &&
1664f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	(0 > (long) node1->content) &&
1665f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	(0 > (long) node2->content) &&
1666f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	(node1->doc == node2->doc)) {
1667f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	long l1, l2;
1668f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard
1669f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	l1 = -((long) node1->content);
1670f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	l2 = -((long) node2->content);
1671f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	if (l1 < l2)
1672f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	    return(1);
1673f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	if (l1 > l2)
1674f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard	    return(-1);
1675f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard    }
1676f49be4778db34e8bbcfabc5d5f1ad33c594b7387Daniel Veillard
16773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (cur = node1->next;cur != NULL;cur = cur->next)
16783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == node2)
16793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(1);
16803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(-1); /* assume there is no sibling list corruption */
16813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
16823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
16843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetSort:
16853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @set:  the node set
16863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
16873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Sort the node set in document order
16883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
16893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
16903473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetSort(xmlNodeSetPtr set) {
1691e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese    int i, j, incr, len;
16923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodePtr tmp;
16933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (set == NULL)
16953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
16963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Use Shell's sort to sort the node-set */
16983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    len = set->nodeNr;
16993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (incr = len / 2; incr > 0; incr /= 2) {
17003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (i = incr; i < len; i++) {
17013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    j = i - incr;
17023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (j >= 0) {
1703e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese		if (xmlXPathCmpNodes(set->nodeTab[j],
1704e1dc0114ac95b4d86c61a05169a3d8eb80fccff3Bjorn Reese				     set->nodeTab[j + incr]) == -1) {
17053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    tmp = set->nodeTab[j];
17063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    set->nodeTab[j] = set->nodeTab[j + incr];
17073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    set->nodeTab[j + incr] = tmp;
17083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    j -= incr;
17093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else
17103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
17113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
17123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
17133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
17143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
17153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XML_NODESET_DEFAULT	10
17173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1718044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetDupNs:
1719044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @node:  the parent node of the namespace XPath node
1720044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  the libxml namespace declaration node.
1721044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1722044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Namespace node in libxml don't match the XPath semantic. In a node set
1723044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * the namespace nodes are duplicated and the next pointer is set to the
1724044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * parent node in the XPath semantic.
1725044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1726044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * Returns the newly created object.
1727044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
1728044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillardstatic xmlNodePtr
1729044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
1730044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    xmlNsPtr cur;
1731044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1732044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
1733044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return(NULL);
1734044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
1735044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return((xmlNodePtr) ns);
1736044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1737044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1738044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * Allocate a new Namespace and fill the fields.
1739044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1740044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1741044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (cur == NULL) {
1742d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "duplicating namespace\n");
1743044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return(NULL);
1744044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1745044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    memset(cur, 0, sizeof(xmlNs));
1746044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->type = XML_NAMESPACE_DECL;
1747044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (ns->href != NULL)
1748044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->href = xmlStrdup(ns->href);
1749044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (ns->prefix != NULL)
1750044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->prefix = xmlStrdup(ns->prefix);
1751044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->next = (xmlNsPtr) node;
1752044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    return((xmlNodePtr) cur);
1753044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1754044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1755044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
1756044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetFreeNs:
1757044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  the XPath namespace node found in a nodeset.
1758044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1759081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Namespace nodes in libxml don't match the XPath semantic. In a node set
1760044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * the namespace nodes are duplicated and the next pointer is set to the
1761081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * parent node in the XPath semantic. Check if such a node needs to be freed
1762044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
1763f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Saninvoid
1764044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetFreeNs(xmlNsPtr ns) {
1765044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
1766044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return;
1767044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1768044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) {
1769044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (ns->href != NULL)
1770044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlFree((xmlChar *)ns->href);
1771044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (ns->prefix != NULL)
1772044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlFree((xmlChar *)ns->prefix);
1773044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlFree(ns);
1774044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1775044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1776044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1777044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
17783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetCreate:
17793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an initial xmlNodePtr, or NULL
17803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
17813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlNodeSetPtr of type double and of value @val
17823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
17833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
17843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
17853473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodeSetPtr
17863473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetCreate(xmlNodePtr val) {
17873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ret;
17883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
17903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
1791d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating nodeset\n");
17923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
17933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
17943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlNodeSet));
17953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val != NULL) {
17963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
17973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
17983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret->nodeTab == NULL) {
1799d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "creating nodeset\n");
1800d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlFree(ret);
18013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
18023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
18033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(ret->nodeTab, 0 ,
18043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
18053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        ret->nodeMax = XML_NODESET_DEFAULT;
1806044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (val->type == XML_NAMESPACE_DECL) {
1807044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val;
1808044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1809044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    ret->nodeTab[ret->nodeNr++] =
1810044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1811044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	} else
1812044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    ret->nodeTab[ret->nodeNr++] = val;
18133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
18143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
18153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
18163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1818f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeSetContains:
1819f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @cur:  the node-set
1820f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @val:  the node
1821f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1822f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * checks whether @cur contains @val
1823f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
1824f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns true (1) if @cur contains @val, false (0) otherwise
1825f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
1826f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
1827f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
1828f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i;
1829f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1830a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((cur == NULL) || (val == NULL)) return(0);
1831044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
1832044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0; i < cur->nodeNr; i++) {
1833044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) {
1834044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns1, ns2;
1835044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1836044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns1 = (xmlNsPtr) val;
1837044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns2 = (xmlNsPtr) cur->nodeTab[i];
1838044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if (ns1 == ns2)
1839044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return(1);
1840044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns1->next != NULL) && (ns2->next == ns1->next) &&
1841044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	            (xmlStrEqual(ns1->prefix, ns2->prefix)))
1842044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return(1);
1843044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
1844044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1845044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else {
1846044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0; i < cur->nodeNr; i++) {
1847044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (cur->nodeTab[i] == val)
1848044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		return(1);
1849044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1850f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
1851f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(0);
1852f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
1853f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
1854f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
1855044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * xmlXPathNodeSetAddNs:
1856044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @cur:  the initial node set
1857044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @node:  the hosting node
1858044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * @ns:  a the namespace node
1859044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard *
1860044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard * add a new namespace node to an existing NodeSet
1861044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard */
186279376ba94845db7096c3917f4f40baeb450eb0e9Aleksey Saninvoid
1863044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
1864044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    int i;
1865044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1866a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
1867a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
1868a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard        (ns->type != XML_NAMESPACE_DECL) ||
1869044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(node->type != XML_ELEMENT_NODE))
1870044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	return;
1871044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1872081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
1873044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1874081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * prevent duplicates
1875044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1876044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    for (i = 0;i < cur->nodeNr;i++) {
1877044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        if ((cur->nodeTab[i] != NULL) &&
1878044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
1879c62a147963b5839fc815267706eaec381f90ca16Daniel Veillard	    (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
1880044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
1881044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1882044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1883044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1884044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    /*
1885044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     * grow the nodeTab if needed
1886044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard     */
1887044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (cur->nodeMax == 0) {
1888044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
1889044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					     sizeof(xmlNodePtr));
1890044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (cur->nodeTab == NULL) {
1891d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
1892044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1893044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1894044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	memset(cur->nodeTab, 0 ,
1895044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
1896044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeMax = XML_NODESET_DEFAULT;
1897044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else if (cur->nodeNr == cur->nodeMax) {
1898044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        xmlNodePtr *temp;
1899044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1900044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        cur->nodeMax *= 2;
1901044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
1902044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				      sizeof(xmlNodePtr));
1903044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (temp == NULL) {
1904d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
1905044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    return;
1906044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
1907044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab = temp;
1908044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
1909044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
1910044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard}
1911044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1912044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard/**
19133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetAdd:
19143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
19153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  a new xmlNodePtr
19163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1917cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * add a new xmlNodePtr to an existing NodeSet
19183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
19193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
19203473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
19213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
19223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1923a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((cur == NULL) || (val == NULL)) return;
19243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1925ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#if 0
1926652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard    if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
1927652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	return;	/* an XSLT fake node */
1928ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#endif
1929652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard
1930081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
19313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
1932081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * prevent duplcates
19333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
19343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->nodeNr;i++)
19353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->nodeTab[i] == val) return;
19363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
19383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * grow the nodeTab if needed
19393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
19403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->nodeMax == 0) {
19413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
19423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
19433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->nodeTab == NULL) {
1944d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
19453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
19463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
19473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(cur->nodeTab, 0 ,
19483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
19493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax = XML_NODESET_DEFAULT;
19503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->nodeNr == cur->nodeMax) {
19513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNodePtr *temp;
19523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax *= 2;
19543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
19553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				      sizeof(xmlNodePtr));
19563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (temp == NULL) {
1957d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
19583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
19593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
19603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->nodeTab = temp;
19613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1962044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
1963044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlNsPtr ns = (xmlNsPtr) val;
1964044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
1965044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] =
1966044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
1967044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else
1968044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] = val;
19693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
19703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
19723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetAddUnique:
19733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
19743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  a new xmlNodePtr
19753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1976cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * add a new xmlNodePtr to an existing NodeSet, optimized version
19773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * when we are sure the node is not already in the set.
19783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
19793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
19803473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
1981a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((cur == NULL) || (val == NULL)) return;
19823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1983ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#if 0
1984652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard    if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
1985652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	return;	/* an XSLT fake node */
1986ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard#endif
1987652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard
1988081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
19893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
19903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * grow the nodeTab if needed
19913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
19923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->nodeMax == 0) {
19933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
19943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
19953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->nodeTab == NULL) {
1996d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
19973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
19983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
19993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	memset(cur->nodeTab, 0 ,
20003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	       XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
20013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax = XML_NODESET_DEFAULT;
20023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (cur->nodeNr == cur->nodeMax) {
20033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlNodePtr *temp;
20043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeMax *= 2;
20063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax *
20073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				      sizeof(xmlNodePtr));
20083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (temp == NULL) {
2009d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathErrMemory(NULL, "growing nodeset\n");
20103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
20113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
20123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->nodeTab = temp;
20133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2014044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if (val->type == XML_NAMESPACE_DECL) {
2015044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlNsPtr ns = (xmlNsPtr) val;
2016044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2017044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] =
2018044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2019044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    } else
2020044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	cur->nodeTab[cur->nodeNr++] = val;
20213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
20223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
20243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetMerge:
20253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val1:  the first NodeSet or NULL
20263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val2:  the second NodeSet
20273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
20283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Merges two nodesets, all nodes from @val2 are added to @val1
20293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if @val1 is NULL, a new set is created and copied from @val2
20303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
2031cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns @val1 once extended or NULL in case of error.
20323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
20333473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodeSetPtr
20343473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
2035d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    int i, j, initNr, skip;
20363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val2 == NULL) return(val1);
20383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val1 == NULL) {
20393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	val1 = xmlXPathNodeSetCreate(NULL);
20403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2042081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
20433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    initNr = val1->nodeNr;
20443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < val2->nodeNr;i++) {
20463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
2047081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	 * check against duplicates
20483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
2049d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	skip = 0;
2050d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	for (j = 0; j < initNr; j++) {
2051d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    if (val1->nodeTab[j] == val2->nodeTab[i]) {
2052d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		skip = 1;
2053d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		break;
2054044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    } else if ((val1->nodeTab[j]->type == XML_NAMESPACE_DECL) &&
2055044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		       (val2->nodeTab[i]->type == XML_NAMESPACE_DECL)) {
2056044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns1, ns2;
2057044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns1 = (xmlNsPtr) val1->nodeTab[j];
2058044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		ns2 = (xmlNsPtr) val2->nodeTab[i];
2059044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns1->next == ns2->next) &&
2060044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (xmlStrEqual(ns1->prefix, ns2->prefix))) {
2061044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    skip = 1;
2062044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    break;
2063044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		}
2064d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    }
2065d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	}
2066d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	if (skip)
2067d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    continue;
20683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
20703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * grow the nodeTab if needed
20713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
20723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (val1->nodeMax == 0) {
20733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
20743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor						    sizeof(xmlNodePtr));
20753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (val1->nodeTab == NULL) {
2076d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	        xmlXPathErrMemory(NULL, "merging nodeset\n");
20773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
20783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
20793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    memset(val1->nodeTab, 0 ,
20803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
20813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeMax = XML_NODESET_DEFAULT;
20823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (val1->nodeNr == val1->nodeMax) {
20833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlNodePtr *temp;
20843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeMax *= 2;
20863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
20873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor					     sizeof(xmlNodePtr));
20883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (temp == NULL) {
2089d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	        xmlXPathErrMemory(NULL, "merging nodeset\n");
20903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
20913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
20923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val1->nodeTab = temp;
20933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
2094044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2095044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
2096044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2097044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    val1->nodeTab[val1->nodeNr++] =
2098044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2099044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	} else
2100044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
21013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(val1);
21043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
210775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * xmlXPathNodeSetMergeUnique:
210875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * @val1:  the first NodeSet or NULL
210975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * @val2:  the second NodeSet
211075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard *
211175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * Merges two nodesets, all nodes from @val2 are added to @val1
211275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * if @val1 is NULL, a new set is created and copied from @val2
211375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard *
211475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard * Returns @val1 once extended or NULL in case of error.
211575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard */
211675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillardstatic xmlNodeSetPtr
211775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel VeillardxmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
211878637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    int i;
211975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
212075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    if (val2 == NULL) return(val1);
212175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    if (val1 == NULL) {
212275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	val1 = xmlXPathNodeSetCreate(NULL);
212375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    }
212475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
2125081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
212675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
212775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    for (i = 0;i < val2->nodeNr;i++) {
212875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	/*
212975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	 * grow the nodeTab if needed
213075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	 */
213175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	if (val1->nodeMax == 0) {
213275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
213375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard						    sizeof(xmlNodePtr));
213475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    if (val1->nodeTab == NULL) {
2135d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	        xmlXPathErrMemory(NULL, "merging nodeset\n");
213675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		return(NULL);
213775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    }
213875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    memset(val1->nodeTab, 0 ,
213975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		   XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
214075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeMax = XML_NODESET_DEFAULT;
214175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	} else if (val1->nodeNr == val1->nodeMax) {
214275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    xmlNodePtr *temp;
214375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
214475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeMax *= 2;
214575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
214675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard					     sizeof(xmlNodePtr));
214775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    if (temp == NULL) {
2148d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	        xmlXPathErrMemory(NULL, "merging nodeset\n");
214975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		return(NULL);
215075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    }
215175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab = temp;
215275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	}
215375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
215475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
215575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
215675be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab[val1->nodeNr++] =
215775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard		xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
215875be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	} else
215975be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
216075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    }
216175be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
216275be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    return(val1);
216375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard}
216475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard
216575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard/**
21663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetDel:
21673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
21683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an xmlNodePtr
21693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
21703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Removes an xmlNodePtr from an existing NodeSet
21713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
21723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
21733473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
21743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
21753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return;
21773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL) return;
21783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
2180081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * find node in nodeTab
21813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
21823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < cur->nodeNr;i++)
21833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->nodeTab[i] == val) break;
21843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2185081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    if (i >= cur->nodeNr) {	/* not found */
21863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG
21873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlGenericError(xmlGenericErrorContext,
21883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        "xmlXPathNodeSetDel: Node %s wasn't found in NodeList\n",
21893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		val->name);
21903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
21913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return;
21923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
2193044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((cur->nodeTab[i] != NULL) &&
2194044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(cur->nodeTab[i]->type == XML_NAMESPACE_DECL))
2195044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]);
21963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeNr--;
21973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (;i < cur->nodeNr;i++)
21983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab[i] = cur->nodeTab[i + 1];
21993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeTab[cur->nodeNr] = NULL;
22003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
22033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNodeSetRemove:
22043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the initial node set
22053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the index to remove
22063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Removes an entry from an existing NodeSet list.
22083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
22093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
22103473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) {
22113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return;
22123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val >= cur->nodeNr) return;
2213044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    if ((cur->nodeTab[val] != NULL) &&
2214044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	(cur->nodeTab[val]->type == XML_NAMESPACE_DECL))
2215044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]);
22163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeNr--;
22173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (;val < cur->nodeNr;val++)
22183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur->nodeTab[val] = cur->nodeTab[val + 1];
22193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur->nodeTab[cur->nodeNr] = NULL;
22203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
22233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeNodeSet:
22243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
22253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free the NodeSet compound (not the actual nodes !).
22273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
22283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
22293473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
22303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
22313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab != NULL) {
2232044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	int i;
2233044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
2234081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	/* @@ with_ns to check whether namespace nodes should be looked at @@ */
2235044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0;i < obj->nodeNr;i++)
2236044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if ((obj->nodeTab[i] != NULL) &&
2237044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		(obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
2238044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
22393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(obj->nodeTab);
22403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
22413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
22423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
22453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeValueTree:
22463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the xmlNodeSetPtr to free
22473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free the NodeSet compound and the actual tree, this is different
22493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * from xmlXPathFreeNodeSet()
22503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
225156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
22523473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeValueTree(xmlNodeSetPtr obj) {
22533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
22543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
22563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab != NULL) {
2258044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	for (i = 0;i < obj->nodeNr;i++) {
2259044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    if (obj->nodeTab[i] != NULL) {
2260044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if (obj->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2261044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
2262044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		} else {
2263044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    xmlFreeNodeList(obj->nodeTab[i]);
2264044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		}
2265044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
2266044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	}
22673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(obj->nodeTab);
22683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
22693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
22703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
22713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if defined(DEBUG) || defined(DEBUG_STEP)
22733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
22743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlGenericErrorContextNodeSet:
22753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @output:  a FILE * for the output
2276081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * @obj:  the xmlNodeSetPtr to display
22773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
22783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Quick display of a NodeSet
22793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
22803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
22813473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlGenericErrorContextNodeSet(FILE *output, xmlNodeSetPtr obj) {
22823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
22833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
22843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (output == NULL) output = xmlGenericErrorContext;
22853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL)  {
22863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "NodeSet == NULL !\n");
22873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
22883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
22893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeNr == 0) {
22903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        fprintf(output, "NodeSet is empty\n");
22913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
22923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
22933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj->nodeTab == NULL) {
22943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	fprintf(output, " nodeTab == NULL !\n");
22953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
22963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
22973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0; i < obj->nodeNr; i++) {
22983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (obj->nodeTab[i] == NULL) {
22993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " NULL !\n");
23003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
23013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
23023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((obj->nodeTab[i]->type == XML_DOCUMENT_NODE) ||
23033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (obj->nodeTab[i]->type == XML_HTML_DOCUMENT_NODE))
23043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " /");
23053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (obj->nodeTab[i]->name == NULL)
23063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    fprintf(output, " noname!");
23073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else fprintf(output, " %s", obj->nodeTab[i]->name);
23083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
23093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    fprintf(output, "\n");
23103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
23113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
23123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
23143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewNodeSet:
23153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
23163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type NodeSet and initialize
23183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the single Node @val
23193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
23213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
23223473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
23233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewNodeSet(xmlNodePtr val) {
23243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
23253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
23273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
2328d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating nodeset\n");
23293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
23303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
23313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
23323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NODESET;
233377851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard    ret->boolval = 0;
23343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = xmlXPathNodeSetCreate(val);
2335081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    /* @@ with_ns to check whether namespace nodes should be looked at @@ */
23363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
23373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
23383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
23403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewValueTree:
23413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
23423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize
23443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the tree root @val
23453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
23473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
23483473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
23493473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewValueTree(xmlNodePtr val) {
23503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
23513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
23533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
2354d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating result value tree\n");
23553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
23563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
23573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
23583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_XSLT_TREE;
23590ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    ret->boolval = 1;
23600ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    ret->user = (void *) val;
23613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = xmlXPathNodeSetCreate(val);
23623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
23633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
23643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
23663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewNodeSetList:
23673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  an existing NodeSet
23683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type NodeSet and initialize
23703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * it with the Nodeset @val
23713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
23733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
23743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
2375044fc6b7476798cbb95277b4905e5111d7c2775dDaniel VeillardxmlXPathNewNodeSetList(xmlNodeSetPtr val)
2376044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard{
23773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
23783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
23793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL)
2381044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = NULL;
23823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (val->nodeTab == NULL)
2383044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = xmlXPathNewNodeSet(NULL);
2384044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    else {
2385044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        ret = xmlXPathNewNodeSet(val->nodeTab[0]);
2386044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard        for (i = 1; i < val->nodeNr; ++i)
2387044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard            xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]);
2388044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    }
23893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2390044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard    return (ret);
23913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
23923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
23933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
23943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathWrapNodeSet:
23953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the NodePtr value
23963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Wrap the Nodeset @val in a new xmlXPathObjectPtr
23983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
23993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
24003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
24013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
24023473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathWrapNodeSet(xmlNodeSetPtr val) {
24033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
24043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
24053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
24063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
2407d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating node set object\n");
24083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
24093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
24103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
24113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NODESET;
24123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nodesetval = val;
24133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
24143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
24153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
24163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
24173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeNodeSetList:
24183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  an existing NodeSetList object
24193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
24203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
24213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the list contrary to xmlXPathFreeObject().
24223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
24233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
24243473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
24253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
24263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
24273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
24283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2429f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2430f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDifference:
2431f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2432f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2433f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2434f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets difference() function:
2435f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:difference (node-set, node-set)
2436f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2437f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the difference between the two node sets, or nodes1 if
2438f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         nodes2 is empty
2439f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2440f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2441f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2442f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2443f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l1;
2444f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2445f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2446f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2447f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2448f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2449f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2450f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2451f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2452f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2453f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l1 = xmlXPathNodeSetGetLength(nodes1);
2454f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2455f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l1; i++) {
2456f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2457f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (!xmlXPathNodeSetContains(nodes2, cur))
2458f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2459f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2460f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2461f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2462f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2463f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2464f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathIntersection:
2465f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2466f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2467f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2468f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets intersection() function:
2469f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:intersection (node-set, node-set)
2470f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2471f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a node set comprising the nodes that are within both the
2472f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         node sets passed as arguments
2473f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2474f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2475f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2476f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
2477f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l1;
2478f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2479f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2480f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2481f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2482f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2483f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2484f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2485f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l1 = xmlXPathNodeSetGetLength(nodes1);
2486f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2487f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l1; i++) {
2488f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2489f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlXPathNodeSetContains(nodes2, cur))
2490f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2491f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2492f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2493f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2494f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2495f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2496f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDistinctSorted:
2497f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set, sorted by document order
2498f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2499f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets distinct() function:
2500f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:distinct (node-set)
2501f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2502f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a subset of the nodes contained in @nodes, or @nodes if
2503f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         it is empty
2504f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2505f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2506f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
2507f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2508f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlHashTablePtr hash;
2509f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2510f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlChar * strval;
2511f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2512f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2513f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes))
2514f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2515f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2516f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2517f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2518f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    hash = xmlHashCreate (l);
2519f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2520f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2521f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	strval = xmlXPathCastNodeToString(cur);
2522f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlHashLookup(hash, strval) == NULL) {
2523f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlHashAddEntry(hash, strval, strval);
2524f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlXPathNodeSetAddUnique(ret, cur);
2525f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	} else {
2526f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    xmlFree(strval);
2527f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	}
2528f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2529f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlHashFree(hash, (xmlHashDeallocator) xmlFree);
2530f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2531f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2532f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2533f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2534f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathDistinct:
2535f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2536f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2537f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets distinct() function:
2538f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:distinct (node-set)
2539f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #exslSetsDistinctSorted
2540f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called with the sorted node-set
2541f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2542f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns a subset of the nodes contained in @nodes, or @nodes if
2543f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         it is empty
2544f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2545f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2546f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathDistinct (xmlNodeSetPtr nodes) {
2547f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes))
2548f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2549f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2550f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2551f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathDistinctSorted(nodes));
2552f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2553f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2554f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2555f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathHasSameNodes:
2556f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2557f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2558f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2559f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets has-same-nodes function:
2560f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    boolean set:has-same-node(node-set, node-set)
2561f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2562f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
2563f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         otherwise
2564f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2565f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyerint
2566f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2567f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2568f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2569f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2570f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1) ||
2571f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetIsEmpty(nodes2))
2572f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(0);
2573f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2574f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes1);
2575f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2576f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes1, i);
2577f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (xmlXPathNodeSetContains(nodes2, cur))
2578f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    return(1);
2579f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2580f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(0);
2581f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2582f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2583f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2584f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeLeadingSorted:
2585f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes: a node-set, sorted by document order
2586f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node: a node
2587f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2588f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2589f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2590f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2591f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that precede @node in document order,
2592f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2593f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2594f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2595f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2596f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
2597f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2598f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2599f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2600f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2601f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (node == NULL)
2602f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2603f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2604f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2605f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes) ||
2606f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	(!xmlXPathNodeSetContains(nodes, node)))
2607f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2608f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2609f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2610f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    for (i = 0; i < l; i++) {
2611f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2612f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (cur == node)
2613f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    break;
2614f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetAddUnique(ret, cur);
2615f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2616f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2617f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2618f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2619f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2620f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeLeading:
2621f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2622f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node:  a node
2623f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2624f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2625f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2626f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
2627f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called.
2628f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2629f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that precede @node in document order,
2630f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2631f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2632f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2633f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2634f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
2635f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2636f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes, node));
2637f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2638f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2639f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2640f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathLeadingSorted:
2641f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set, sorted by document order
2642f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set, sorted by document order
2643f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2644f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2645f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2646f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2647f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that precede the first node in @nodes2
2648f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2649f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2650f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2651f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2652f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2653f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2654f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2655f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes1,
2656f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				     xmlXPathNodeSetItem(nodes2, 1)));
2657f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2658f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2659f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2660f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathLeading:
2661f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2662f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2663f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2664f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets leading() function:
2665f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:leading (node-set, node-set)
2666f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1 and @nodes2 are sorted by document order, then
2667f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * #exslSetsLeadingSorted is called.
2668f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2669f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that precede the first node in @nodes2
2670f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2671f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2672f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2673f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2674f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2675f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2676f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2677f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2678f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(xmlXPathNodeSetCreate(NULL));
2679f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes1);
2680f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes2);
2681f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeLeadingSorted(nodes1,
2682f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				     xmlXPathNodeSetItem(nodes2, 1)));
2683f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2684f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2685f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2686f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeTrailingSorted:
2687f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes: a node-set, sorted by document order
2688f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node: a node
2689f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2690f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2691f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2692f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2693f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that follow @node in document order,
2694f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2695f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2696f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2697f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2698f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
2699f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    int i, l;
2700f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodePtr cur;
2701f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlNodeSetPtr ret;
2702f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2703f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (node == NULL)
2704f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes);
2705f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2706f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = xmlXPathNodeSetCreate(NULL);
2707f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes) ||
2708f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	(!xmlXPathNodeSetContains(nodes, node)))
2709f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(ret);
2710f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2711f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    l = xmlXPathNodeSetGetLength(nodes);
2712f186c8259ae985cd56b3e14c1def484ab127fd14Thomas Broyer    for (i = l; i > 0; i--) {
2713f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	cur = xmlXPathNodeSetItem(nodes, i);
2714f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	if (cur == node)
2715f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	    break;
2716f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	xmlXPathNodeSetAddUnique(ret, cur);
2717f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
2718f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
2719f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2720f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2721f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2722f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathNodeTrailing:
2723f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes:  a node-set
2724f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @node:  a node
2725f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2726f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2727f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2728f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
2729f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * is called.
2730f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2731f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes that follow @node in document order,
2732f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         @nodes if @node is NULL or an empty node-set if @nodes
2733f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         doesn't contain @node
2734f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2735f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2736f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
2737f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes);
2738f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes, node));
2739f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2740f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2741f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2742f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathTrailingSorted:
2743f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set, sorted by document order
2744f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set, sorted by document order
2745f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2746f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2747f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2748f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2749f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that follow the first node in @nodes2
2750f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2751f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2752f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2753f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2754f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2755f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2756f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2757f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes1,
2758f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				      xmlXPathNodeSetItem(nodes2, 0)));
2759f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2760f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
2761f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
2762f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathTrailing:
2763f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1:  a node-set
2764f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes2:  a node-set
2765f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2766f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Implements the EXSLT - Sets trailing() function:
2767f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *    node-set set:trailing (node-set, node-set)
2768f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @nodes1 and @nodes2 are sorted by document order, then
2769f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * #xmlXPathTrailingSorted is called.
2770f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
2771f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the nodes in @nodes1 that follow the first node in @nodes2
2772f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         in document order, @nodes1 if @nodes2 is NULL or empty or
2773f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *         an empty node-set if @nodes1 doesn't contain @nodes2
2774f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
2775f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlNodeSetPtr
2776f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
2777f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes2))
2778f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(nodes1);
2779f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (xmlXPathNodeSetIsEmpty(nodes1))
2780f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(xmlXPathNodeSetCreate(NULL));
2781f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes1);
2782f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathNodeSetSort(nodes2);
2783f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(xmlXPathNodeTrailingSorted(nodes1,
2784f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer				      xmlXPathNodeSetItem(nodes2, 0)));
2785f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
2786f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
27873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
27883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
27893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle extra functions			*
27903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
27913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
27923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
27933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
27943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterFunc:
27953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
27963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
27973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the function implementation or NULL
27983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
27993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new function. If @f is NULL it unregisters the function
28003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
28023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
28043473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
28053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		     xmlXPathFunction f) {
28063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f));
28073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterFuncNS:
28113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
28133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the function namespace URI
28143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the function implementation or NULL
28153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new function. If @f is NULL it unregisters the function
28173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
28193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
28213473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
28223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		       const xmlChar *ns_uri, xmlXPathFunction f) {
28233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
28253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
28263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
28273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->funcHash == NULL)
28293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->funcHash = xmlHashCreate(0);
28303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->funcHash == NULL)
28313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
283294394cd1e494f8d669b310748f54192268185c8dDaniel Veillard    if (f == NULL)
283394394cd1e494f8d669b310748f54192268185c8dDaniel Veillard        return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL));
2834ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack    return(xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, XML_CAST_FPTR(f)));
28353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
2838ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * xmlXPathRegisterFuncLookup:
2839ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * @ctxt:  the XPath context
2840ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer * @f:  the lookup function
2841cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @funcCtxt:  the lookup data
2842ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer *
2843cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Registers an external mechanism to do function lookup.
2844ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer */
2845ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyervoid
2846ba4ad3263bf7f5625329f115367e0c7018521a16Thomas BroyerxmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
2847ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer			    xmlXPathFuncLookupFunc f,
2848ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer			    void *funcCtxt) {
2849ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt == NULL)
2850ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return;
28516ebf3c4c1a78406d15e8629b4a7b3d52549f0c8bDaniel Veillard    ctxt->funcLookupFunc = f;
2852ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    ctxt->funcLookupData = funcCtxt;
2853ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer}
2854ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2855ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer/**
28563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFunctionLookup:
28573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
28593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Function array of the context for the given
28613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * function.
28623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathFunction or NULL if not found
28643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunction
28663473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
2867ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt == NULL)
2868ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return (NULL);
2869ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2870ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcLookupFunc != NULL) {
2871ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	xmlXPathFunction ret;
287299e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	xmlXPathFuncLookupFunc f;
2873ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
28746ebf3c4c1a78406d15e8629b4a7b3d52549f0c8bDaniel Veillard	f = ctxt->funcLookupFunc;
2875963d2ae41574066f9b44bcae610dd280c1e57dd8Daniel Veillard	ret = f(ctxt->funcLookupData, name, NULL);
2876ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	if (ret != NULL)
2877ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	    return(ret);
2878ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    }
28793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
28803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
28813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
28823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
28833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFunctionLookupNS:
28843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
28853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the function name
28863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the function namespace URI
28873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Function array of the context for the given
28893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * function.
28903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
28913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathFunction or NULL if not found
28923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
28933473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunction
28943473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
28953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 const xmlChar *ns_uri) {
2896ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack    xmlXPathFunction ret;
2897ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack
28983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
28993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
29003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
29013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
29023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2903ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcLookupFunc != NULL) {
290499e55ebe945f6f4de33e8454f2770e02295a3a00Daniel Veillard	xmlXPathFuncLookupFunc f;
2905ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
29066ebf3c4c1a78406d15e8629b4a7b3d52549f0c8bDaniel Veillard	f = ctxt->funcLookupFunc;
2907963d2ae41574066f9b44bcae610dd280c1e57dd8Daniel Veillard	ret = f(ctxt->funcLookupData, name, ns_uri);
2908ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	if (ret != NULL)
2909ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	    return(ret);
2910ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    }
2911ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2912ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer    if (ctxt->funcHash == NULL)
2913ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer	return(NULL);
2914ba4ad3263bf7f5625329f115367e0c7018521a16Thomas Broyer
2915ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack    XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
2916ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack    return(ret);
29173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisteredFuncsCleanup:
29213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
29223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered functions
29243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
29263473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
29273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
29283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
29293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlHashFree(ctxt->funcHash, NULL);
29313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->funcHash = NULL;
29323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
29353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
2936081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack *			Routines to handle Variables			*
29373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
29383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
29393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariable:
29423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
29433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
29443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @value:  the variable value or NULL
29453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new variable value. If @value is NULL it unregisters
29473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the variable
29483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
29503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
29523473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
29533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 xmlXPathObjectPtr value) {
29543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value));
29553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariableNS:
29593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
29603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
29613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the variable namespace URI
29623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @value:  the variable value or NULL
29633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new variable value. If @value is NULL it unregisters
29653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the variable
29663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
29683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
29703473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name,
29713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   const xmlChar *ns_uri,
29723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   xmlXPathObjectPtr value) {
29733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
29743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
29753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
29763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
29773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
29793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->varHash = xmlHashCreate(0);
29803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
29813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
298294394cd1e494f8d669b310748f54192268185c8dDaniel Veillard    if (value == NULL)
298394394cd1e494f8d669b310748f54192268185c8dDaniel Veillard        return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri,
298494394cd1e494f8d669b310748f54192268185c8dDaniel Veillard	                           (xmlHashDeallocator)xmlXPathFreeObject));
29853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
29863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			       (void *) value,
29873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			       (xmlHashDeallocator)xmlXPathFreeObject));
29883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
29893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
29903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
29913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterVariableLookup:
29923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
29933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the lookup function
29943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @data:  the lookup data
29953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
29963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * register an external mechanism to do variable lookup
29973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
29983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
29993473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
30003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 xmlXPathVariableLookupFunc f, void *data) {
30013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
30023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
30036ebf3c4c1a78406d15e8629b4a7b3d52549f0c8bDaniel Veillard    ctxt->varLookupFunc = f;
30043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varLookupData = data;
30053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
30063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
30083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathVariableLookup:
30093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
30103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
30113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Variable array of the context for the given
30133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * variable value.
30143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
301573c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * Returns a copy of the value or NULL if not found
30163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
30173473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
30183473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
30193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
30203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varLookupFunc != NULL) {
30233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathObjectPtr ret;
30243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
30263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        (ctxt->varLookupData, name, NULL);
3027556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	return(ret);
30283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
30293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathVariableLookupNS(ctxt, name, NULL));
30303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
30313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
30333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathVariableLookupNS:
30343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
30353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  the variable name
30363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the variable namespace URI
30373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the Variable array of the context for the given
303973c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * variable value.
30403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
304173c9c049195bf897dbcb6308a1ab9d16b3fe6b2cDaniel Veillard * Returns the a copy of the value or NULL if not found
30423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
30433473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
30443473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
30453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			 const xmlChar *ns_uri) {
30463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
30473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varLookupFunc != NULL) {
30503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathObjectPtr ret;
30513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
30533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        (ctxt->varLookupData, name, ns_uri);
30543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret != NULL) return(ret);
30553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
30563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->varHash == NULL)
30583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
30603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
30613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30628c357d58c2d1dde022b67393a47dcb52100ce129Daniel Veillard    return(xmlXPathObjectCopy((xmlXPathObjectPtr)
30638c357d58c2d1dde022b67393a47dcb52100ce129Daniel Veillard		xmlHashLookup2(ctxt->varHash, name, ns_uri)));
30643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
30653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
30673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisteredVariablesCleanup:
30683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
30693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered variables
30713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
30723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
30733473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
30743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
30753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
30763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
307776d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard    xmlHashFree(ctxt->varHash, (xmlHashDeallocator)xmlXPathFreeObject);
30783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->varHash = NULL;
30793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
30803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
30813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
30823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterNs:
30833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
30843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  the namespace prefix
30853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ns_uri:  the namespace name
30863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Register a new namespace. If @ns_uri is NULL it unregisters
30883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the namespace
30893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
30903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 in case of success, -1 in case of error
30913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
30923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
30933473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
30943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   const xmlChar *ns_uri) {
30953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
30963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
30973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
30983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
30993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->nsHash == NULL)
31013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ctxt->nsHash = xmlHashCreate(10);
31023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->nsHash == NULL)
31033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
3104e991fe958f5269a459262bcff802a3d26167edb8Daniel Veillard    if (ns_uri == NULL)
310594394cd1e494f8d669b310748f54192268185c8dDaniel Veillard        return(xmlHashRemoveEntry(ctxt->nsHash, prefix,
3106e991fe958f5269a459262bcff802a3d26167edb8Daniel Veillard	                          (xmlHashDeallocator)xmlFree));
310742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) xmlStrdup(ns_uri),
31083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			      (xmlHashDeallocator)xmlFree));
31093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
31123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNsLookup:
31133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
31143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  the namespace prefix value
31153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Search in the namespace declaration array of the context for the given
31173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace name associated to the given prefix
31183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the value or NULL if not found
31203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorconst xmlChar *
31223473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
31233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
31243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
31253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
31263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
31273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef XML_XML_NAMESPACE
31293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
31303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(XML_XML_NAMESPACE);
31313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
31323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3133c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard    if (ctxt->namespaces != NULL) {
3134c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	int i;
3135c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard
3136c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	for (i = 0;i < ctxt->nsNr;i++) {
3137c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	    if ((ctxt->namespaces[i] != NULL) &&
3138c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard		(xmlStrEqual(ctxt->namespaces[i]->prefix, prefix)))
3139c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard		return(ctxt->namespaces[i]->href);
3140c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard	}
3141c8f620ba7f95b3ceb687699e140eeaa33343e41aDaniel Veillard    }
31423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
31443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
31475e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathRegisteredNsCleanup:
31483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
31493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Cleanup the XPath context data associated to registered variables
31513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
31533473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
31543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL)
31553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
31563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
315742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlHashFree(ctxt->nsHash, (xmlHashDeallocator)xmlFree);
31583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->nsHash = NULL;
31593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
31623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
31633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Routines to handle Values			*
31643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
31653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
31663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3167081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack/* Allocations are terrible, one needs to optimize all this !!! */
31683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
31703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewFloat:
31713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the double value
31723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type double and of value @val
31743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
31763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
31773473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
31783473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewFloat(double val) {
31793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
31803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
31823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3183d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating float object\n");
31843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
31853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
31863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
31873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_NUMBER;
31883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->floatval = val;
31893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
31903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
31913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
31923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
31933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewBoolean:
31943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the boolean value
31953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type boolean and of value @val
31973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
31983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
31993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
32003473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
32013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewBoolean(int val) {
32023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
32033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
32053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3206d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating boolean object\n");
32073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
32083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
32093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
32103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_BOOLEAN;
32113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->boolval = (val != 0);
32123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
32133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
32163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewString:
32173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the xmlChar * value
32183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type string and of value @val
32203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
32223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
32233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
32243473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewString(const xmlChar *val) {
32253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
32263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
32283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3229d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating string object\n");
32303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
32313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
32323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
32333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_STRING;
32343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val != NULL)
32353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret->stringval = xmlStrdup(val);
32363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
32373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret->stringval = xmlStrdup((const xmlChar *)"");
32383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
32393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3242ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathWrapString:
3243ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  the xmlChar * value
3244ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3245ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Wraps the @val string into an XPath object.
3246ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3247ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the newly created object.
3248ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3249ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3250ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathWrapString (xmlChar *val) {
3251ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3252ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3253ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3254ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (ret == NULL) {
3255d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating string object\n");
3256ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(NULL);
3257ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3258ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
3259ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret->type = XPATH_STRING;
3260ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret->stringval = val;
3261ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3262ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3263ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3264ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
32653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewCString:
32663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the char * value
32673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathObjectPtr of type string and of value @val
32693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
32703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
32713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
32723473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
32733473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewCString(const char *val) {
32743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
32753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
32773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3278d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating string object\n");
32793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
32803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
32813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
32823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->type = XPATH_STRING;
32833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->stringval = xmlStrdup(BAD_CAST val);
32843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
32853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
32863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
32873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
3288ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathWrapCString:
3289ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  the char * value
3290ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3291ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Wraps a string into an XPath object.
3292ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3293ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the newly created object.
3294ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3295ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3296ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathWrapCString (char * val) {
3297ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathWrapString((xmlChar *)(val)));
3298ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3299ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3300ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3301f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * xmlXPathWrapExternal:
3302f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * @val:  the user data
3303f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3304f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Wraps the @val data into an XPath object.
3305f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer *
3306f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer * Returns the newly created object.
3307f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer */
3308f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathObjectPtr
3309f06a3d8b53686e215eb3302eea32436e8c3f693fThomas BroyerxmlXPathWrapExternal (void *val) {
3310f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    xmlXPathObjectPtr ret;
3311f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3312f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3313f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    if (ret == NULL) {
3314d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating user object\n");
3315f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer	return(NULL);
3316f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    }
3317f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
3318f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret->type = XPATH_USERS;
3319f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    ret->user = val;
3320f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer    return(ret);
3321f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer}
3322f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer
3323f06a3d8b53686e215eb3302eea32436e8c3f693fThomas Broyer/**
33243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathObjectCopy:
33253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the original object
33263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
33273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * allocate a new copy of a given object
33283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
33293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the newly created object.
33303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
33313473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
33323473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectCopy(xmlXPathObjectPtr val) {
33333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr ret;
33343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (val == NULL)
33363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
33373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
33383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
33393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3340d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "copying object\n");
33413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
33423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
33433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memcpy(ret, val , (size_t) sizeof(xmlXPathObject));
33443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (val->type) {
33453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_BOOLEAN:
33463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_NUMBER:
33473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
33483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
33493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
33503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_STRING:
33513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->stringval = xmlStrdup(val->stringval);
33523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
33533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_XSLT_TREE:
3354e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#if 0
3355e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack/*
3356e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack  Removed 11 July 2004 - the current handling of xslt tmpRVT nodes means that
3357e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack  this previous handling is no longer correct, and can cause some serious
3358e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack  problems (ref. bug 145547)
3359e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack*/
33603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((val->nodesetval != NULL) &&
33610ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard		(val->nodesetval->nodeTab != NULL)) {
33629adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		xmlNodePtr cur, tmp;
33639adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		xmlDocPtr top;
3364ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard
33650ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard		ret->boolval = 1;
33669adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		top =  xmlNewDoc(NULL);
33679adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		top->name = (char *)
33689adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    xmlStrdup(val->nodesetval->nodeTab[0]->name);
3369ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		ret->user = top;
3370ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		if (top != NULL) {
33719adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    top->doc = top;
3372ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    cur = val->nodesetval->nodeTab[0]->children;
3373ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    while (cur != NULL) {
33749adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard			tmp = xmlDocCopyNode(cur, top, 1);
33759adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard			xmlAddChild((xmlNodePtr) top, tmp);
3376ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard			cur = cur->next;
3377ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		    }
3378ef0b45016373d65700ef6f7d494a200758b2e4c5Daniel Veillard		}
3379e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack
33809adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		ret->nodesetval = xmlXPathNodeSetCreate((xmlNodePtr) top);
33810ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    } else
33823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret->nodesetval = xmlXPathNodeSetCreate(NULL);
33830ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    /* Deallocate the copied tree value */
33843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
3385e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#endif
33863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_NODESET:
33873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
33880ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    /* Do not deallocate the copied tree value */
33890ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    ret->boolval = 0;
33903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
33913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
33923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
33933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	{
33943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlLocationSetPtr loc = val->user;
33953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc);
33963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
33973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
33983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
339947334c09f4373e4cff71334e60a623fee73a525fThomas Broyer        case XPATH_USERS:
340047334c09f4373e4cff71334e60a623fee73a525fThomas Broyer	    ret->user = val->user;
340147334c09f4373e4cff71334e60a623fee73a525fThomas Broyer	    break;
340247334c09f4373e4cff71334e60a623fee73a525fThomas Broyer        case XPATH_UNDEFINED:
34033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
34043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "xmlXPathObjectCopy: unsupported type %d\n",
34053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    val->type);
34063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
34073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
34083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
34093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
34103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
34123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeObject:
34133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @obj:  the object to free
34143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
34153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathObjectPtr object.
34163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
34173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
34183473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeObject(xmlXPathObjectPtr obj) {
34193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) return;
34200ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
342177851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	if (obj->boolval) {
3422e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#if 0
34230ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	    if (obj->user != NULL) {
34240ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard                xmlXPathFreeNodeSet(obj->nodesetval);
342538bf6f042507c6051bfa2db5cc9b6666cfc35c2aDaniel Veillard		xmlFreeNodeList((xmlNodePtr) obj->user);
3426e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack	    } else
3427e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack#endif
3428e9449c5d29d87b1dc51de7784ed947ae1e3da831William M. Brack	    if (obj->nodesetval != NULL)
342977851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard		xmlXPathFreeValueTree(obj->nodesetval);
343077851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	} else {
343177851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	    if (obj->nodesetval != NULL)
343277851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard		xmlXPathFreeNodeSet(obj->nodesetval);
343377851710aba3a0effdc6af67ea4caf212307420cDaniel Veillard	}
34343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
34353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (obj->type == XPATH_LOCATIONSET) {
34363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (obj->user != NULL)
34373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPtrFreeLocationSet(obj->user);
34383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
34393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (obj->type == XPATH_STRING) {
34403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (obj->stringval != NULL)
34413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(obj->stringval);
34423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
34433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
34443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(obj);
34453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
34463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3447ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3448ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/************************************************************************
3449ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *									*
3450ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *			Type Casting Routines				*
3451ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *									*
3452ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard ************************************************************************/
3453ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3454ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3455ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastBooleanToString:
3456ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a boolean
3457ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3458ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a boolean to its string value.
3459ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3460ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3461ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3462ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3463ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastBooleanToString (int val) {
3464ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret;
3465ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val)
3466ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "true");
3467ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    else
3468ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "false");
3469ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3470ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3471ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3472ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3473ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNumberToString:
3474ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a number
3475ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3476ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a number to its string value.
3477ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3478ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3479ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3480ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3481ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNumberToString (double val) {
3482ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret;
3483cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    switch (xmlXPathIsInf(val)) {
3484ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case 1:
34855fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	ret = xmlStrdup((const xmlChar *) "Infinity");
3486ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3487ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case -1:
3488ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlStrdup((const xmlChar *) "-Infinity");
3489ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3490ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    default:
3491cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(val)) {
3492ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "NaN");
3493d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	} else if (val == 0 && xmlXPathGetSign(val) != 0) {
3494d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "0");
3495ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	} else {
3496ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    /* could be improved */
3497ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    char buf[100];
3498ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlXPathFormatNumber(val, buf, 100);
3499ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) buf);
3500ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	}
3501ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3502ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3503ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3504ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3505ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3506ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeToString:
3507ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @node:  a node
3508ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3509ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node to its string value.
3510ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3511ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3512ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3513ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3514ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeToString (xmlNodePtr node) {
3515ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlNodeGetContent(node));
3516ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3517ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3518ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3519ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToString:
3520ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3521ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3522ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its string value.
3523ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3524ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a newly allocated string.
3525ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3526ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3527ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
3528ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
3529ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlStrdup((const xmlChar *) ""));
3530ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3531ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathNodeSetSort(ns);
3532ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathCastNodeToString(ns->nodeTab[0]));
3533ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3534ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3535ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3536ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastToString:
3537ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3538ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3539ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its string() equivalent
3540ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3541ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the string value of the object, NULL in case of error.
3542cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *         A new string is allocated only if needed (@val isn't a
3543ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         string object).
3544ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3545ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlChar *
3546ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToString(xmlXPathObjectPtr val) {
3547ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ret = NULL;
3548ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3549ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3550ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlStrdup((const xmlChar *) ""));
3551ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3552ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_UNDEFINED:
3553ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3554ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "String: undefined\n");
3555ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3556ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "");
3557ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3558ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_NODESET:
35590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        case XPATH_XSLT_TREE:
3560ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastNodeSetToString(val->nodesetval);
3561ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3562ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_STRING:
35634e2df54bb17645ef0d3f28b9665b2d2dde4b47a3Daniel Veillard	    return(xmlStrdup(val->stringval));
3564ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        case XPATH_BOOLEAN:
3565ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastBooleanToString(val->boolval);
3566ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3567ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_NUMBER: {
3568ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlXPathCastNumberToString(val->floatval);
3569ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3570ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	}
3571ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_USERS:
3572ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_POINT:
3573ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_RANGE:
3574ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	case XPATH_LOCATIONSET:
3575ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    TODO
3576ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    ret = xmlStrdup((const xmlChar *) "");
3577ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    break;
3578ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3579ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3580ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3581ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3582ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3583ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertString:
3584ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3585ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3586ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its string() equivalent
3587ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3588ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3589ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3590ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3591ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3592ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertString(xmlXPathObjectPtr val) {
3593ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *res = NULL;
3594ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3595ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3596ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewCString(""));
3597ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3598ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3599ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3600ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3601ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "STRING: undefined\n");
3602ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3603ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3604ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
36050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
3606ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastNodeSetToString(val->nodesetval);
3607ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3608ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3609ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3610ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3611ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastBooleanToString(val->boolval);
3612ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3613ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3614ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	res = xmlXPathCastNumberToString(val->floatval);
3615ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3616ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3617ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3618ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3619ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3620ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3621ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3622ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3623ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3624ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (res == NULL)
3625ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewCString(""));
3626ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathWrapString(res));
3627ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3628ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3629ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3630ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastBooleanToNumber:
3631ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a boolean
3632ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3633ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a boolean to its number value
3634ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3635ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3636ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3637ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3638ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastBooleanToNumber(int val) {
3639ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val)
3640ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(1.0);
3641ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(0.0);
3642ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3643ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3644ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3645ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastStringToNumber:
3646ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a string
3647ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3648ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a string to its number value
3649ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3650ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3651ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3652ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3653ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastStringToNumber(const xmlChar * val) {
3654ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(xmlXPathStringEvalNumber(val));
3655ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3656ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3657ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3658ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeToNumber:
3659ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @node:  a node
3660ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3661ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node to its number value
3662ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3663ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3664ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3665ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3666ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeToNumber (xmlNodePtr node) {
3667ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *strval;
3668ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret;
3669ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3670ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (node == NULL)
3671ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3672ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    strval = xmlXPathCastNodeToString(node);
3673ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (strval == NULL)
3674ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3675ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathCastStringToNumber(strval);
3676ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlFree(strval);
3677ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3678ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3679ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3680ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3681ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3682ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToNumber:
3683ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3684ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3685ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its number value
3686ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3687ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3688ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3689ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3690ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
3691ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *str;
3692ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret;
3693ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3694ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (ns == NULL)
3695ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3696ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    str = xmlXPathCastNodeSetToString(ns);
3697ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathCastStringToNumber(str);
3698ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlFree(str);
3699ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3700ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3701ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3702ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3703ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastToNumber:
3704ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3705ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3706ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an XPath object to its number value
3707ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3708ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the number value
3709ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3710ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillarddouble
3711ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToNumber(xmlXPathObjectPtr val) {
3712ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double ret = 0.0;
3713ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3714ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3715ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNAN);
3716ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3717ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3718ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEGUB_EXPR
3719ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "NUMBER: undefined\n");
3720ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3721ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNAN;
3722ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3723ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
37240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
3725ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNodeSetToNumber(val->nodesetval);
3726ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3727ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3728ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastStringToNumber(val->stringval);
3729ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3730ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3731ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = val->floatval;
3732ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3733ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3734ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastBooleanToNumber(val->boolval);
3735ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3736ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3737ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3738ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3739ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3740ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3741ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNAN;
3742ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3743ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3744ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3745ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3746ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3747ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3748ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertNumber:
3749ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3750ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3751ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its number() equivalent
3752ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3753ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3754ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3755ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3756ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3757ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertNumber(xmlXPathObjectPtr val) {
3758ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3759ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3760ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3761ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewFloat(0.0));
3762ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val->type == XPATH_NUMBER)
3763ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3764ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
3765ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3766ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3767ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3768ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3769ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3770ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNumberToBoolean:
3771ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a number
3772ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3773ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a number to its boolean value
3774ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3775ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3776ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3777ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3778ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNumberToBoolean (double val) {
3779cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard     if (xmlXPathIsNaN(val) || (val == 0.0))
3780ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	 return(0);
3781ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard     return(1);
3782ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3783ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3784ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3785ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastStringToBoolean:
3786ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  a string
3787ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3788ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a string to its boolean value
3789ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3790ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3791ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3792ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3793ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastStringToBoolean (const xmlChar *val) {
3794ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((val == NULL) || (xmlStrlen(val) == 0))
3795ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3796ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(1);
3797ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3798ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3799ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3800ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathCastNodeSetToBoolean:
3801ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ns:  a node-set
3802ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3803ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts a node-set to its boolean value
3804ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3805ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3806ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3807ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3808ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
3809ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if ((ns == NULL) || (ns->nodeNr == 0))
3810ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3811ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(1);
3812ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3813ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3814ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
38155e2dace1ca6fbb023d1ce848d4e98deefbbfec31Daniel Veillard * xmlXPathCastToBoolean:
3816ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3817ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3818ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an XPath object to its boolean value
3819ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3820ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the boolean value
3821ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3822ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardint
3823ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathCastToBoolean (xmlXPathObjectPtr val) {
3824ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    int ret = 0;
3825ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3826ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3827ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(0);
3828ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    switch (val->type) {
3829ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_UNDEFINED:
3830ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#ifdef DEBUG_EXPR
3831ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "BOOLEAN: undefined\n");
3832ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard#endif
3833ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = 0;
3834ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3835ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NODESET:
38360c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    case XPATH_XSLT_TREE:
3837ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
3838ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3839ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_STRING:
3840ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastStringToBoolean(val->stringval);
3841ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3842ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_NUMBER:
3843ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathCastNumberToBoolean(val->floatval);
3844ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3845ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_BOOLEAN:
3846ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = val->boolval;
3847ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3848ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_USERS:
3849ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_POINT:
3850ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_RANGE:
3851ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    case XPATH_LOCATIONSET:
3852ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	TODO;
3853ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = 0;
3854ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	break;
3855ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
3856ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3857ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3858ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3859ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3860ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
3861ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathConvertBoolean:
3862ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @val:  an XPath object
3863ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3864ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Converts an existing object to its boolean() equivalent
3865ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
3866ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns the new object, the old one is freed (or the operation
3867ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *         is done directly on @val)
3868ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
3869ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathObjectPtr
3870ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathConvertBoolean(xmlXPathObjectPtr val) {
3871ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr ret;
3872ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
3873ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val == NULL)
3874ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(xmlXPathNewBoolean(0));
3875ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (val->type == XPATH_BOOLEAN)
3876ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return(val);
3877ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
3878ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathFreeObject(val);
3879ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
3880ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
3881ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
38823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
38833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
38843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle XPath contexts			*
38853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
38863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
38873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
38883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
38893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewContext:
38903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @doc:  the XML document
38913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
38923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathContext
38933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
3894af43f63aaabf0dc4b4a070773875d0927da3d8a2Daniel Veillard * Returns the xmlXPathContext just allocated. The caller will need to free it.
38953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
38963473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathContextPtr
38973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewContext(xmlDocPtr doc) {
38983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathContextPtr ret;
38993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
39013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3902d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "creating context\n");
39033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
39043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
39053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathContext));
39063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->doc = doc;
39073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->node = NULL;
39083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->varHash = NULL;
39103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nb_types = 0;
39123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->max_types = 0;
39133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->types = NULL;
39143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->funcHash = xmlHashCreate(0);
39163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nb_axis = 0;
39183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->max_axis = 0;
39193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->axis = NULL;
39203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->nsHash = NULL;
39223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->user = NULL;
39233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->contextSize = -1;
39253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->proximityPosition = -1;
39263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterAllFunctions(ret);
39283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
39303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
39313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
39333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeContext:
39343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the context to free
39353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathContext
39373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
39383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
39393473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeContext(xmlXPathContextPtr ctxt) {
39407eca35fbaef6bd06074c4b978d381303609fcb0bDaniel Veillard    if (ctxt == NULL) return;
39417eca35fbaef6bd06074c4b978d381303609fcb0bDaniel Veillard
39423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredNsCleanup(ctxt);
39433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredFuncsCleanup(ctxt);
39443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisteredVariablesCleanup(ctxt);
39457eca35fbaef6bd06074c4b978d381303609fcb0bDaniel Veillard    xmlResetError(&ctxt->lastError);
39463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
39473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
39483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
39503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
39513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		Routines to handle XPath parser contexts		*
39523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
39533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
39543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CHECK_CTXT(ctxt)						\
39563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt == NULL) { 						\
3957f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack	__xmlRaiseError(NULL, NULL, NULL,				\
3958f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		NULL, NULL, XML_FROM_XPATH,				\
3959f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		XML_ERR_INTERNAL_ERROR, XML_ERR_FATAL,			\
3960f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		__FILE__, __LINE__,					\
3961f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		NULL, NULL, NULL, 0, 0,					\
3962f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack		"NULL context pointer\n");				\
3963f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack	return(NULL);							\
39643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }									\
39653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define CHECK_CONTEXT(ctxt)						\
396857b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard    if ((ctxt == NULL) || (ctxt->doc == NULL) ||			\
396957b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard        (ctxt->doc->children == NULL)) { 				\
397057b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_INVALID_CTXT);	\
3971ce682bc24b79f1dd29b781d4c17f9bf169ce7e32Daniel Veillard	return(NULL);							\
397257b2516af5e2e06c54750b6549723cf5b8edf8a4Daniel Veillard    }
39733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
39763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNewParserContext:
39773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
39783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
39793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Create a new xmlXPathParserContext
39813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
39823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathParserContext just allocated.
39833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
39843473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParserContextPtr
39853473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
39863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr ret;
39873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
39893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) {
3990d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(ctxt, "creating parser context\n");
39913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
39923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
39933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
39943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->cur = ret->base = str;
39953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->context = ctxt;
39963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
39979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret->comp = xmlXPathNewCompExpr();
39989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret->comp == NULL) {
39999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret->valueTab);
40009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret);
40019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
40029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
40034773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if ((ctxt != NULL) && (ctxt->dict != NULL)) {
40044773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        ret->comp->dict = ctxt->dict;
40054773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	xmlDictReference(ret->comp->dict);
40064773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    }
40079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
40089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(ret);
40099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
40109e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
40119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
40129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompParserContext:
40139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the XPath compiled expression
40149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctxt:  the XPath context
40159e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
40169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Create a new xmlXPathParserContext when processing a compiled expression
40179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
40189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Returns the xmlXPathParserContext just allocated.
40199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
402056a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathParserContextPtr
40219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
40229e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathParserContextPtr ret;
40239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
40249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
40259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret == NULL) {
4026d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(ctxt, "creating evaluation context\n");
40279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
40289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
40299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    memset(ret, 0 , (size_t) sizeof(xmlXPathParserContext));
40309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
40313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Allocate the value stack */
40323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueTab = (xmlXPathObjectPtr *)
40333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                     xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
40349e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ret->valueTab == NULL) {
40359e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlFree(ret);
4036d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	xmlXPathErrMemory(ctxt, "creating evaluation context\n");
40379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
40389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
40393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueNr = 0;
40403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->valueMax = 10;
40413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret->value = NULL;
40429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
4043fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    ret->context = ctxt;
40449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ret->comp = comp;
40459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
40463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
40473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
40483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
40503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFreeParserContext:
40513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the context to free
40523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
40533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Free up an xmlXPathParserContext
40543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
40553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
40563473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
40573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->valueTab != NULL) {
40583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlFree(ctxt->valueTab);
40593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
406056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (ctxt->comp != NULL) {
406156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
406256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ctxt->comp->stream != NULL) {
406356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    xmlFreePatternList(ctxt->comp->stream);
406456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    ctxt->comp->stream = NULL;
406556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
406656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
40679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathFreeCompExpr(ctxt->comp);
406856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
40693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ctxt);
40703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
40713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
40733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
40743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		The implicit core function library			*
40753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
40763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
40773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
40783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
407901c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathNodeValHash:
4080f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @node:  a node pointer
4081f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4082f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Function computing the beginning of the string value of the node,
4083f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * used to speed up comparisons
4084f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4085f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns an int usable as a hash
4086f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
4087f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic unsigned int
4088f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNodeValHash(xmlNodePtr node) {
4089f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int len = 2;
4090f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar * string = NULL;
4091f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr tmp = NULL;
4092f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int ret = 0;
4093f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4094f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (node == NULL)
4095f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4096f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
40979adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard    if (node->type == XML_DOCUMENT_NODE) {
40989adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	tmp = xmlDocGetRootElement((xmlDocPtr) node);
40999adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	if (tmp == NULL)
41009adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    node = node->children;
41019adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	else
41029adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    node = tmp;
41039adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard
41049adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	if (node == NULL)
41059adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    return(0);
41069adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard    }
4107f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4108f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (node->type) {
4109f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_COMMENT_NODE:
4110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_PI_NODE:
4111f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_CDATA_SECTION_NODE:
4112f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_TEXT_NODE:
4113f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    string = node->content;
4114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string == NULL)
4115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
4116f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
4117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
4118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(((unsigned int) string[0]) +
4119f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		   (((unsigned int) string[1]) << 8));
4120f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_NAMESPACE_DECL:
4121f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    string = ((xmlNsPtr)node)->href;
4122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string == NULL)
4123f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
4124f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[0] == 0)
4125f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(0);
4126f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(((unsigned int) string[0]) +
4127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		   (((unsigned int) string[1]) << 8));
4128f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_ATTRIBUTE_NODE:
4129f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = ((xmlAttrPtr) node)->children;
4130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
4131f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	case XML_ELEMENT_NODE:
4132f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = node->children;
4133f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
4134f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	default:
4135f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(0);
4136f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
4137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (tmp != NULL) {
4138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	switch (tmp->type) {
4139f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_COMMENT_NODE:
4140f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_PI_NODE:
4141f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_CDATA_SECTION_NODE:
4142f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_TEXT_NODE:
4143f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		string = tmp->content;
4144f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4145f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    case XML_NAMESPACE_DECL:
4146f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		string = ((xmlNsPtr)tmp)->href;
4147f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    default:
4149f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4150f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4151f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if ((string != NULL) && (string[0] != 0)) {
4152f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (len == 1) {
4153f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(ret + (((unsigned int) string[0]) << 8));
4154f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4155f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (string[1] == 0) {
4156f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		len = 1;
4157f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		ret = (unsigned int) string[0];
4158f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    } else {
4159f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		return(((unsigned int) string[0]) +
4160f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		       (((unsigned int) string[1]) << 8));
4161f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4162f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4163f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	/*
4164f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	 * Skip to next node
4165f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	 */
4166f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if ((tmp->children != NULL) && (tmp->type != XML_DTD_NODE)) {
4167f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp->children->type != XML_ENTITY_DECL) {
4168f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = tmp->children;
4169f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		continue;
4170f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4171f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4172f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (tmp == node)
4173f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    break;
4174f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4175f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (tmp->next != NULL) {
4176f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = tmp->next;
4177f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    continue;
4178f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	}
4179f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4180f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	do {
4181f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    tmp = tmp->parent;
4182f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp == NULL)
4183f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4184f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp == node) {
4185f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = NULL;
4186f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4188f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (tmp->next != NULL) {
4189f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		tmp = tmp->next;
4190f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
4191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
4192f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	} while (tmp != NULL);
4193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
4194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(ret);
4195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
4196f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4197f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
4198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathStringHash:
4199f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @string:  a string
4200f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4201f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Function computing the beginning of the string value of the node,
4202f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * used to speed up comparisons
4203f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
4204f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns an int usable as a hash
4205f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
4206f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic unsigned int
4207f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathStringHash(const xmlChar * string) {
4208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (string == NULL)
4209f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return((unsigned int) 0);
4210f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (string[0] == 0)
4211f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(((unsigned int) string[0]) +
4213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	   (((unsigned int) string[1]) << 8));
4214f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
4215f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
4216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
42173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetFloat:
42183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
42193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
42203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
42213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
42223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the value
42233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a number
42253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
42263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
42273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
42283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
42293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a number,
42313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in the
42323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node-set such that the result of performing the comparison on the number
42333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be compared and on the result of converting the string-value of that
42343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node to a number using the number function is true.
42353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
42373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
423856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
42393473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
42403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr f) {
42413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, ret = 0;
42423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
42433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
42443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((f == NULL) || (arg == NULL) ||
42463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
42473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg);
42483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(f);
42493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
42503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
42513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4252911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (ns != NULL) {
4253911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < ns->nodeNr;i++) {
4254ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
4255911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     if (str2 != NULL) {
4256911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt,
4257911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard			   xmlXPathNewString(str2));
4258911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlFree(str2);
4259911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlXPathNumberFunction(ctxt, 1);
4260911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt, xmlXPathObjectCopy(f));
4261911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 ret = xmlXPathCompareValues(ctxt, inf, strict);
4262911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 if (ret)
4263911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		     break;
4264911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     }
4265911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
42663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
42673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
42683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(f);
42693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
42703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
42713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
42723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
42733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetString:
42743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
42753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
42763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
42773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
42783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @s:  the value
42793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a string
42813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
42823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
42833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
42843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
42853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a string,
42873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
42883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
42893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string-value of the node and the other string is true.
42903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
42913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
42923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
429356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
42943473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
42953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr s) {
42963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, ret = 0;
42973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
42983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
42993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((s == NULL) || (arg == NULL) ||
43013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
43023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg);
43033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(s);
43043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
43053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
43063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4307911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if (ns != NULL) {
4308911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	for (i = 0;i < ns->nodeNr;i++) {
4309ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
4310911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     if (str2 != NULL) {
4311911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt,
4312911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard			   xmlXPathNewString(str2));
4313911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 xmlFree(str2);
4314911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 valuePush(ctxt, xmlXPathObjectCopy(s));
4315911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 ret = xmlXPathCompareValues(ctxt, inf, strict);
4316911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		 if (ret)
4317911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		     break;
4318911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	     }
4319911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	}
43203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
43213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
43223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(s);
43233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
43243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
43253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
43273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSets:
4328ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @inf:  less than (1) or greater than (0)
43293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
4330cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @arg1:  the first node set object
43313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg2:  the second node set object
43323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation on nodesets:
43343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If both objects to be compared are node-sets, then the comparison
43363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if there is a node in the first node-set
43373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and a node in the second node-set such that the result of performing
43383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the comparison on the string-values of the two nodes is true.
43393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ....
43403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * When neither object to be compared is a node-set and the operator
43413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is <=, <, >= or >, then the objects are compared by converting both
43423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * objects to numbers and comparing the numbers according to IEEE 754.
43433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ....
43443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The number function converts its argument to a number as follows:
43453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - a string that consists of optional whitespace followed by an
43463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    optional minus sign followed by a Number followed by whitespace
43473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    is converted to the IEEE 754 number that is nearest (according
43483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    to the IEEE 754 round-to-nearest rule) to the mathematical value
43493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    represented by the string; any other string is converted to NaN
43503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
43513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Conclusion all nodes need to be converted first to their string value
43523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and then the comparison must be done when possible
43533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
435456a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
435556a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel VeillardxmlXPathCompareNodeSets(int inf, int strict,
43563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
43573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, j, init = 0;
43583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val1;
43593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double *values2;
43603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
43613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns1;
43623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns2;
43633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg1 == NULL) ||
43654dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) {
43664dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
43673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
43684dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
43693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2 == NULL) ||
43704dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) {
43714dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
43724dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
43733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
43744dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
43753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns1 = arg1->nodesetval;
43773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns2 = arg2->nodesetval;
43783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4379d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
43804dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
43814dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
43823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
43834dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
4384d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
43854dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
43864dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
43873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
43884dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    }
43893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
43903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
43913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values2 == NULL) {
4392d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
43934dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg1);
43944dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard	xmlXPathFreeObject(arg2);
43953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
43963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
43973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++) {
4398ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	val1 = xmlXPathCastNodeToNumber(ns1->nodeTab[i]);
4399cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	if (xmlXPathIsNaN(val1))
44003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    continue;
44013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++) {
44023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (init == 0) {
4403ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		values2[j] = xmlXPathCastNodeToNumber(ns2->nodeTab[j]);
44043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
4405cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	    if (xmlXPathIsNaN(values2[j]))
44063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		continue;
44073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (inf && strict)
44083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 < values2[j]);
44093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (inf && !strict)
44103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 <= values2[j]);
44113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (!inf && strict)
44123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 > values2[j]);
44133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else if (!inf && !strict)
44143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = (val1 >= values2[j]);
44153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ret)
44163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		break;
44173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
44183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret)
44193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
44203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	init = 1;
44213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
44223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values2);
44234dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    xmlXPathFreeObject(arg1);
44244dd9346df228ff478e8cbe38bee270d56a609676Daniel Veillard    xmlXPathFreeObject(arg2);
44253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
44263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
44273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
44293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareNodeSetValue:
44303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
44313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
44323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
44333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the node set
44343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @val:  the value
44353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
44363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation between a nodeset and a value
44373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns < @val    (1, 1, ...
44383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns <= @val   (1, 0, ...
44393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns > @val    (0, 1, ...
44403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @ns >= @val   (0, 0, ...
44413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
44423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a boolean,
44433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if the result of performing
44443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the comparison on the boolean and on the result of converting
44453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set to a boolean using the boolean function is true.
44463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
44473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
44483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
444956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
44503473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
44513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr val) {
44523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((val == NULL) || (arg == NULL) ||
44533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
44543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
44553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch(val->type) {
44573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
44583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
44593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NODESET:
44603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_XSLT_TREE:
446156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    return(xmlXPathCompareNodeSets(inf, strict, arg, val));
44623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
44633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
44643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
44653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, arg);
44663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathBooleanFunction(ctxt, 1);
44673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, val);
44683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathCompareValues(ctxt, inf, strict));
44693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
44703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    TODO
44713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
44723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
44733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
44743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
447601c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSetString:
44773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the nodeset object argument
44783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the string to compare to.
44790c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:  flag to show whether for '=' (0) or '!=' (1)
44803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
44813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
44823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a string,
44833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
44843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
44853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string-value of the node and the other string is true.
44863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
44873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
44883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
448956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
44900c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSetString(xmlXPathObjectPtr arg, const xmlChar * str, int neq)
4491f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
44923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
44933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns;
44943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *str2;
4495f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int hash;
44963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
44973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((str == NULL) || (arg == NULL) ||
4498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
4499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return (0);
45003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns = arg->nodesetval;
4501c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack    /*
4502c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack     * A NULL nodeset compared with a string is always false
4503c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack     * (since there is no node equal, and no node not equal)
4504c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack     */
4505c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack    if ((ns == NULL) || (ns->nodeNr <= 0) )
4506f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return (0);
4507c125a721a4b7856f5356334137d467f95e6bf4b2William M. Brack    hash = xmlXPathStringHash(str);
4508f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < ns->nodeNr; i++) {
4509f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
4510f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            str2 = xmlNodeGetContent(ns->nodeTab[i]);
4511f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((str2 != NULL) && (xmlStrEqual(str, str2))) {
4512f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(str2);
45130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (neq)
45140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    continue;
4515f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (1);
45169adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard	    } else if ((str2 == NULL) && (xmlStrEqual(str, BAD_CAST ""))) {
45179adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		if (neq)
45189adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard		    continue;
45199adc0469d4691e798ea4ad59b84c874cdea8b38dDaniel Veillard                return (1);
45200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack            } else if (neq) {
45210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (str2 != NULL)
45220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    xmlFree(str2);
45230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		return (1);
45240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
4525f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (str2 != NULL)
4526f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlFree(str2);
45270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        } else if (neq)
45280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    return (1);
45293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4530f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (0);
45313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
45323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
453401c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSetFloat:
45353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg:  the nodeset object argument
45363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @f:  the float to compare to
45370c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:  flag to show whether to compare '=' (0) or '!=' (1)
45383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the equal operation on XPath objects content: @arg1 == @arg2
45403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If one object to be compared is a node-set and the other is a number,
45413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the comparison will be true if and only if there is a node in
45423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the node-set such that the result of performing the comparison on the
45433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number to be compared and on the result of converting the string-value
45443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of that node to a number using the number function is true.
45453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
45473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
454856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
45490c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
45500c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg, double f, int neq) {
45510c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  int i, ret=0;
45520c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlNodeSetPtr ns;
45530c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlChar *str2;
45540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlXPathObjectPtr val;
45550c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  double v;
45563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg == NULL) ||
45583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
45593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
45603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45610c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    ns = arg->nodesetval;
45620c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (ns != NULL) {
45630c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	for (i=0;i<ns->nodeNr;i++) {
45640c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
45650c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (str2 != NULL) {
45660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		valuePush(ctxt, xmlXPathNewString(str2));
45670c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlFree(str2);
45680c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlXPathNumberFunction(ctxt, 1);
45690c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		val = valuePop(ctxt);
45700c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		v = val->floatval;
45710c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlXPathFreeObject(val);
45720c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (!xmlXPathIsNaN(v)) {
45730c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    if ((!neq) && (v==f)) {
45740c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			ret = 1;
45750c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			break;
45760c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    } else if ((neq) && (v!=f)) {
45770c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			ret = 1;
45780c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			break;
45790c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    }
45800c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		}
45810c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
45820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
45830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
45840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
45850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return(ret);
45863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
45873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
45893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
459001c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlXPathEqualNodeSets:
45913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg1:  first nodeset object argument
45923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @arg2:  second nodeset object argument
45930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @neq:   flag to show whether to test '=' (0) or '!=' (1)
45943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
45950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal / not equal operation on XPath nodesets:
45960c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @arg1 == @arg2  or  @arg1 != @arg2
45973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If both objects to be compared are node-sets, then the comparison
45983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if there is a node in the first node-set and
45993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * a node in the second node-set such that the result of performing the
46003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * comparison on the string-values of the two nodes is true.
46013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
46023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (needless to say, this is a costly operation)
46033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
46043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 0 or 1 depending on the results of the test.
46053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
460656a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic int
46070c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualNodeSets(xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2, int neq) {
46083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i, j;
4609f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int *hashs1;
4610f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    unsigned int *hashs2;
46113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar **values1;
46123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar **values2;
46133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
46143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns1;
46153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNodeSetPtr ns2;
46163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg1 == NULL) ||
46183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)))
46193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
46203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((arg2 == NULL) ||
46213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE)))
46223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(0);
46233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns1 = arg1->nodesetval;
46253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ns2 = arg2->nodesetval;
46263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
4627911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((ns1 == NULL) || (ns1->nodeNr <= 0))
46283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
4629911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((ns2 == NULL) || (ns2->nodeNr <= 0))
46303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
46313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
46330c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     * for equal, check if there is a node pertaining to both sets
46343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
46350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (neq == 0)
46360c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	for (i = 0;i < ns1->nodeNr;i++)
46370c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    for (j = 0;j < ns2->nodeNr;j++)
46380c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (ns1->nodeTab[i] == ns2->nodeTab[j])
46390c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    return(1);
46403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
46413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
4642d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    if (values1 == NULL) {
4643d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
46443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
4645d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard    }
4646f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
4647f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (hashs1 == NULL) {
4648d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
4649f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values1);
4650f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4651f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
46523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
46533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
46543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (values2 == NULL) {
4655d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
4656f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(hashs1);
46573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(values1);
46583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
46593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
4660f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
4661f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (hashs2 == NULL) {
4662d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard        xmlXPathErrMemory(NULL, "comparing nodesets\n");
4663f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(hashs1);
4664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values1);
4665f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	xmlFree(values2);
4666f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return(0);
4667f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
46683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *));
46693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++) {
4670f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]);
46713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	for (j = 0;j < ns2->nodeNr;j++) {
46723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (i == 0)
4673f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]);
46740c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (hashs1[i] != hashs2[j]) {
46750c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if (neq) {
46760c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
46770c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
46780c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		}
46790c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    }
46800c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    else {
4681f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (values1[i] == NULL)
4682f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
4683f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (values2[j] == NULL)
4684f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
46850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlStrEqual(values1[i], values2[j]) ^ neq;
4686f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		if (ret)
4687f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    break;
4688f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    }
46893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
46903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ret)
46913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
46923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
46933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (i = 0;i < ns1->nodeNr;i++)
46943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (values1[i] != NULL)
46953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(values1[i]);
46963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    for (j = 0;j < ns2->nodeNr;j++)
46973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (values2[j] != NULL)
46983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(values2[j]);
46993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values1);
47003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(values2);
4701f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlFree(hashs1);
4702f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlFree(hashs2);
47033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
47043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
47053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
47060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackstatic int
47070c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
47080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack  xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
47093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
47100c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
47110c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *At this point we are assured neither arg1 nor arg2
47120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *is a nodeset, so we can just pick the appropriate routine.
47130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
47143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (arg1->type) {
47153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_UNDEFINED:
47163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
47173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
47183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "Equal: undefined\n");
47193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
47203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
47213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_BOOLEAN:
47223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
47233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
47243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
47253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
47263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
47273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
47283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
47293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
47303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
47313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
47323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: %d boolean %d \n",
47333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    arg1->boolval, arg2->boolval);
47343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
47353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == arg2->boolval);
47363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
47373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
4738ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		    ret = (arg1->boolval ==
4739ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack			   xmlXPathCastNumberToBoolean(arg2->floatval));
47403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
47413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
47423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg2->stringval == NULL) ||
47433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg2->stringval[0] == 0)) ret = 0;
47443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
47453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
47463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg1->boolval == ret);
47473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
47483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
47493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
47503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
47513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
47523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
47533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
47540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
47550c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
47560c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
47573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
47583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
47593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_NUMBER:
47603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
47613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
47623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
47633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
47643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
47653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
47663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
47673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
4768ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		    ret = (arg2->boolval==
4769ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack			   xmlXPathCastNumberToBoolean(arg1->floatval));
47703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
47713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
47723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    valuePush(ctxt, arg2);
47733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlXPathNumberFunction(ctxt, 1);
47743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    arg2 = valuePop(ctxt);
47753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* no break on purpose */
47763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
4777d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    /* Hand check NaN and Infinity equalities */
4778081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    if (xmlXPathIsNaN(arg1->floatval) ||
4779081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    	    xmlXPathIsNaN(arg2->floatval)) {
478021458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = 0;
4781d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
4782d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		        if (xmlXPathIsInf(arg2->floatval) == 1)
4783d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4784d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4785d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4786d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
4787d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == -1)
4788d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4789d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4790d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4791d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
4792d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == 1)
4793d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4794d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4795d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4796d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
4797d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == -1)
4798d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4799d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4800d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
480121458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    } else {
480221458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = (arg1->floatval == arg2->floatval);
480321458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    }
48043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
48053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
48063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
48073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
48083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
48093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
48103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
48110c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
48120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
48130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
48143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
48153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
48163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_STRING:
48173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    switch (arg2->type) {
48183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        case XPATH_UNDEFINED:
48193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
48203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
48213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "Equal: undefined\n");
48223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
48233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
48243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_BOOLEAN:
48253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if ((arg1->stringval == NULL) ||
48263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			(arg1->stringval[0] == 0)) ret = 0;
48273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    else
48283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = 1;
48293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = (arg2->boolval == ret);
48303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
48313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_STRING:
48323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    ret = xmlStrEqual(arg1->stringval, arg2->stringval);
48333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
48343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_NUMBER:
48353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    valuePush(ctxt, arg1);
48363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlXPathNumberFunction(ctxt, 1);
48373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    arg1 = valuePop(ctxt);
4838d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    /* Hand check NaN and Infinity equalities */
4839081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    if (xmlXPathIsNaN(arg1->floatval) ||
4840081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    	    xmlXPathIsNaN(arg2->floatval)) {
484121458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = 0;
4842d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
4843d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == 1)
4844d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4845d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4846d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4847d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
4848d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg2->floatval) == -1)
4849d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4850d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4851d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4852d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
4853d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == 1)
4854d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4855d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4856d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
4857d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
4858d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			if (xmlXPathIsInf(arg1->floatval) == -1)
4859d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 1;
4860d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			else
4861d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard			    ret = 0;
486221458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    } else {
486321458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		        ret = (arg1->floatval == arg2->floatval);
486421458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard		    }
48653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
48663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_USERS:
48673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_POINT:
48683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_RANGE:
48693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		case XPATH_LOCATIONSET:
48703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    TODO
48713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
48720c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_NODESET:
48730c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		case XPATH_XSLT_TREE:
48740c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    break;
48753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
48763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
48773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XPATH_USERS:
48783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_POINT:
48793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_RANGE:
48803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XPATH_LOCATIONSET:
48813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    TODO
48823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
48830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	case XPATH_NODESET:
48840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	case XPATH_XSLT_TREE:
48850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    break;
48863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
48873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg1);
48883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg2);
48893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
48903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
48913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
48920c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack/**
48930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * xmlXPathEqualValues:
48940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @ctxt:  the XPath Parser context
48950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
48960c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal operation on XPath objects content: @arg1 == @arg2
48970c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
48980c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Returns 0 or 1 depending on the results of the test.
48990c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack */
49000c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackint
49010c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
49020c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg1, arg2, argtmp;
49030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    int ret = 0;
49040c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
49056128c01ca6a5c1d67970b44cd11aa95a392d8a2dDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
49060c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
49070c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg1 = valuePop(ctxt);
49080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
49090c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
49100c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
49110c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
49120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
49130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	XP_ERROR0(XPATH_INVALID_OPERAND);
49140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
49150c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
49160c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (arg1 == arg2) {
49170c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
49180c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        xmlGenericError(xmlGenericErrorContext,
49190c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		"Equal: by pointer\n");
49200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
49212c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	xmlXPathFreeObject(arg1);
49220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        return(1);
49230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
49240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
49250c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
49260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *If either argument is a nodeset, it's a 'special case'
49270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
49280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
49290c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
49300c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	/*
49310c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 *Hack it to assure arg1 is the nodeset
49320c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 */
49330c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
49340c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		argtmp = arg2;
49350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg2 = arg1;
49360c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg1 = argtmp;
49370c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
49380c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	switch (arg2->type) {
49390c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_UNDEFINED:
49400c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
49410c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlGenericError(xmlGenericErrorContext,
49420c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			"Equal: undefined\n");
49430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
49440c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
49450c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NODESET:
49460c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_XSLT_TREE:
49470c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSets(arg1, arg2, 0);
49480c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
49490c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_BOOLEAN:
49500c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if ((arg1->nodesetval == NULL) ||
49510c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		  (arg1->nodesetval->nodeNr == 0)) ret = 0;
49520c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		else
49530c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
49540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = (ret == arg2->boolval);
49550c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
49560c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NUMBER:
49570c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0);
49580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
49590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_STRING:
49600c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval, 0);
49610c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
49620c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_USERS:
49630c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_POINT:
49640c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_RANGE:
49650c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_LOCATIONSET:
49660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		TODO
49670c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
49680c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
49690c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg1);
49700c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg2);
49710c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	return(ret);
49720c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
49730c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
49740c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return (xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
49750c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack}
49760c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
49770c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack/**
49780c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * xmlXPathNotEqualValues:
49790c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * @ctxt:  the XPath Parser context
49800c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
49810c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Implement the equal operation on XPath objects content: @arg1 == @arg2
49820c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack *
49830c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack * Returns 0 or 1 depending on the results of the test.
49840c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack */
49850c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brackint
49860c022ad8234a9228288c651f5e6a9bce7efcd789William M. BrackxmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
49870c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    xmlXPathObjectPtr arg1, arg2, argtmp;
49880c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    int ret = 0;
49890c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
49906128c01ca6a5c1d67970b44cd11aa95a392d8a2dDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
49910c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
49920c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg1 = valuePop(ctxt);
49930c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
49940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
49950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
49960c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
49970c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
49980c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	XP_ERROR0(XPATH_INVALID_OPERAND);
49990c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
50000c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
50010c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if (arg1 == arg2) {
50020c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
50030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        xmlGenericError(xmlGenericErrorContext,
50040c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		"NotEqual: by pointer\n");
50050c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
50062c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	xmlXPathFreeObject(arg1);
50070c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        return(0);
50080c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
50090c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
50100c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    /*
50110c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     *If either argument is a nodeset, it's a 'special case'
50120c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack     */
50130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
50140c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
50150c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	/*
50160c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 *Hack it to assure arg1 is the nodeset
50170c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	 */
50180c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
50190c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		argtmp = arg2;
50200c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg2 = arg1;
50210c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		arg1 = argtmp;
50220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
50230c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	switch (arg2->type) {
50240c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_UNDEFINED:
50250c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#ifdef DEBUG_EXPR
50260c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		xmlGenericError(xmlGenericErrorContext,
50270c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack			"NotEqual: undefined\n");
50280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack#endif
50290c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
50300c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NODESET:
50310c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_XSLT_TREE:
50320c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSets(arg1, arg2, 1);
50330c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
50340c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_BOOLEAN:
50350c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		if ((arg1->nodesetval == NULL) ||
50360c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		  (arg1->nodesetval->nodeNr == 0)) ret = 0;
50370c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		else
50380c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		    ret = 1;
5039ef61d208503e41688f4bf86f6e9023c70e65829bWilliam M. Brack		ret = (ret != arg2->boolval);
50400c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
50410c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_NUMBER:
50420c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1);
50430c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
50440c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_STRING:
50450c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		ret = xmlXPathEqualNodeSetString(arg1, arg2->stringval,1);
50460c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
50470c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_USERS:
50480c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_POINT:
50490c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_RANGE:
50500c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    case XPATH_LOCATIONSET:
50510c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		TODO
50520c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		break;
50530c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	}
50540c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg1);
50550c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	xmlXPathFreeObject(arg2);
50560c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	return(ret);
50570c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    }
50580c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack
50590c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
50600c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack}
50613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
50633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCompareValues:
50643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
50653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @inf:  less than (1) or greater than (0)
50663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @strict:  is the comparison strict
50673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the compare operation on XPath objects:
50693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 < @arg2    (1, 1, ...
50703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 <= @arg2   (1, 0, ...
50713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 > @arg2    (0, 1, ...
50723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *     @arg1 >= @arg2   (0, 0, ...
50733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
50743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * When neither object to be compared is a node-set and the operator is
50753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * <=, <, >=, >, then the objects are compared by converted both objects
50763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to numbers and comparing the numbers according to IEEE 754. The <
50773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * comparison will be true if and only if the first number is less than the
50783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * second number. The <= comparison will be true if and only if the first
50793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number is less than or equal to the second number. The > comparison
50803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * will be true if and only if the first number is greater than the second
50813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number. The >= comparison will be true if and only if the first number
50823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is greater than or equal to the second number.
50833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5084cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if the comparison succeeded, 0 if it failed
50853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
50863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
50873473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
5088d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard    int ret = 0, arg1i = 0, arg2i = 0;
50893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg1, arg2;
50903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
50916128c01ca6a5c1d67970b44cd11aa95a392d8a2dDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
50920c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    arg2 = valuePop(ctxt);
50933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    arg1 = valuePop(ctxt);
50940c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg1 == NULL) || (arg2 == NULL)) {
50950c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (arg1 != NULL)
50960c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg1);
50970c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	else
50980c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    xmlXPathFreeObject(arg2);
50993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
51003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51020c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
51030c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack      (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
5104d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	/*
5105d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	 * If either argument is a XPATH_NODESET or XPATH_XSLT_TREE the two arguments
5106d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	 * are not freed from within this routine; they will be freed from the
5107d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	 * called routine, e.g. xmlXPathCompareNodeSets or xmlXPathCompareNodeSetValue
5108d6e347e865b473f06fd431be926183c77596194aWilliam M. Brack	 */
51090c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) &&
51100c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	  ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){
511156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    ret = xmlXPathCompareNodeSets(inf, strict, arg1, arg2);
51123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
51130c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
51144af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard		ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
51154af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard			                          arg1, arg2);
51163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else {
51174af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard		ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict,
51184af6b6e801346d1c832cf19b7c3833a831871db2Daniel Veillard			                          arg2, arg1);
51193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
51203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
51213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(ret);
51223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1->type != XPATH_NUMBER) {
51253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, arg1);
51263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathNumberFunction(ctxt, 1);
51273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	arg1 = valuePop(ctxt);
51283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg1->type != XPATH_NUMBER) {
51303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
51313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
51323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
51333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2->type != XPATH_NUMBER) {
51353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, arg2);
51363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathNumberFunction(ctxt, 1);
51373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	arg2 = valuePop(ctxt);
51383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (arg2->type != XPATH_NUMBER) {
51403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg1);
51413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(arg2);
51423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_INVALID_OPERAND);
51433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
51443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
51453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Add tests for infinity and nan
51463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * => feedback on 3.4 for Inf and NaN
51473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
5148d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard    /* Hand check NaN and Infinity comparisons */
514921458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
5150d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	ret=0;
515121458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    } else {
5152d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	arg1i=xmlXPathIsInf(arg1->floatval);
5153d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	arg2i=xmlXPathIsInf(arg2->floatval);
5154d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	if (inf && strict) {
5155d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if ((arg1i == -1 && arg2i != -1) ||
5156d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		(arg2i == 1 && arg1i != 1)) {
5157d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
5158d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
5159d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval < arg2->floatval);
5160d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
5161d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
5162d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
5163d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
5164d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (inf && !strict) {
5165d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if (arg1i == -1 || arg2i == 1) {
5166d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
5167d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
5168d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval <= arg2->floatval);
5169d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
5170d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
5171d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
5172d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
5173d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (!inf && strict) {
5174d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if ((arg1i == 1 && arg2i != 1) ||
5175d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		(arg2i == -1 && arg1i != -1)) {
5176d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
5177d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
5178d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval > arg2->floatval);
5179d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
5180d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
5181d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
5182d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
5183d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	else if (!inf && !strict) {
5184d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    if (arg1i == 1 || arg2i == -1) {
5185d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 1;
5186d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else if (arg1i == 0 && arg2i == 0) {
5187d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = (arg1->floatval >= arg2->floatval);
5188d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    } else {
5189d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard		ret = 0;
5190d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	    }
5191d30be4add765e2c16840c4f2aab25f447384c7b2Daniel Veillard	}
519221458c85e209cd2621ac3eadfee075ae2dc0121dDaniel Veillard    }
51933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg1);
51943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg2);
51953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
51963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
51973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
51983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
51993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathValueFlipSign:
52003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the unary - operation on an XPath object
52033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
52043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
52053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
52073473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
5208a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return;
5209ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5210ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5211eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (xmlXPathIsNaN(ctxt->value->floatval))
5212eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathNAN;
5213eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (xmlXPathIsInf(ctxt->value->floatval) == 1)
5214eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathNINF;
5215eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (xmlXPathIsInf(ctxt->value->floatval) == -1)
5216eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard        ctxt->value->floatval=xmlXPathPINF;
5217eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (ctxt->value->floatval == 0) {
52185fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard        if (xmlXPathGetSign(ctxt->value->floatval) == 0)
52195fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNZERO;
52205fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else
52215fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = 0;
52225fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
52235fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else
52245fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard        ctxt->value->floatval = - ctxt->value->floatval;
52253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathAddValues:
52293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the add operation on XPath objects:
52323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
52333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
52343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
52363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
52373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
52383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
52393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5240ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5241ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5242ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5243ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
52443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
52453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5246ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5247ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5248ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval += val;
52493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubValues:
52533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
5255cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Implement the subtraction operation on XPath objects:
52563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
52573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
52583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
52603473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
52613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
52623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
52633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5264ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5265ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5266ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5267ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
52683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
52693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5270ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5271ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5272ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval -= val;
52733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
52763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathMultValues:
52773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
52783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
52793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the multiply operation on XPath objects:
52803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
52813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
52823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
52833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
52843473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
52853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
52863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
52873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5288ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5289ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5290ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5291ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
52923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
52933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5294ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5295ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5296ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ctxt->value->floatval *= val;
52973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
52983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
52993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
53003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathDivValues:
53013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
53023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the div operation on XPath objects @arg1 / @arg2:
53043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
53053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
53063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
53083473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
53093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
53103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double val;
53113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5312ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5313ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5314ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
5315ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    val = xmlXPathCastToNumber(arg);
53163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
53173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5318ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5319ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
5320eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (xmlXPathIsNaN(val) || xmlXPathIsNaN(ctxt->value->floatval))
5321eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard	ctxt->value->floatval = xmlXPathNAN;
5322eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    else if (val == 0 && xmlXPathGetSign(val) != 0) {
53235fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (ctxt->value->floatval == 0)
53245fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNAN;
53255fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else if (ctxt->value->floatval > 0)
53265fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNINF;
53275fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else if (ctxt->value->floatval < 0)
53285fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathPINF;
53295fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
53305fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else if (val == 0) {
53315f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	if (ctxt->value->floatval == 0)
53325f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathNAN;
53335f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	else if (ctxt->value->floatval > 0)
53345f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathPINF;
53355f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	else if (ctxt->value->floatval < 0)
53365f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	    ctxt->value->floatval = xmlXPathNINF;
53375f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard    } else
53385f4b5999b4eeda2ca68e6d9f54a3c534a8474b38Daniel Veillard	ctxt->value->floatval /= val;
53393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
53403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
53423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathModValues:
53433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
53443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the mod operation on XPath objects: @arg1 / @arg2
53463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The numeric operators convert their operands to numbers as if
53473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by calling the number function.
53483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
53503473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathModValues(xmlXPathParserContextPtr ctxt) {
53513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr arg;
5352fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    double arg1, arg2;
53533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5354ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    arg = valuePop(ctxt);
5355ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    if (arg == NULL)
5356ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	XP_ERROR(XPATH_INVALID_OPERAND);
53575fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    arg2 = xmlXPathCastToNumber(arg);
53583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(arg);
53593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5360ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CAST_TO_NUMBER;
5361ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    CHECK_TYPE(XPATH_NUMBER);
53625fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    arg1 = ctxt->value->floatval;
5363268fd1bc97f79b43290041cfda2287fb0b0ef2d6Daniel Veillard    if (arg2 == 0)
5364268fd1bc97f79b43290041cfda2287fb0b0ef2d6Daniel Veillard	ctxt->value->floatval = xmlXPathNAN;
53655fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    else {
5366fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	ctxt->value->floatval = fmod(arg1, arg2);
53675fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard    }
53683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
53693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
53713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
53723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		The traversal functions					*
53733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
53743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
53753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
53773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A traversal function enumerates nodes along an axis.
53783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Initially it must be called with NULL, and it indicates
53793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * termination on the axis by returning NULL.
53803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylortypedef xmlNodePtr (*xmlXPathTraversalFunction)
53823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    (xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
53833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
53843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
53853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextSelf:
53863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
53873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
53883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "self" direction
53903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The self axis contains just the context node itself
53913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
53933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
53943473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
53953473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5396a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
53973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
53983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
53993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
54003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
54013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
54033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextChild:
54043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
54053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
54063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "child" direction
54083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The child axis contains the children of the context node in document order.
54093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
54113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
54123473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
54133473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5414a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
54153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
54163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
54173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
54183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
54193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
54203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
54213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
54223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
54233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
54243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
54253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
54263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DTD_NODE:
54273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->children);
54283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
54293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
54303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
54313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5432eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5433eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
54343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
54353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(((xmlDocPtr) ctxt->context->node)->children);
54363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
54373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
54383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
54393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE:
54403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_NAMESPACE_DECL:
54413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
54423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
54433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(NULL);
54443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
54453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
54463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur->type == XML_DOCUMENT_NODE) ||
54483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        (cur->type == XML_HTML_DOCUMENT_NODE))
54493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
54503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->next);
54513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
54523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
54543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextDescendant:
54553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
54563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
54573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "descendant" direction
54593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the descendant axis contains the descendants of the context node in document
54603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * order; a descendant is a child or a child of a child and so on.
54613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
54623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
54633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
54643473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
54653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5466a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
54673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
54683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL)
54693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
54703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
54713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
54723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
54733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
54743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
54753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(ctxt->context->doc->children);
54763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->children);
54773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
54783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
5479567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    if (cur->children != NULL) {
548068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	/*
548168e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	 * Do not descend on entities declarations
548268e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	 */
548368e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    	if (cur->children->type != XML_ENTITY_DECL) {
548468e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    cur = cur->children;
548568e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    /*
548668e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	     * Skip DTDs
548768e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	     */
548868e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    if (cur->type != XML_DTD_NODE)
548968e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard		return(cur);
549068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	}
5491567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    }
5492567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard
5493567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard    if (cur == ctxt->context->node) return(NULL);
5494567e1b48e8664163894742d5674c24baa4282f9eDaniel Veillard
549568e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    while (cur->next != NULL) {
549668e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	cur = cur->next;
549768e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	if ((cur->type != XML_ENTITY_DECL) &&
549868e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    (cur->type != XML_DTD_NODE))
549968e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard	    return(cur);
550068e9e74af85ebbc30781787f247c361bc85adfa0Daniel Veillard    }
55013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
55033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
55043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == NULL) return(NULL);
55053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur == ctxt->context->node) return(NULL);
55063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (cur->next != NULL) {
55073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur = cur->next;
55083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(cur);
55093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
55103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (cur != NULL);
55113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur);
55123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextDescendantOrSelf:
55163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
55183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "descendant-or-self" direction
55203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the descendant-or-self axis contains the context node and the descendants
55213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node in document order; thus the context node is the first
55223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node on the axis, and the first child of the context node is the second node
55233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * on the axis
55243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
55263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55273473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
55283473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5529a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
55303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
55313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL)
55323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
55333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
55343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
55353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
55363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
55373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
55383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathNextDescendant(ctxt, cur));
55403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
55413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
55433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextParent:
55443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
55453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
55463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "parent" direction
55483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The parent axis contains the parent of the context node, if there is one.
55493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
55503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
55513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
55523473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
55533473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5554a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
55553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
55563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * the parent of an attribute or namespace node is the element
55573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * to which the attribute or namespace node is attached
55583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Namespace handling !!!
55593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
55603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
55613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
55623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
55633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
55643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
55653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
55663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
55673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
55683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
55693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
55703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
55713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DTD_NODE:
55723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
55733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
55743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
55753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
55763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
55773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (ctxt->context->node->parent == NULL)
55783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return((xmlNodePtr) ctxt->context->doc);
55798e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
5580652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    ((ctxt->context->node->parent->name[0] == ' ') ||
5581652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		     (xmlStrEqual(ctxt->context->node->parent->name,
5582652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard				 BAD_CAST "fake node libxslt"))))
55838e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		    return(NULL);
55843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->parent);
55853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE: {
55863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
55873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
55883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(att->parent);
55893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
55903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
55913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
55923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
55933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5594eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5595eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
55963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
55973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5598044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    case XML_NAMESPACE_DECL: {
5599044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5600044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
5601044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns->next != NULL) &&
5602044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (ns->next->type != XML_NAMESPACE_DECL))
5603044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return((xmlNodePtr) ns->next);
56043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5605044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
56063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
56073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
56083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
56093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
56103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
56113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
56123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAncestor:
56133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
56143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
56153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "ancestor" direction
56173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the ancestor axis contains the ancestors of the context node; the ancestors
56183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node consist of the parent of context node and the parent's
56193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent and so on; the nodes are ordered in reverse document order; thus the
56203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent is the first node on the axis, and the parent's parent is the second
56213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node on the axis
56223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
56233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
56243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
56253473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
56263473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5627a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
56283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
56293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * the parent of an attribute or namespace node is the element
56303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * to which the attribute or namespace node is attached
56313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * !!!!!!!!!!!!!
56323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
56333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
56343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) return(NULL);
56353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (ctxt->context->node->type) {
56363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ELEMENT_NODE:
56373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_TEXT_NODE:
56383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_CDATA_SECTION_NODE:
56393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_REF_NODE:
56403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ENTITY_NODE:
56413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_PI_NODE:
56423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_COMMENT_NODE:
56433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_DTD_NODE:
56443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ELEMENT_DECL:
56453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ATTRIBUTE_DECL:
56463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_ENTITY_DECL:
56473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_NOTATION_NODE:
56483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_START:
56493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    case XML_XINCLUDE_END:
56503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (ctxt->context->node->parent == NULL)
56513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    return((xmlNodePtr) ctxt->context->doc);
56528e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
5653652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    ((ctxt->context->node->parent->name[0] == ' ') ||
5654652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		     (xmlStrEqual(ctxt->context->node->parent->name,
5655652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard				 BAD_CAST "fake node libxslt"))))
56568e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		    return(NULL);
56573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		return(ctxt->context->node->parent);
56583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_ATTRIBUTE_NODE: {
565956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard		xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node;
56603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
566156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard		return(tmp->parent);
56623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
56633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_NODE:
56643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_TYPE_NODE:
56653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_DOCUMENT_FRAG_NODE:
56663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            case XML_HTML_DOCUMENT_NODE:
5667eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5668eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	    case XML_DOCB_DOCUMENT_NODE:
56693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
56703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5671044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    case XML_NAMESPACE_DECL: {
5672044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5673044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard
5674044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		if ((ns->next != NULL) &&
5675044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    (ns->next->type != XML_NAMESPACE_DECL))
5676044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard		    return((xmlNodePtr) ns->next);
5677081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		/* Bad, how did that namespace end up here ? */
56783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                return(NULL);
5679044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard	    }
56803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
56813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
56823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
56833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == ctxt->context->doc->children)
56843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return((xmlNodePtr) ctxt->context->doc);
56853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
56863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
56873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (cur->type) {
56883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
56893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_TEXT_NODE:
56903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_CDATA_SECTION_NODE:
56913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ENTITY_REF_NODE:
56923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ENTITY_NODE:
56933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_PI_NODE:
56943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_COMMENT_NODE:
56953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_NOTATION_NODE:
56963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DTD_NODE:
56973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ELEMENT_DECL:
56983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ATTRIBUTE_DECL:
56993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        case XML_ENTITY_DECL:
57003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_XINCLUDE_START:
57013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_XINCLUDE_END:
57028e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard	    if (cur->parent == NULL)
57038e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		return(NULL);
57048e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard	    if ((cur->parent->type == XML_ELEMENT_NODE) &&
5705652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		((cur->parent->name[0] == ' ') ||
5706652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		 (xmlStrEqual(cur->parent->name,
5707652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard			      BAD_CAST "fake node libxslt"))))
57088e7e1c00ce5cc3ce959833b888c50ed9fd9d5aaeDaniel Veillard		return(NULL);
57093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(cur->parent);
57103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE: {
57113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
57123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(att->parent);
57143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
5715dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	case XML_NAMESPACE_DECL: {
5716dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
5717dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin
5718dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	    if ((ns->next != NULL) &&
5719dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	        (ns->next->type != XML_NAMESPACE_DECL))
5720dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	        return((xmlNodePtr) ns->next);
5721081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    /* Bad, how did that namespace end up here ? */
5722dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin            return(NULL);
5723dffd5c8dbc7b9052db7ae69dce419a96e22acc68Aleksey Sanin	}
57243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_NODE:
57253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_TYPE_NODE:
57263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_DOCUMENT_FRAG_NODE:
57273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_HTML_DOCUMENT_NODE:
5728eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
5729eae522a0d8aa9f830d2e447f29b504030dbb6bbdDaniel Veillard	case XML_DOCB_DOCUMENT_NODE:
57303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
57313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
57323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
57333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(NULL);
57343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAncestorOrSelf:
57383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
57403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "ancestor-or-self" direction
57423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * he ancestor-or-self axis contains the context node and ancestors of
57433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node in reverse document order; thus the context node is
57443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the first node on the axis, and the context node's parent the second;
57453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parent here is defined the same as with the parent axis.
57463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
57483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57493473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
57503473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5751a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
57523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
57533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node);
57543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xmlXPathNextAncestor(ctxt, cur));
57553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextFollowingSibling:
57593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
57613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "following-sibling" direction
57633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The following-sibling axis contains the following siblings of the context
57643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node in document order.
57653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
57673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57683473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
57693473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5770a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
57713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
57723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->context->node->type == XML_NAMESPACE_DECL))
57733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
57743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
57753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
57763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
57773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->next);
57783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->next);
57793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
57803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
57813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
57823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextPrecedingSibling:
57833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
57843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
57853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "preceding-sibling" direction
57873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The preceding-sibling axis contains the preceding siblings of the context
57883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node in reverse document order; the first preceding sibling is first on the
57893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * axis; the sibling preceding that node is the second on the axis and so on.
57903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
57913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
57923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
57933473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
57943473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5795a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
57963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
57973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->context->node->type == XML_NAMESPACE_DECL))
57983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
57993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == (xmlNodePtr) ctxt->context->doc)
58003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(NULL);
58013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
58023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(ctxt->context->node->prev);
5803f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
5804f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
5805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (cur == NULL)
5806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    return(ctxt->context->node->prev);
5807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
58083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur->prev);
58093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
58103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
58123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextFollowing:
58133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
58143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
58153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "following" direction
58173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The following axis contains all nodes in the same document as the context
58183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node that are after the context node in document order, excluding any
58193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * descendants and excluding attribute nodes and namespace nodes; the nodes
58203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * are ordered in document order
58213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
58233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
58243473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
58253473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5826a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
58273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur != NULL && cur->children != NULL)
58283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return cur->children ;
58293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) cur = ctxt->context->node;
58303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) return(NULL) ; /* ERROR */
58313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur->next != NULL) return(cur->next) ;
58323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
58333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
58343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur == NULL) return(NULL);
58353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
58363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->next != NULL) return(cur->next);
58373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (cur != NULL);
58383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(cur);
58393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
58403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
58423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsAncestor:
58433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ancestor:  the ancestor node
58443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node:  the current node
58453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Check that @ancestor is a @node's ancestor
58473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
58493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
58503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstatic int
58513473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
58523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ancestor == NULL) || (node == NULL)) return(0);
58533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* nodes need to be in the same document */
58543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ancestor->doc != node->doc) return(0);
58553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* avoid searching if ancestor or node is the root node */
58563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ancestor == (xmlNodePtr) node->doc) return(1);
58573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node == (xmlNodePtr) ancestor->doc) return(0);
58583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (node->parent != NULL) {
58593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (node->parent == ancestor)
58603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            return(1);
58613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	node = node->parent;
58623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
58633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
58643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
58653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
58673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextPreceding:
58683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
58693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current node in the traversal
58703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "preceding" direction
58723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the preceding axis contains all nodes in the same document as the context
58733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node that are before the context node in document order, excluding any
58743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ancestors and excluding attribute nodes and namespace nodes; the nodes are
58753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * ordered in reverse document order
58763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
58773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
58783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
58793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
5880f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
5881f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
5882a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
5883f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (cur == NULL)
5884f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = ctxt->context->node;
58853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL)
5886f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	return (NULL);
5887f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
5888f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
58893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
58903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (cur->prev != NULL) {
5891f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
5892f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (cur);
58933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
58943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
58953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur = cur->parent;
5896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5898f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == ctxt->context->doc->children)
5899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
59003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (xmlXPathIsAncestor(cur, ctxt->context->node));
5901f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (cur);
5902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
5903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
5904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
5905f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNextPrecedingInternal:
5906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath Parser context
5907f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @cur:  the current node in the traversal
5908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
5909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Traversal function for the "preceding" direction
5910f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * the preceding axis contains all nodes in the same document as the context
5911f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * node that are before the context node in document order, excluding any
5912f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * ancestors and excluding attribute nodes and namespace nodes; the nodes are
5913f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * ordered in reverse document order
5914f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * This is a faster implementation but internal only since it requires a
5915f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * state kept in the parser context: ctxt->ancestor.
5916f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
5917f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the next element following that axis
5918f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
5919f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic xmlNodePtr
5920f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
5921f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlNodePtr cur)
5922f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
5923a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
5924f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (cur == NULL) {
5925f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = ctxt->context->node;
5926f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
592840c22b472b3d24ecc2f5b843aa3fffad6ed5cf5eWilliam M. Brack	if (cur->type == XML_NAMESPACE_DECL)
592940c22b472b3d24ecc2f5b843aa3fffad6ed5cf5eWilliam M. Brack	    cur = (xmlNodePtr)((xmlNsPtr)cur)->next;
5930f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->ancestor = cur->parent;
5931f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
5932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
5933f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	cur = cur->prev;
5934f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (cur->prev == NULL) {
5935f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = cur->parent;
5936f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == NULL)
5937f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5938f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur == ctxt->context->doc->children)
5939f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (NULL);
5940f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (cur != ctxt->ancestor)
5941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (cur);
5942f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->ancestor = cur->parent;
5943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
5944f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    cur = cur->prev;
5945f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    while (cur->last != NULL)
5946f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = cur->last;
5947f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (cur);
59483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
59493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
59513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextNamespace:
59523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
59533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current attribute in the traversal
59543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "namespace" direction
59563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the namespace axis contains the namespace nodes of the context node;
59573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the order of nodes on this axis is implementation-defined; the axis will
59583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * be empty unless the context node is an element
59593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
596020ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard * We keep the XML namespace node at the end of the list.
596120ee8c03107e5d5724765da513d595fdaf290dceDaniel Veillard *
59623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
59633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
59643473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
59653473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
5966a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
59673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
5968fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    if (ctxt->context->tmpNsList == NULL && cur != (xmlNodePtr) xmlXPathXMLNamespace) {
59697d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard        if (ctxt->context->tmpNsList != NULL)
59707d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	    xmlFree(ctxt->context->tmpNsList);
59717d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsList =
59723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGetNsList(ctxt->context->doc, ctxt->context->node);
59737d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsNr = 0;
5974fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	if (ctxt->context->tmpNsList != NULL) {
5975fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
5976fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard		ctxt->context->tmpNsNr++;
5977fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    }
5978fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	}
5979fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return((xmlNodePtr) xmlXPathXMLNamespace);
59807d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard    }
5981fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    if (ctxt->context->tmpNsNr > 0) {
5982fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return (xmlNodePtr)ctxt->context->tmpNsList[--ctxt->context->tmpNsNr];
5983fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard    } else {
5984fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	if (ctxt->context->tmpNsList != NULL)
5985fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	    xmlFree(ctxt->context->tmpNsList);
59867d7e37919fc6c7f257769c867122d885d2aae26fDaniel Veillard	ctxt->context->tmpNsList = NULL;
5987fdc9156a753e839386d9f82b7a962f9779de862cDaniel Veillard	return(NULL);
59883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
59893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
59903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
59913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
59923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNextAttribute:
59933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
59943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @cur:  the current attribute in the traversal
59953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Traversal function for the "attribute" direction
59973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * TODO: support DTD inherited default attributes
59983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
59993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the next element following that axis
60003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
60013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlNodePtr
60023473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6003a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6004e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard    if (ctxt->context->node == NULL)
6005e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard	return(NULL);
6006e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard    if (ctxt->context->node->type != XML_ELEMENT_NODE)
6007e470df7fdd3505c6232d6498f3b8834ebfce522dDaniel Veillard	return(NULL);
60083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) {
60093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
60103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
60113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return((xmlNodePtr)ctxt->context->node->properties);
60123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
60133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return((xmlNodePtr)cur->next);
60143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
60153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
60173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
60183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		NodeTest Functions					*
60193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
60203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
60213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
60223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_FUNCTION			200
60233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6024d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
6025d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/************************************************************************
6026d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
6027d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *		Implicit tree core function library			*
6028d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
6029d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard ************************************************************************/
6030d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
60313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
6032d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathRoot:
60333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
60343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
6035d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Initialize the context to the root of the document
60363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
6037d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
6038d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathRoot(xmlXPathParserContextPtr ctxt) {
6039a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->context == NULL)) return;
6040d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ctxt->context->node = (xmlNodePtr) ctxt->context->doc;
6041d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
6042d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
60433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6044d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/************************************************************************
6045d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
6046d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *		The explicit core function library			*
6047d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib	*
6048d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *									*
6049d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard ************************************************************************/
60503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6051d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
6052d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
6053d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathLastFunction:
6054d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
6055d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @nargs:  the number of arguments
6056d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
6057d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Implement the last() XPath function
6058d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *    number last()
6059d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * The last function returns the number of nodes in the context node list.
6060d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
6061d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
6062d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6063d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    CHECK_ARITY(0);
6064d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ctxt->context->contextSize >= 0) {
6065d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) ctxt->context->contextSize));
6066d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_EXPR
6067d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlGenericError(xmlGenericErrorContext,
6068d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		"last() : %d\n", ctxt->context->contextSize);
60693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
6070d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    } else {
6071d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	XP_ERROR(XPATH_INVALID_CTXT_SIZE);
60723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6073d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
60743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6075d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
6076d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathPositionFunction:
6077d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
6078d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @nargs:  the number of arguments
6079d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
6080d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Implement the position() XPath function
6081d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *    number position()
6082d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * The position function returns the position of the context node in the
6083cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * context node list. The first position is 1, and so the last position
6084d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * will be equal to last().
6085d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
6086d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardvoid
6087d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6088d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    CHECK_ARITY(0);
6089d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (ctxt->context->proximityPosition >= 0) {
6090d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	valuePush(ctxt,
6091d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	      xmlXPathNewFloat((double) ctxt->context->proximityPosition));
6092d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_EXPR
6093d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "position() : %d\n",
6094d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		ctxt->context->proximityPosition);
60953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
6096d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    } else {
6097d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	XP_ERROR(XPATH_INVALID_CTXT_POSITION);
6098d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
6099d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
61003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
61023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCountFunction:
61033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
61043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
61053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
61063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the count() XPath function
61073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number count(node-set)
61083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
61093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
61103473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
61113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
61123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
61143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
61153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
61163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
61173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
61183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
61193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6120911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur == NULL) || (cur->nodesetval == NULL))
6121911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) 0));
61220c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    else if ((cur->type == XPATH_NODESET) || (cur->type == XPATH_XSLT_TREE)) {
6123911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	valuePush(ctxt, xmlXPathNewFloat((double) cur->nodesetval->nodeNr));
6124fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    } else {
6125fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	if ((cur->nodesetval->nodeNr != 1) ||
6126fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    (cur->nodesetval->nodeTab == NULL)) {
6127fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    valuePush(ctxt, xmlXPathNewFloat((double) 0));
6128fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	} else {
6129fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    xmlNodePtr tmp;
6130fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    int i = 0;
6131fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard
6132fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    tmp = cur->nodesetval->nodeTab[0];
6133fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    if (tmp != NULL) {
6134fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		tmp = tmp->children;
6135fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		while (tmp != NULL) {
6136fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		    tmp = tmp->next;
6137fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		    i++;
6138fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard		}
6139fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    }
6140fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	    valuePush(ctxt, xmlXPathNewFloat((double) i));
6141fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard	}
6142fe70332f7f29f146a364c73450729a8b3274daeeDaniel Veillard    }
61433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
61443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
61453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
61463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
6147ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * xmlXPathGetElementsByIds:
6148ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @doc:  the document
6149ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * @ids:  a whitespace separated list of IDs
6150ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
6151ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Selects elements by their unique ID.
6152ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard *
6153ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard * Returns a node-set of selected elements.
6154ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard */
6155ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillardstatic xmlNodeSetPtr
6156ba0b8c94acad3f8e880002b3069f074be582e893Daniel VeillardxmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
6157ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodeSetPtr ret;
6158ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    const xmlChar *cur = ids;
6159ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *ID;
6160ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlAttrPtr attr;
6161ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodePtr elem = NULL;
6162ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
61637a985a18c2fee0aa9b490792dd990b75506e3740Daniel Veillard    if (ids == NULL) return(NULL);
61647a985a18c2fee0aa9b490792dd990b75506e3740Daniel Veillard
6165ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathNodeSetCreate(NULL);
6166ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
616776e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*cur)) cur++;
6168ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    while (*cur != 0) {
616976e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((!IS_BLANK_CH(*cur)) && (*cur != 0))
6170e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	    cur++;
6171ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
6172ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard        ID = xmlStrndup(ids, cur - ids);
6173e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	if (ID != NULL) {
617468cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	    /*
617568cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * We used to check the fact that the value passed
617668cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * was an NCName, but this generated much troubles for
617768cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * me and Aleksey Sanin, people blatantly violated that
617868cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * constaint, like Visa3D spec.
617968cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     * if (xmlValidateNCName(ID, 1) == 0)
618068cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	     */
618168cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	    attr = xmlGetID(doc, ID);
618268cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard	    if (attr != NULL) {
618368cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		if (attr->type == XML_ATTRIBUTE_NODE)
618468cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		    elem = attr->parent;
618568cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		else if (attr->type == XML_ELEMENT_NODE)
618668cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		    elem = (xmlNodePtr) attr;
618768cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		else
618868cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		    elem = NULL;
618968cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		if (elem != NULL)
619068cb4b2498088cf920ed6c9490b134ce7f38909fDaniel Veillard		    xmlXPathNodeSetAdd(ret, elem);
6191e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	    }
6192ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    xmlFree(ID);
6193e209b330558d170da195acb3a7618b0048d22c9eDaniel Veillard	}
6194ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
619576e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while (IS_BLANK_CH(*cur)) cur++;
6196ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ids = cur;
6197ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    }
6198ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    return(ret);
6199ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard}
6200ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard
6201ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard/**
62023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIdFunction:
62033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
62043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
62053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
62063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the id() XPath function
62073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    node-set id(object)
62083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The id function selects elements by their unique ID
62093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set,
62103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the result is the union of the result of applying id to the
62113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string value of each of the nodes in the argument node-set. When the
62123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument to id is of any other type, the argument is converted to a
62133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string as if by a call to the string function; the string is split
62143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * into a whitespace-separated list of tokens (whitespace is any sequence
62153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of characters matching the production S); the result is a node-set
62163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * containing the elements in the same document as the context node that
62173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * have a unique ID equal to any of the tokens in the list.
62183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
62193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
62203473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6221ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlChar *tokens;
6222ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlNodeSetPtr ret;
6223ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    xmlXPathObjectPtr obj;
62243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
62263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    obj = valuePop(ctxt);
62273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
62280c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack    if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
6229ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	xmlNodeSetPtr ns;
62303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i;
62313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6232ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	ret = xmlXPathNodeSetCreate(NULL);
62333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6234911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	if (obj->nodesetval != NULL) {
6235911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
6236ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		tokens =
6237ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		    xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
6238ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
6239ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		ret = xmlXPathNodeSetMerge(ret, ns);
6240ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		xmlXPathFreeNodeSet(ns);
6241ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		if (tokens != NULL)
6242ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		    xmlFree(tokens);
6243911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard	    }
62443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
62453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(obj);
6247ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt, xmlXPathWrapNodeSet(ret));
62483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
62493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
6250ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    obj = xmlXPathConvertString(obj);
62513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6252ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    ret = xmlXPathGetElementsByIds(ctxt->context->doc, obj->stringval);
6253ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
62543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(obj);
62563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return;
62573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
62583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
62603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathLocalNameFunction:
62613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
62623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
62633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
62643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the local-name() XPath function
62653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string local-name(node-set?)
62663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The local-name function returns a string containing the local part
62673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the name of the node in the argument node-set that is first in
62683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * document order. If the node-set is empty or the first node has no
62693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * name, an empty string is returned. If the argument is omitted it
62703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
62713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
62723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
62733473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
62743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
62753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6276a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
6277a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
62783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
62793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
62803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs = 1;
62813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
62823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
62833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
62843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
62853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
62863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
62873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
62883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
62893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6290911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
62913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
62923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
62933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i = 0; /* Should be first in document order !!!!! */
62943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (cur->nodesetval->nodeTab[i]->type) {
62953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
62963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE:
62973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_PI_NODE:
6298652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	    if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
6299652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		valuePush(ctxt, xmlXPathNewCString(""));
6300652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard	    else
6301652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		valuePush(ctxt,
63023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		      xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
63033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
63043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_NAMESPACE_DECL:
63053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewString(
63063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
63073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
63083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
63093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewCString(""));
63103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
63113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
63133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
63163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNamespaceURIFunction:
63173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
63193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the namespace-uri() XPath function
63213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string namespace-uri(node-set?)
63223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The namespace-uri function returns a string containing the
63233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace URI of the expanded name of the node in the argument
63243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node-set that is first in document order. If the node-set is empty,
63253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the first node has no name, or the expanded name has no namespace
63263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * URI, an empty string is returned. If the argument is omitted it
63273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
63283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
63293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
63303473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
63313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
63323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6333a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
6334a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard
63353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
63363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
63373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs = 1;
63383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
63403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
63413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
63423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
63433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
63443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
63453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6346911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
63473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
63483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
63493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int i = 0; /* Should be first in document order !!!!! */
63503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	switch (cur->nodesetval->nodeTab[i]->type) {
63513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ELEMENT_NODE:
63523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case XML_ATTRIBUTE_NODE:
63533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (cur->nodesetval->nodeTab[i]->ns == NULL)
63543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		valuePush(ctxt, xmlXPathNewCString(""));
63553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    else
63563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		valuePush(ctxt, xmlXPathNewString(
63573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			  cur->nodesetval->nodeTab[i]->ns->href));
63583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
63593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	default:
63603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewCString(""));
63613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
63623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
63643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
63653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
63673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNameFunction:
63683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
63693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
63703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the name() XPath function
63723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string name(node-set?)
63733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The name function returns a string containing a QName representing
6374cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * the name of the node in the argument node-set that is first in document
63753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * order. The QName must represent the name with respect to the namespace
63763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * declarations in effect on the node whose name is being represented.
63773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Typically, this will be the form in which the name occurred in the XML
63783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * source. This need not be the case if there are namespace declarations
63793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in effect on the node that associate multiple prefixes with the same
63803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * namespace. However, an implementation may include information about
63813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the original prefix in its representation of nodes; in this case, an
63823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * implementation can ensure that the returned string is always the same
63833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * as the QName used in the XML source. If the argument it omitted it
63843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * defaults to the context node.
63853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Libxml keep the original prefix so the "real qualified name" used is
63863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returned.
63873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
638856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic void
63890438375d2e6be47d0179826271081ae64df94f8bDaniel VeillardxmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
63900438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard{
63913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
63923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
63940438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
63950438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        nargs = 1;
63963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
63973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
63983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
63990438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard    if ((ctxt->value == NULL) ||
64000438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        ((ctxt->value->type != XPATH_NODESET) &&
64010438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard         (ctxt->value->type != XPATH_XSLT_TREE)))
64020438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        XP_ERROR(XPATH_INVALID_TYPE);
64033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
64043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6405911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard    if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
64060438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        valuePush(ctxt, xmlXPathNewCString(""));
64073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
64080438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        int i = 0;              /* Should be first in document order !!!!! */
64093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64100438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        switch (cur->nodesetval->nodeTab[i]->type) {
64110438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            case XML_ELEMENT_NODE:
64120438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            case XML_ATTRIBUTE_NODE:
6413652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
6414652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		    valuePush(ctxt, xmlXPathNewCString(""));
6415652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
6416652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard                         (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
64170438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                    valuePush(ctxt,
6418c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		        xmlXPathNewString(cur->nodesetval->nodeTab[i]->name));
64190438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard
6420652d8a949447833405cc0805f4b7ff1179e59ed2Daniel Veillard		} else {
6421c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    xmlChar *fullname;
6422c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard
6423c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name,
6424c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard				     cur->nodesetval->nodeTab[i]->ns->prefix,
6425c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard				     NULL, 0);
6426c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    if (fullname == cur->nodesetval->nodeTab[i]->name)
6427c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard			fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
6428c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    if (fullname == NULL) {
6429c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard			XP_ERROR(XPATH_MEMORY_ERROR);
6430c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard		    }
6431c00cda8c065beba24706c9e8719f08e9de420274Daniel Veillard                    valuePush(ctxt, xmlXPathWrapString(fullname));
64320438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                }
64330438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                break;
64340438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard            default:
64350438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                valuePush(ctxt,
64360438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                          xmlXPathNewNodeSet(cur->nodesetval->nodeTab[i]));
64370438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard                xmlXPathLocalNameFunction(ctxt, 1);
64380438375d2e6be47d0179826271081ae64df94f8bDaniel Veillard        }
64393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
64403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
64413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
64423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6443fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
6444fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
64453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringFunction:
64463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
64473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
64483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
64493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the string() XPath function
64503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string string(object?)
6451081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * The string function converts an object to a string as follows:
64523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - A node-set is converted to a string by returning the value of
64533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      the node in the node-set that is first in document order.
64543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      If the node-set is empty, an empty string is returned.
64553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - A number is converted to a string as follows
64563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + NaN is converted to the string NaN
64573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + positive zero is converted to the string 0
64583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + negative zero is converted to the string 0
64593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + positive infinity is converted to the string Infinity
64603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + negative infinity is converted to the string -Infinity
64613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + if the number is an integer, the number is represented in
64623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        decimal form as a Number with no decimal point and no leading
64633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        zeros, preceded by a minus sign (-) if the number is negative
64643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      + otherwise, the number is represented in decimal form as a
64653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        Number including a decimal point with at least one digit
64663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        before the decimal point and at least one digit after the
64673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        decimal point, preceded by a minus sign (-) if the number
64683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        is negative; there must be no leading zeros before the decimal
6469cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard *        point apart possibly from the one required digit immediately
64703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        before the decimal point; beyond the one required digit
64713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        after the decimal point there must be as many, but only as
64723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        many, more digits as are needed to uniquely distinguish the
64733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *        number from all other IEEE 754 numeric values.
64743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    - The boolean false value is converted to the string false.
64753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *      The boolean true value is converted to the string true.
64763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
64773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * If the argument is omitted, it defaults to a node-set with the
64783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * context node as its only member.
64793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
64803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
64813473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
64823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
64833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6484a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
64853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
6486ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	valuePush(ctxt,
6487ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		  xmlXPathWrapString(
6488ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard			xmlXPathCastNodeToString(ctxt->context->node)));
6489ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	return;
64903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
64913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
64933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
64943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
6495fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertString(cur);
6496fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
64973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
64983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
64993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringLengthFunction:
65013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the string-length() XPath function
65053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number string-length(string?)
65063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The string-length returns the number of characters in the string
65073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (see [3.6 Strings]). If the argument is omitted, it defaults to
65083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node converted to a string, in other words the value
65093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the context node.
65103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65123473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
65143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
6516a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard        if ((ctxt == NULL) || (ctxt->context == NULL))
6517a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard	    return;
65183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) {
65193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(0));
65203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
65213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlChar *content;
65223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6523ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    content = xmlXPathCastNodeToString(ctxt->context->node);
6524e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard	    valuePush(ctxt, xmlXPathNewFloat(xmlUTF8Strlen(content)));
65253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(content);
65263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
65273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
65283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
65293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
65303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
65313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
65323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
6533e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    valuePush(ctxt, xmlXPathNewFloat(xmlUTF8Strlen(cur->stringval)));
65343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
65353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
65363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathConcatFunction:
65393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the concat() XPath function
65433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string concat(string, string, string*)
65443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The concat function returns the concatenation of its arguments.
65453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65473473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur, newobj;
65493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *tmp;
65503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6551a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
65523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs < 2) {
65533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(2);
65543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
65553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
65573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
65583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((cur == NULL) || (cur->type != XPATH_STRING)) {
65593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(cur);
65603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
65613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
65623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    nargs--;
65633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (nargs > 0) {
65653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CAST_TO_STRING;
65663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	newobj = valuePop(ctxt);
65673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((newobj == NULL) || (newobj->type != XPATH_STRING)) {
65683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(newobj);
65693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(cur);
65703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_INVALID_TYPE);
65713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
65723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	tmp = xmlStrcat(newobj->stringval, cur->stringval);
65733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	newobj->stringval = cur->stringval;
65743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur->stringval = tmp;
65753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(newobj);
65773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	nargs--;
65783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
65793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, cur);
65803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
65813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
65833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathContainsFunction:
65843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
65853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
65863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
65873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the contains() XPath function
65883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean contains(string, string)
65893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The contains function returns true if the first argument string
65903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * contains the second argument string, and otherwise returns false.
65913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
65923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
65933473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
65943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr hay, needle;
65953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
65963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(2);
65973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
65983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
65993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    needle = valuePop(ctxt);
66003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
66013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    hay = valuePop(ctxt);
66023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((hay == NULL) || (hay->type != XPATH_STRING)) {
66033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(hay);
66043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(needle);
66053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
66063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrstr(hay->stringval, needle->stringval))
66083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(1));
66093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
66103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(0));
66113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(hay);
66123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(needle);
66133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStartsWithFunction:
66173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
66183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
66193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
66203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the starts-with() XPath function
66213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean starts-with(string, string)
66223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The starts-with function returns true if the first argument string
66233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * starts with the second argument string, and otherwise returns false.
66243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
66253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
66263473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
66273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr hay, needle;
66283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int n;
66293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(2);
66313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
66323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
66333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    needle = valuePop(ctxt);
66343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
66353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    hay = valuePop(ctxt);
66363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((hay == NULL) || (hay->type != XPATH_STRING)) {
66373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(hay);
66383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(needle);
66393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
66403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    n = xmlStrlen(needle->stringval);
66423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrncmp(hay->stringval, needle->stringval, n))
66433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(0));
66443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
66453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        valuePush(ctxt, xmlXPathNewBoolean(1));
66463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(hay);
66473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(needle);
66483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
66493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
66513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringFunction:
66523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
66533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
66543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
66553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring() XPath function
66563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring(string, number, number?)
66573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring function returns the substring of the first argument
66583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * starting at the position specified in the second argument with
66593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * length specified in the third argument. For example,
66603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * substring("12345",2,3) returns "234". If the third argument is not
66613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * specified, it returns the substring starting at the position specified
66623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in the second argument and continuing to the end of the string. For
66633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * example, substring("12345",2) returns "2345".  More precisely, each
66643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character in the string (see [3.6 Strings]) is considered to have a
66653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * numeric position: the position of the first character is 1, the position
66663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of the second character is 2 and so on. The returned substring contains
66673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * those characters for which the position of the character is greater than
66683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * or equal to the second argument and, if the third argument is specified,
66693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * less than the sum of the second and third arguments; the comparisons
66703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and addition used for the above follow the standard IEEE 754 rules. Thus:
66713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 1.5, 2.6) returns "234"
66723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 0, 3) returns "12"
66733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 0 div 0, 3) returns ""
66743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", 1, 0 div 0) returns ""
66753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", -42, 1 div 0) returns "12345"
66763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  - substring("12345", -1 div 0, 1 div 0) returns ""
66773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
66783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
66793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
66803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr str, start, len;
668197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    double le=0, in;
668297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    int i, l, m;
66833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret;
66843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
66853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs < 2) {
66863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(2);
66873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
66883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs > 3) {
66893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ARITY(3);
66903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
669197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    /*
669297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     * take care of possible last (position) argument
669397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    */
66943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 3) {
66953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CAST_TO_NUMBER;
66963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_TYPE(XPATH_NUMBER);
66973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len = valuePop(ctxt);
66983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	le = len->floatval;
66993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        xmlXPathFreeObject(len);
67003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
670197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
67023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
67033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
67043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    start = valuePop(ctxt);
67053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    in = start->floatval;
67063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(start);
67073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
67083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
67093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    str = valuePop(ctxt);
671097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    m = xmlUTF8Strlen((const unsigned char *)str->stringval);
671197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
671297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    /*
671397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     * If last pos not present, calculate last position
671497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    */
67159e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    if (nargs != 3) {
67169e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	le = (double)m;
67179e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	if (in < 1.0)
67189e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    in = 1.0;
67199e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    }
672097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
67210eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    /* Need to check for the special cases where either
67220eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard     * the index is NaN, the length is NaN, or both
67230eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard     * arguments are infinity (relying on Inf + -Inf = NaN)
672497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard     */
67259e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard    if (!xmlXPathIsNaN(in + le) && !xmlXPathIsInf(in)) {
67260eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        /*
67279e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard         * To meet the requirements of the spec, the arguments
67289e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * must be converted to integer format before
67299e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * initial index calculations are done
67300eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard         *
67319e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard         * First we go to integer form, rounding up
67329e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	 * and checking for special cases
67330eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard         */
67340eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        i = (int) in;
67359e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (((double)i)+0.5 <= in) i++;
67369e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard
67379e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	if (xmlXPathIsInf(le) == 1) {
67389e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = m;
67399e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    if (i < 1)
67409e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard		i = 1;
67419e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	}
67429e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	else if (xmlXPathIsInf(le) == -1 || le < 0.0)
67439e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = 0;
67449e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	else {
67459e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    l = (int) le;
67469e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	    if (((double)l)+0.5 <= le) l++;
67479e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	}
67480eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard
67499e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard	/* Now we normalize inidices */
67509e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        i -= 1;
67519e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        l += i;
67529e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (i < 0)
67539e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard            i = 0;
67549e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard        if (l > m)
67559e4123023a930924e26ca965ef14ea67bff7dfc3Daniel Veillard            l = m;
67563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67570eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        /* number of chars to copy */
67580eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        l -= i;
67593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67600eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        ret = xmlUTF8Strsub(str->stringval, i, l);
67610eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    }
67620eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    else {
67630eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard        ret = NULL;
67640eafdef9881c396ce4c014359d8f497cc088cfabDaniel Veillard    }
67653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL)
67673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewCString(""));
67683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
67693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	valuePush(ctxt, xmlXPathNewString(ret));
67703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFree(ret);
67713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
677297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
67733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(str);
67743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
67753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
67773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringBeforeFunction:
67783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
67793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
67803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
67813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring-before() XPath function
67823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring-before(string, string)
67833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring-before function returns the substring of the first
67843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string that precedes the first occurrence of the second
67853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string in the first argument string, or the empty string
67863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if the first argument string does not contain the second argument
67873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, substring-before("1999/04/01","/") returns 1999.
67883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
67893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
67903473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
67913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr str;
67923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr find;
67933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
67943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  const xmlChar *point;
67953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  int offset;
67963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
67973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(2);
67983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
67993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  find = valuePop(ctxt);
68003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
68013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  str = valuePop(ctxt);
68023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
68043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target) {
68053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    point = xmlStrstr(str->stringval, find->stringval);
68063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (point) {
68073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      offset = (int)(point - str->stringval);
68083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      xmlBufferAdd(target, str->stringval, offset);
68093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
68103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
68113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
68123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
68133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(str);
68153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(find);
68163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSubstringAfterFunction:
68203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the substring-after() XPath function
68243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string substring-after(string, string)
68253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The substring-after function returns the substring of the first
68263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string that follows the first occurrence of the second
68273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string in the first argument string, or the empty stringi
68283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * if the first argument string does not contain the second argument
68293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, substring-after("1999/04/01","/") returns 04/01,
68303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and substring-after("1999/04/01","19") returns 99/04/01.
68313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
68333473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
68343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr str;
68353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr find;
68363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
68373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  const xmlChar *point;
68383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  int offset;
68393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(2);
68413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
68423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  find = valuePop(ctxt);
68433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
68443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  str = valuePop(ctxt);
68453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
68473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target) {
68483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    point = xmlStrstr(str->stringval, find->stringval);
68493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (point) {
68503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
68513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      xmlBufferAdd(target, &str->stringval[offset],
68523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		   xmlStrlen(str->stringval) - offset);
68533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
68543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
68553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
68563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
68573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(str);
68593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(find);
68603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
68613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
68633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNormalizeFunction:
68643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
68653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
68663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
68673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the normalize-space() XPath function
68683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string normalize-space(string?)
68693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The normalize-space function returns the argument string with white
68703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * space normalized by stripping leading and trailing whitespace
68713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and replacing sequences of whitespace characters by a single
68723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * space. Whitespace characters are the same allowed by the S production
68733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * in XML. If the argument is omitted, it defaults to the context
68743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node converted to a string, in other words the value of the context node.
68753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
68763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
68773473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
68783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathObjectPtr obj = NULL;
68793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlChar *source = NULL;
68803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlBufferPtr target;
68813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlChar blank;
68823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6883a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard  if (ctxt == NULL) return;
68843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (nargs == 0) {
68853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Use current context node */
6886ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    valuePush(ctxt,
6887ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	      xmlXPathWrapString(
6888ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard		  xmlXPathCastNodeToString(ctxt->context->node)));
68893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    nargs = 1;
68903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
68913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_ARITY(1);
68933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CAST_TO_STRING;
68943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  CHECK_TYPE(XPATH_STRING);
68953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  obj = valuePop(ctxt);
68963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  source = obj->stringval;
68973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
68983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  target = xmlBufferCreate();
68993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  if (target && source) {
69003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Skip leading whitespaces */
690276e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*source))
69033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      source++;
69043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /* Collapse intermediate whitespaces, and skip trailing whitespaces */
69063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    blank = 0;
69073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (*source) {
690876e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack      if (IS_BLANK_CH(*source)) {
690997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	blank = 0x20;
69103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      } else {
69113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (blank) {
69123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	  xmlBufferAdd(target, &blank, 1);
69133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	  blank = 0;
69143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
69153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlBufferAdd(target, source, 1);
69163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      }
69173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor      source++;
69183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
69193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
69213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlBufferFree(target);
69223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  }
69233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor  xmlXPathFreeObject(obj);
69243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
69253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
69263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
69273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathTranslateFunction:
69283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
69293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
69303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
69313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the translate() XPath function
69323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    string translate(string, string, string)
69333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The translate function returns the first argument string with
69343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * occurrences of characters in the second argument string replaced
69353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by the character at the corresponding position in the third argument
69363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string. For example, translate("bar","abc","ABC") returns the string
69373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * BAr. If there is a character in the second argument string with no
69383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character at a corresponding position in the third argument string
69393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * (because the second argument string is longer than the third argument
69403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string), then occurrences of that character in the first argument
69413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * string are removed. For example, translate("--aaa--","abc-","ABC")
69423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns "AAA". If a character occurs more than once in second
69433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string, then the first occurrence determines the replacement
69443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * character. If the third argument string is longer than the second
69453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument string, then excess characters are ignored.
69463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
69473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
69483473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
6949e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr str;
6950e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr from;
6951e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathObjectPtr to;
6952e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlBufferPtr target;
695397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    int offset, max;
6954e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlChar ch;
6955b031cef5b537d8eda30f508627f08bc642bbd31dWilliam M. Brack    const xmlChar *point;
695697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard    xmlChar *cptr;
69573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6958e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CHECK_ARITY(3);
69593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6960e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6961e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    to = valuePop(ctxt);
6962e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6963e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    from = valuePop(ctxt);
6964e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    CAST_TO_STRING;
6965e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    str = valuePop(ctxt);
69663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6967e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    target = xmlBufferCreate();
6968e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    if (target) {
696997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	max = xmlUTF8Strlen(to->stringval);
697097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	for (cptr = str->stringval; (ch=*cptr); ) {
697197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    offset = xmlUTF8Strloc(from->stringval, cptr);
697297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    if (offset >= 0) {
697397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if (offset < max) {
697497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    point = xmlUTF8Strpos(to->stringval, offset);
697597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    if (point)
697697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1));
697797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		}
697897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    } else
697997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
698097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard
698197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    /* Step to next character in input */
698297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    cptr++;
698397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    if ( ch & 0x80 ) {
698497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		/* if not simple ascii, verify proper format */
698597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if ( (ch & 0xc0) != 0xc0 ) {
698697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    xmlGenericError(xmlGenericErrorContext,
698797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			"xmlXPathTranslateFunction: Invalid UTF8 string\n");
698897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    break;
698997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		}
699097ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		/* then skip over remaining bytes for this char */
699197ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		while ( (ch <<= 1) & 0x80 )
699297ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    if ( (*cptr++ & 0xc0) != 0x80 ) {
699397ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			xmlGenericError(xmlGenericErrorContext,
699497ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			    "xmlXPathTranslateFunction: Invalid UTF8 string\n");
699597ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard			break;
699697ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    }
699797ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		if (ch & 0x80) /* must have had error encountered */
699897ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard		    break;
699997ac13197ce5a6a754a7071a0e95b07f1f54ac6cDaniel Veillard	    }
7000e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard	}
70013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7002e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
7003e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlBufferFree(target);
7004e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(str);
7005e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(from);
7006e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    xmlXPathFreeObject(to);
70073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
70083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7010fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathBooleanFunction:
7011fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath Parser context
7012fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @nargs:  the number of arguments
7013fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7014fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Implement the boolean() XPath function
7015fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    boolean boolean(object)
7016081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * The boolean function converts its argument to a boolean as follows:
7017fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a number is true if and only if it is neither positive or
7018fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *      negative zero nor NaN
7019fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a node-set is true if and only if it is non-empty
7020fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *    - a string is true if and only if its length is non-zero
7021fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
7022fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardvoid
7023fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7024fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    xmlXPathObjectPtr cur;
7025fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
7026fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    CHECK_ARITY(1);
7027fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = valuePop(ctxt);
7028fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
7029fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertBoolean(cur);
7030fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
70313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
70323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
70343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNotFunction:
70353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
70363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
70373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
70383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the not() XPath function
70393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean not(boolean)
70403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The not function returns true if its argument is false,
70413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and false otherwise.
70423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
70433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
70443473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
70453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
70463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_BOOLEAN;
70473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_BOOLEAN);
70483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->value->boolval = ! ctxt->value->boolval;
70493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
70503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
70523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathTrueFunction:
70533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
70543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
70553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
70563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the true() XPath function
70573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean true()
70583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
70593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
70603473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
70613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(0);
70623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(1));
70633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
70643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
70663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFalseFunction:
70673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
70683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
70693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
70703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the false() XPath function
70713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean false()
70723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
70733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
70743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
70753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(0);
70763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(0));
70773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
70783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
70793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
70803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathLangFunction:
70813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
70823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
70833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
70843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the lang() XPath function
70853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    boolean lang(string)
70863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The lang function returns true or false depending on whether the
70873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * language of the context node as specified by xml:lang attributes
70883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * is the same as or is a sublanguage of the language specified by
70893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the argument string. The language of the context node is determined
70903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * by the value of the xml:lang attribute on the context node, or, if
70913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the context node has no xml:lang attribute, by the value of the
70923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xml:lang attribute on the nearest ancestor of the context node that
70933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * has an xml:lang attribute. If there is no such attribute, then lang
70943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * returns false. If there is such an attribute, then lang returns
70953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * true if the attribute value is equal to the argument ignoring case,
70963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * or if there is some suffix starting with - such that the attribute
70973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * value is equal to the argument ignoring that suffix of the attribute
70983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * value and ignoring case.
70993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
71003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
71013473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
71024ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard    xmlXPathObjectPtr val = NULL;
71034ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard    const xmlChar *theLang = NULL;
71043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *lang;
71053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int ret = 0;
71063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
71073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
71093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_STRING;
71103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_STRING);
71113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    val = valuePop(ctxt);
71123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    lang = val->stringval;
71133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    theLang = xmlNodeGetLang(ctxt->context->node);
71143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((theLang != NULL) && (lang != NULL)) {
71153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        for (i = 0;lang[i] != 0;i++)
71163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (toupper(lang[i]) != toupper(theLang[i]))
71173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        goto not_equal;
71184ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard	if ((theLang[i] == 0) || (theLang[i] == '-'))
71194ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard	    ret = 1;
71203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
71213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylornot_equal:
71224ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard    if (theLang != NULL)
71234ddaa56d7af6638c20a4446c47b02b299987be65Daniel Veillard	xmlFree((void *)theLang);
71243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(val);
71253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    valuePush(ctxt, xmlXPathNewBoolean(ret));
71263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
71273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
71293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathNumberFunction:
71303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
71313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
71323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the number() XPath function
71343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number number(object?)
71353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
71363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
71373473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
71383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
71393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double res;
71403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7141a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
71423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (nargs == 0) {
71433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ctxt->context->node == NULL) {
71443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(0.0));
71453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
71463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlChar* content = xmlNodeGetContent(ctxt->context->node);
71473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res = xmlXPathStringEvalNumber(content);
71493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    valuePush(ctxt, xmlXPathNewFloat(res));
71503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(content);
71513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
71523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
71533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
71543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
71563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
7157fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    cur = xmlXPathConvertNumber(cur);
7158fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    valuePush(ctxt, cur);
71593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
71603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
71623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathSumFunction:
71633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
71643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
71653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
71663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the sum() XPath function
71673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number sum(node-set)
71683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The sum function returns the sum of the values of the nodes in
71693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the argument node-set.
71703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
71713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
71723473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
71733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr cur;
71743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int i;
7175ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard    double res = 0.0;
71763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
71783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ctxt->value == NULL) ||
71793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ctxt->value->type != XPATH_NODESET) &&
71803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 (ctxt->value->type != XPATH_XSLT_TREE)))
71813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_INVALID_TYPE);
71823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = valuePop(ctxt);
71833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7184081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
7185ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	for (i = 0; i < cur->nodesetval->nodeNr; i++) {
7186ba0b8c94acad3f8e880002b3069f074be582e893Daniel Veillard	    res += xmlXPathCastNodeToNumber(cur->nodesetval->nodeTab[i]);
71873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
71883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7189081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack    valuePush(ctxt, xmlXPathNewFloat(res));
71903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeObject(cur);
71913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
71923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
71933d426663629a53180f3f54282ba27f3d070eef24William M. Brack/*
71943d426663629a53180f3f54282ba27f3d070eef24William M. Brack * To assure working code on multiple platforms, we want to only depend
71953d426663629a53180f3f54282ba27f3d070eef24William M. Brack * upon the characteristic truncation of converting a floating point value
71963d426663629a53180f3f54282ba27f3d070eef24William M. Brack * to an integer.  Unfortunately, because of the different storage sizes
71973d426663629a53180f3f54282ba27f3d070eef24William M. Brack * of our internal floating point value (double) and integer (int), we
71983d426663629a53180f3f54282ba27f3d070eef24William M. Brack * can't directly convert (see bug 301162).  This macro is a messy
71993d426663629a53180f3f54282ba27f3d070eef24William M. Brack * 'workaround'
72003d426663629a53180f3f54282ba27f3d070eef24William M. Brack */
72013d426663629a53180f3f54282ba27f3d070eef24William M. Brack#define XTRUNC(f, v)            \
72023d426663629a53180f3f54282ba27f3d070eef24William M. Brack    f = fmod((v), INT_MAX);     \
72033d426663629a53180f3f54282ba27f3d070eef24William M. Brack    f = (v) - (f) + (double)((int)(f));
72043d426663629a53180f3f54282ba27f3d070eef24William M. Brack
72053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
72063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathFloorFunction:
72073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
72083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
72093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the floor() XPath function
72113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number floor(number)
72123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The floor function returns the largest (closest to positive infinity)
72133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number that is not greater than the argument and that is an integer.
72143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
72153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
72163473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
721756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    double f;
721856cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard
72193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
72203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
72213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
722256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard
72233d426663629a53180f3f54282ba27f3d070eef24William M. Brack    XTRUNC(f, ctxt->value->floatval);
722456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (f != ctxt->value->floatval) {
722556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval > 0)
722656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
722756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
722856cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f - 1;
722956cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
72303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
72313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
72333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathCeilingFunction:
72343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
72353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
72363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the ceiling() XPath function
72383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number ceiling(number)
72393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The ceiling function returns the smallest (closest to negative infinity)
72403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * number that is not less than the argument and that is an integer.
72413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
72423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
72433473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
72443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double f;
72453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
72473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
72483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
72493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#if 0
72513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt->value->floatval = ceil(ctxt->value->floatval);
72523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#else
72533d426663629a53180f3f54282ba27f3d070eef24William M. Brack    XTRUNC(f, ctxt->value->floatval);
725456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (f != ctxt->value->floatval) {
725556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval > 0)
725656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f + 1;
72575fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	else {
72585fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    if (ctxt->value->floatval < 0 && f == 0)
72595fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	        ctxt->value->floatval = xmlXPathNZERO;
72605fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    else
72615fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	        ctxt->value->floatval = f;
72625fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	}
72635fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard
726456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
72653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
72663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
72673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
72693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRoundFunction:
72703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
72713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @nargs:  the number of arguments
72723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
72733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Implement the round() XPath function
72743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *    number round(number)
72753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The round function returns the number that is closest to the
72763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * argument and that is an integer. If there are two such numbers,
72773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * then the one that is even is returned.
72783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
72793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
72803473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
72813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double f;
72823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ARITY(1);
72843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CAST_TO_NUMBER;
72853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_TYPE(XPATH_NUMBER);
72863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7287cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard    if ((xmlXPathIsNaN(ctxt->value->floatval)) ||
7288cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	(xmlXPathIsInf(ctxt->value->floatval) == 1) ||
7289cda969218bdda1d3dd8d3c4417f3dc100d076024Daniel Veillard	(xmlXPathIsInf(ctxt->value->floatval) == -1) ||
72903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	(ctxt->value->floatval == 0.0))
72913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return;
72923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
72933d426663629a53180f3f54282ba27f3d070eef24William M. Brack    XTRUNC(f, ctxt->value->floatval);
729456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    if (ctxt->value->floatval < 0) {
729556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval < f - 0.5)
729656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f - 1;
729756cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
729856cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
72995fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	if (ctxt->value->floatval == 0)
73005fc1f0893af6ffe76453ac16817204a866bdeab2Daniel Veillard	    ctxt->value->floatval = xmlXPathNZERO;
730156cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    } else {
730256cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	if (ctxt->value->floatval < f + 0.5)
730356cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f;
730456cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	else
730556cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard	    ctxt->value->floatval = f + 1;
730656cd18b977006c28eaae715ac6590e6ad48186daDaniel Veillard    }
73073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
73083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
73103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
73113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			The Parser					*
73123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
73133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
73143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
7316081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * a few forward declarations since we use a recursive call based
73173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * implementation.
73183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7319afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt);
7320d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillardstatic void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
7321afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
7322afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt);
73232156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillardstatic xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,
73242156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	                                  int qualified);
73253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
73263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
732761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * xmlXPathCurrentChar:
732861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @ctxt:  the XPath parser context
732961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @cur:  pointer to the beginning of the char
733061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * @len:  pointer to the length of the char read
733161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard *
7332cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * The current char value, if using UTF-8 this may actually span multiple
733361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard * bytes in the input buffer.
733461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard *
733560087f30f3b4cf21de48f39181736e7d71e7a661Daniel Veillard * Returns the current char value and its length
733661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard */
733761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
733861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardstatic int
733961d80a2822b2678dee885ac2850295cc96277c63Daniel VeillardxmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
734061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    unsigned char c;
734161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    unsigned int val;
734261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    const xmlChar *cur;
734361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
734461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (ctxt == NULL)
734561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(0);
734661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    cur = ctxt->cur;
734761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
734861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
734961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * We are supposed to handle UTF8, check it's valid
735061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * From rfc2044: encoding of the Unicode values on UTF-8:
735161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     *
735261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
735361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0000-0000 007F   0xxxxxxx
735461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
735561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
735661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     *
735761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Check for the 0x110000 limit too
735861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
735961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    c = *cur;
736061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (c & 0x80) {
736161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if ((cur[1] & 0xc0) != 0x80)
736261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    goto encoding_error;
736361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if ((c & 0xe0) == 0xe0) {
736461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
736561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if ((cur[2] & 0xc0) != 0x80)
736661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		goto encoding_error;
736761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if ((c & 0xf0) == 0xf0) {
736861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		if (((c & 0xf8) != 0xf0) ||
736961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    ((cur[3] & 0xc0) != 0x80))
737061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    goto encoding_error;
737161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		/* 4-byte code */
737261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		*len = 4;
737361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val = (cur[0] & 0x7) << 18;
737461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[1] & 0x3f) << 12;
737561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[2] & 0x3f) << 6;
737661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= cur[3] & 0x3f;
737761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    } else {
737861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	      /* 3-byte code */
737961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		*len = 3;
738061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val = (cur[0] & 0xf) << 12;
738161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= (cur[1] & 0x3f) << 6;
738261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		val |= cur[2] & 0x3f;
738361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
738461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	} else {
738561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	  /* 2-byte code */
738661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    *len = 2;
738761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    val = (cur[0] & 0x1f) << 6;
738861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    val |= cur[1] & 0x3f;
738961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
739061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if (!IS_CHAR(val)) {
739161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    XP_ERROR0(XPATH_INVALID_CHAR_ERROR);
739261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
739361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(val);
739461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    } else {
739561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	/* 1-byte code */
739661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	*len = 1;
739761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return((int) *cur);
739861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
739961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardencoding_error:
740061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
7401081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * If we detect an UTF8 error that probably means that the
7402081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack     * input encoding didn't get properly advertised in the
740361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * declaration header. Report the error and switch the encoding
740461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * to ISO-Latin-1 (if you don't like this policy, just declare the
740561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * encoding !)
740661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
740742596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard    *len = 0;
740861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    XP_ERROR0(XPATH_ENCODING_ERROR);
740961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
741061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
741161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard/**
74123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseNCName:
74133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
74143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML namespace non qualified name.
74163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
74183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
74203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                       CombiningChar | Extender
74213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the namespace name or NULL
74233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
74243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74253473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
74263473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
74272156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    const xmlChar *in;
74282156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    xmlChar *ret;
74292156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    int count = 0;
74303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7431a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
74322156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    /*
74332156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard     * Accelerator for simple ASCII names
74342156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard     */
74352156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    in = ctxt->cur;
74362156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    if (((*in >= 0x61) && (*in <= 0x7A)) ||
74372156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	((*in >= 0x41) && (*in <= 0x5A)) ||
74382156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	(*in == '_')) {
74392156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	in++;
74402156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	while (((*in >= 0x61) && (*in <= 0x7A)) ||
74412156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	       ((*in >= 0x41) && (*in <= 0x5A)) ||
74422156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	       ((*in >= 0x30) && (*in <= 0x39)) ||
74439a89a8ab80bc021deec9da7d79bda20995c4e78dDaniel Veillard	       (*in == '_') || (*in == '.') ||
74449a89a8ab80bc021deec9da7d79bda20995c4e78dDaniel Veillard	       (*in == '-'))
74452156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    in++;
74462156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	if ((*in == ' ') || (*in == '>') || (*in == '/') ||
74472156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard            (*in == '[') || (*in == ']') || (*in == ':') ||
74482156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard            (*in == '@') || (*in == '*')) {
74492156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    count = in - ctxt->cur;
74502156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (count == 0)
74512156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		return(NULL);
74522156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    ret = xmlStrndup(ctxt->cur, count);
74532156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    ctxt->cur = in;
74542156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    return(ret);
74552156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	}
74562156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    }
74572156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    return(xmlXPathParseNameComplex(ctxt, 0));
74583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
74593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74602156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard
74613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
74623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseQName:
74633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
74643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  a xmlChar **
74653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML qualified name
74673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 5] QName ::= (Prefix ':')? LocalPart
74693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 6] Prefix ::= NCName
74713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [NS 7] LocalPart ::= NCName
74733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the function returns the local part, and prefix is updated
74753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *   to get the Prefix if any.
74763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
74773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
747856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
74793473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
74803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret = NULL;
74813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *prefix = NULL;
74833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ret = xmlXPathParseNCName(ctxt);
74843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == ':') {
74853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        *prefix = ret;
74863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
74873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = xmlXPathParseNCName(ctxt);
74883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
74893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
74903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
74913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
74923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
74933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathParseName:
74943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
74953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * parse an XML name
74973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
74983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
74993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  CombiningChar | Extender
75003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] Name ::= (Letter | '_' | ':') (NameChar)*
75023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
75033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the namespace name or NULL
75043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
75053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
75063473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
75073473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathParseName(xmlXPathParserContextPtr ctxt) {
750861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    const xmlChar *in;
750961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    xmlChar *ret;
751061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int count = 0;
75113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
7512a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
751361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
751461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Accelerator for simple ASCII names
751561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
751661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    in = ctxt->cur;
751761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if (((*in >= 0x61) && (*in <= 0x7A)) ||
751861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	((*in >= 0x41) && (*in <= 0x5A)) ||
751961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	(*in == '_') || (*in == ':')) {
752061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	in++;
752161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	while (((*in >= 0x61) && (*in <= 0x7A)) ||
752261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	       ((*in >= 0x41) && (*in <= 0x5A)) ||
752361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	       ((*in >= 0x30) && (*in <= 0x39)) ||
752476d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	       (*in == '_') || (*in == '-') ||
752576d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	       (*in == ':') || (*in == '.'))
752661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    in++;
752776d66f416d2d0d5db4a09d212b4e43087e9cdae7Daniel Veillard	if ((*in > 0) && (*in < 0x80)) {
752861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    count = in - ctxt->cur;
752961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    ret = xmlStrndup(ctxt->cur, count);
753061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    ctxt->cur = in;
753161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    return(ret);
753261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
753361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
75342156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    return(xmlXPathParseNameComplex(ctxt, 1));
753561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
75363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
753761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillardstatic xmlChar *
75382156a56bcbf5d83fb3d694123be01beebf84d273Daniel VeillardxmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
753961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    xmlChar buf[XML_MAX_NAMELEN + 5];
754061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int len = 0, l;
754161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    int c;
75423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
754361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    /*
754461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     * Handler for more complex cases
754561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard     */
754661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    c = CUR_CHAR(l);
754761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
75482156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard        (c == '[') || (c == ']') || (c == '@') || /* accelerators */
75492156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard        (c == '*') || /* accelerators */
755061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	(!IS_LETTER(c) && (c != '_') &&
75512156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard         ((qualified) && (c != ':')))) {
755261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	return(NULL);
755361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
75543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
755561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
755661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
755761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard            (c == '.') || (c == '-') ||
75582156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    (c == '_') || ((qualified) && (c == ':')) ||
755961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    (IS_COMBINING(c)) ||
756061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    (IS_EXTENDER(c)))) {
756161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	COPY_BUF(l,buf,len,c);
756261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	NEXTL(l);
756361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	c = CUR_CHAR(l);
756461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	if (len >= XML_MAX_NAMELEN) {
756561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    /*
756661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     * Okay someone managed to make a huge name, so he's ready to pay
756761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     * for the processing speed.
756861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	     */
756961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    xmlChar *buffer;
757061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    int max = len * 2;
757161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard
75723c908dca479ed50dca24b8593bca90e40dbde6b8Daniel Veillard	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
757361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    if (buffer == NULL) {
757461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		XP_ERROR0(XPATH_MEMORY_ERROR);
757561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
757661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    memcpy(buffer, buf, len);
757761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
757861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (c == '.') || (c == '-') ||
75792156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		   (c == '_') || ((qualified) && (c == ':')) ||
758061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (IS_COMBINING(c)) ||
758161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		   (IS_EXTENDER(c))) {
758261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		if (len + 10 > max) {
758361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    max *= 2;
758461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    buffer = (xmlChar *) xmlRealloc(buffer,
758561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard			                            max * sizeof(xmlChar));
758661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    if (buffer == NULL) {
758761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard			XP_ERROR0(XPATH_MEMORY_ERROR);
758861d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		    }
758961d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		}
759061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		COPY_BUF(l,buffer,len,c);
759161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		NEXTL(l);
759261d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard		c = CUR_CHAR(l);
759361d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    }
759461d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    buffer[len] = 0;
759561d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	    return(buffer);
759661d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard	}
759761d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    }
75982156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard    if (len == 0)
75992156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	return(NULL);
760061d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard    return(xmlStrndup(buf, len));
760161d80a2822b2678dee885ac2850295cc96277c63Daniel Veillard}
76023cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
76033cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard#define MAX_FRAC 20
76043cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
7605372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack/*
7606372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack * These are used as divisors for the fractional part of a number.
7607372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack * Since the table includes 1.0 (representing '0' fractional digits),
7608372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack * it must be dimensioned at MAX_FRAC+1 (bug 133921)
7609372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack */
7610372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brackstatic double my_pow10[MAX_FRAC+1] = {
76113cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1.0, 10.0, 100.0, 1000.0, 10000.0,
76123cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    100000.0, 1000000.0, 10000000.0, 100000000.0, 1000000000.0,
76133cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0,
76143cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    100000000000000.0,
76153cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard    1000000000000000.0, 10000000000000000.0, 100000000000000000.0,
7616372a445479b859bd0fe24df54e9b3db34d113d5aWilliam M. Brack    1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0
76173cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard};
76183cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
76193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
76203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathStringEvalNumber:
76213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  A string to scan
76223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
762370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese *  [30a]  Float  ::= Number ('e' Digits?)?
762470a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese *
76253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [30]   Number ::=   Digits ('.' Digits?)?
76263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | '.' Digits
76273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [31]   Digits ::=   [0-9]+
76283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7629afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Number in the string
76303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * In complement of the Number expression, this function also handles
76313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * negative values : '-' Number.
76323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
76333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the double value.
76343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
76353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordouble
76363473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathStringEvalNumber(const xmlChar *str) {
76373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *cur = str;
76387b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double ret;
7639b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    int ok = 0;
76403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int isneg = 0;
764170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int exponent = 0;
764270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int is_exponent_negative = 0;
7643b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#ifdef __GNUC__
7644b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    unsigned long tmp = 0;
76457b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double temp;
7646b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#endif
7647eca82810f0fb81f3e9936d2018347e1e19de513aDaniel Veillard    if (cur == NULL) return(0);
764876e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*cur)) cur++;
76493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((*cur != '.') && ((*cur < '0') || (*cur > '9')) && (*cur != '-')) {
76503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        return(xmlXPathNAN);
76513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
76523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == '-') {
76533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	isneg = 1;
76543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur++;
76553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7656b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard
7657b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#ifdef __GNUC__
7658d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard    /*
76597b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * tmp/temp is a workaround against a gcc compiler bug
76607b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * http://veillard.com/gcc.bug
7661d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard     */
76627b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
76633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((*cur >= '0') && (*cur <= '9')) {
76647b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10;
76657b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	tmp = (*cur - '0');
76663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ok = 1;
76673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	cur++;
76687b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	temp = (double) tmp;
76697b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret + temp;
76703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7671b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#else
76727b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
7673b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    while ((*cur >= '0') && (*cur <= '9')) {
7674b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	ret = ret * 10 + (*cur - '0');
7675b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	ok = 1;
7676b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard	cur++;
7677b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard    }
7678b06c61455f86758511aa050a06ff1bbd33f8c3c3Daniel Veillard#endif
7679d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard
76803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur == '.') {
76813cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	int v, frac = 0;
76823cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	double fraction = 0;
76833cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard
76843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        cur++;
76853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (((*cur < '0') || (*cur > '9')) && (!ok)) {
76863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(xmlXPathNAN);
76873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
76883cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	while (((*cur >= '0') && (*cur <= '9')) && (frac < MAX_FRAC)) {
76893cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    v = (*cur - '0');
76903cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    fraction = fraction * 10 + v;
76913cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    frac = frac + 1;
76923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur++;
76933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
76943cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	fraction /= my_pow10[frac];
76953cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	ret = ret + fraction;
76963cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	while ((*cur >= '0') && (*cur <= '9'))
76973cd7240da45a00a17f003b67881d8e4afb618711Daniel Veillard	    cur++;
76983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
769970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if ((*cur == 'e') || (*cur == 'E')) {
770070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      cur++;
770170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      if (*cur == '-') {
770270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	is_exponent_negative = 1;
770370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	cur++;
77049912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack      } else if (*cur == '+') {
77059912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack        cur++;
770670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      }
770770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      while ((*cur >= '0') && (*cur <= '9')) {
770870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	exponent = exponent * 10 + (*cur - '0');
770970a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese	cur++;
771070a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese      }
771170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    }
771276e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    while (IS_BLANK_CH(*cur)) cur++;
77133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*cur != 0) return(xmlXPathNAN);
77143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (isneg) ret = -ret;
771570a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if (is_exponent_negative) exponent = -exponent;
771670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    ret *= pow(10.0, (double)exponent);
77173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
77183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
77193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7721afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompNumber:
77223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
77233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [30]   Number ::=   Digits ('.' Digits?)?
77253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | '.' Digits
77263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [31]   Digits ::=   [0-9]+
77273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7728afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Number, then push it on the stack
77293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
77303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7731afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7732d79bcd1b36412a7996ace1900ab613e38a609b60Daniel VeillardxmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
7733d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard{
77343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double ret = 0.0;
77353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    double mult = 1;
77367b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    int ok = 0;
773770a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int exponent = 0;
773870a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    int is_exponent_negative = 0;
77397b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#ifdef __GNUC__
77407b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    unsigned long tmp = 0;
77417b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    double temp;
77427b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#endif
77433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
77443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
77453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
77463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        XP_ERROR(XPATH_NUMBER_ERROR);
77473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77487b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#ifdef __GNUC__
7749d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard    /*
77507b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * tmp/temp is a workaround against a gcc compiler bug
77517b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard     * http://veillard.com/gcc.bug
7752d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard     */
77537b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
77543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR >= '0') && (CUR <= '9')) {
77557b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10;
77567b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	tmp = (CUR - '0');
7757d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        ok = 1;
7758d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        NEXT;
77597b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	temp = (double) tmp;
77607b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret + temp;
77613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
77627b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#else
77637b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    ret = 0;
77647b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    while ((CUR >= '0') && (CUR <= '9')) {
77657b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ret = ret * 10 + (CUR - '0');
77667b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	ok = 1;
77677b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard	NEXT;
77687b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard    }
77697b41613ff3a060180b2e92ad3bb0366061537a29Daniel Veillard#endif
77703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '.') {
77713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
7772d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (((CUR < '0') || (CUR > '9')) && (!ok)) {
7773d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            XP_ERROR(XPATH_NUMBER_ERROR);
7774d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
7775d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        while ((CUR >= '0') && (CUR <= '9')) {
7776d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            mult /= 10;
7777d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            ret = ret + (CUR - '0') * mult;
7778d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
7779d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
77803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
778170a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    if ((CUR == 'e') || (CUR == 'E')) {
7782d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        NEXT;
7783d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (CUR == '-') {
7784d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            is_exponent_negative = 1;
7785d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
77869912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack        } else if (CUR == '+') {
77879912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack	    NEXT;
77889912705b82cbf3fbff43e19dd95dd0a6ec494d2dWilliam M. Brack	}
7789d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        while ((CUR >= '0') && (CUR <= '9')) {
7790d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            exponent = exponent * 10 + (CUR - '0');
7791d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            NEXT;
7792d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        }
7793d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        if (is_exponent_negative)
7794d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard            exponent = -exponent;
7795d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard        ret *= pow(10.0, (double) exponent);
779670a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese    }
77979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0,
7798d79bcd1b36412a7996ace1900ab613e38a609b60Daniel Veillard                   xmlXPathNewFloat(ret), NULL);
77993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
78003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7802fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathParseLiteral:
7803fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath Parser context
7804fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7805fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Parse a Literal
7806fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7807fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *  [29]   Literal ::=   '"' [^"]* '"'
7808fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *                    | "'" [^']* "'"
7809fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
7810fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Returns the value found or NULL in case of error
7811fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
7812fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardstatic xmlChar *
7813fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
7814fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    const xmlChar *q;
7815fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    xmlChar *ret = NULL;
7816fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
7817fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    if (CUR == '"') {
7818fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        NEXT;
7819fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	q = CUR_PTR;
782076e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
7821fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
782276e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	if (!IS_CHAR_CH(CUR)) {
7823fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    XP_ERROR0(XPATH_UNFINISHED_LITERAL_ERROR);
7824fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	} else {
7825fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    ret = xmlStrndup(q, CUR_PTR - q);
7826fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
7827fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        }
7828fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    } else if (CUR == '\'') {
7829fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        NEXT;
7830fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	q = CUR_PTR;
783176e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
7832fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
783376e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	if (!IS_CHAR_CH(CUR)) {
7834fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    XP_ERROR0(XPATH_UNFINISHED_LITERAL_ERROR);
7835fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	} else {
7836fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    ret = xmlStrndup(q, CUR_PTR - q);
7837fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    NEXT;
7838fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        }
7839fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    } else {
7840fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	XP_ERROR0(XPATH_START_LITERAL_ERROR);
7841fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    }
7842fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    return(ret);
7843fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard}
7844fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
7845fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
7846afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompLiteral:
78473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
78483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Parse a Literal and push it on the stack.
78503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [29]   Literal ::=   '"' [^"]* '"'
78523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | "'" [^']* "'"
78533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7854afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * TODO: xmlXPathCompLiteral memory allocation could be improved.
78553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7856afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7857afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
78583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    const xmlChar *q;
78593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *ret = NULL;
78603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '"') {
78623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
78633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	q = CUR_PTR;
786476e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((IS_CHAR_CH(CUR)) && (CUR != '"'))
78653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
786676e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	if (!IS_CHAR_CH(CUR)) {
78673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
78683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
78693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlStrndup(q, CUR_PTR - q);
78703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
78713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
78723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '\'') {
78733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        NEXT;
78743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	q = CUR_PTR;
787576e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	while ((IS_CHAR_CH(CUR)) && (CUR != '\''))
78763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
787776e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack	if (!IS_CHAR_CH(CUR)) {
78783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_UNFINISHED_LITERAL_ERROR);
78793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
78803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlStrndup(q, CUR_PTR - q);
78813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
78823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
78833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
78843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_START_LITERAL_ERROR);
78853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
78863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret == NULL) return;
78879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0,
78889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           xmlXPathNewString(ret), NULL);
78893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlFree(ret);
78903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
78913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
78923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7893afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompVariableReference:
78943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
78953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Parse a VariableReference, evaluate it and push it on the stack.
78973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
78983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The variable bindings consist of a mapping from variable names
7899081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * to variable values. The value of a variable is an object, which can be
79003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * of any of the types that are possible for the value of an expression,
79013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and may also be of additional types not specified here.
79023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Early evaluation is possible since:
79043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The variable bindings [...] used to evaluate a subexpression are
79053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * always the same as those used to evaluate the containing expression.
79063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [36]   VariableReference ::=   '$' QName
79083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7909afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7910afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
79113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name;
79123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *prefix;
79133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
79153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '$') {
79163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
79173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
79183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
79193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    name = xmlXPathParseQName(ctxt, &prefix);
79203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
79213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
79223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
7923fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    ctxt->comp->last = -1;
79249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
79259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           name, prefix);
79263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
79273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
79283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
79303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsNodeType:
79313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  a name string
79323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Is the name given a NodeType one.
79343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [38]   NodeType ::=   'comment'
79363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'text'
79373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'processing-instruction'
79383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                    | 'node'
79393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns 1 if true 0 otherwise
79413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
79423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorint
79433473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsNodeType(const xmlChar *name) {
79443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
79453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(0);
79463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79471971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "node"))
79483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
79493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (xmlStrEqual(name, BAD_CAST "text"))
79503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
79511971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "comment"))
79523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
79531971ee2698cb84c7699c96d3302f00e20d42c0d3Daniel Veillard    if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
79543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
79553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
79563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
79573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
7959afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompFunctionCall:
79603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
79613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
79623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [16]   FunctionCall ::=   FunctionName '(' ( Argument ( ',' Argument)*)? ')'
79633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [17]   Argument ::=   Expr
79643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7965afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a function call, the evaluation of all arguments are
79663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * pushed on the stack
79673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
7968afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
7969afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
79703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name;
79713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *prefix;
79723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int nbargs = 0;
79733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    name = xmlXPathParseQName(ctxt, &prefix);
79753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
79763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_EXPR_ERROR);
79773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
79783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
79793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_EXPR
79803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (prefix == NULL)
79813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Calling function %s\n",
79823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			name);
79833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else
79843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Calling function %s:%s\n",
79853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			prefix, name);
79863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
79873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '(') {
79893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR(XPATH_EXPR_ERROR);
79903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
79913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
79923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
79933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
79949e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt->comp->last = -1;
799571f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard    if (CUR != ')') {
799671f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	while (CUR != 0) {
799771f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    int op1 = ctxt->comp->last;
799871f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    ctxt->comp->last = -1;
799971f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    xmlXPathCompileExpr(ctxt);
800071f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    CHECK_ERROR;
800171f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
800271f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    nbargs++;
800371f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    if (CUR == ')') break;
800471f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    if (CUR != ',') {
800571f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard		XP_ERROR(XPATH_EXPR_ERROR);
800671f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    }
800771f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    NEXT;
800871f9d7310c1f8c587f518ec685b1448160df7336Daniel Veillard	    SKIP_BLANKS;
80093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
80103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80119e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0,
80129e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	           name, prefix);
80133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    NEXT;
80143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
80153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
80163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8018afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPrimaryExpr:
80193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
80203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [15]   PrimaryExpr ::=   VariableReference
80223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | '(' Expr ')'
80233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | Literal
80243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | Number
80253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                | FunctionCall
80263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8027afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a primary expression.
80283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8029afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8030afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) {
80313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
8032afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    if (CUR == '$') xmlXPathCompVariableReference(ctxt);
80333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (CUR == '(') {
80343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
80353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8036afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompileExpr(ctxt);
803750fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	CHECK_ERROR;
80383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ')') {
80393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
80403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
80413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
80423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8043d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack    } else if (IS_ASCII_DIGIT(CUR) || (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
8044afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompNumber(ctxt);
80453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if ((CUR == '\'') || (CUR == '"')) {
8046afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompLiteral(ctxt);
80473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
8048afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompFunctionCall(ctxt);
80493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
80513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
80523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8054afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompFilterExpr:
80553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
80563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [20]   FilterExpr ::=   PrimaryExpr
80583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr Predicate
80593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8060afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a filter expression.
80613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Square brackets are used to filter expressions in the same way that
80623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * they are used in location paths. It is an error if the expression to
80633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * be filtered does not evaluate to a node-set. The context node list
80643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * used for evaluating the expression in square brackets is the node-set
80653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be filtered listed in document order.
80663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
80673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8068afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8069afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
8070afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompPrimaryExpr(ctxt);
80713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
80723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
80733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '[') {
8075d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	xmlXPathCompPredicate(ctxt, 1);
80763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
80773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
80783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
80813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
80823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
80833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathScanName:
80843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
80853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Trickery: parse an XML name but without consuming the input flow
80873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Needed to avoid insanity in the parser state.
80883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
80903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  CombiningChar | Extender
80913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] Name ::= (Letter | '_' | ':') (NameChar)*
80933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [6] Names ::= Name (S Name)*
80953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
80963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the Name parsed or NULL
80973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
80983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
809956a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
81003473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathScanName(xmlXPathParserContextPtr ctxt) {
8101032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    int len = 0, l;
8102032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    int c;
8103032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    const xmlChar *cur;
8104032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    xmlChar *ret;
81053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8106032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    cur = ctxt->cur;
8107032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard
8108032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    c = CUR_CHAR(l);
8109032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
8110032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	(!IS_LETTER(c) && (c != '_') &&
8111032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard         (c != ':'))) {
81123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
81133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
81143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8115032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
8116032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
8117032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard            (c == '.') || (c == '-') ||
8118032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	    (c == '_') || (c == ':') ||
8119032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	    (IS_COMBINING(c)) ||
8120032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	    (IS_EXTENDER(c)))) {
8121032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	len += l;
8122032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	NEXTL(l);
8123032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard	c = CUR_CHAR(l);
81243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8125032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    ret = xmlStrndup(cur, ctxt->cur - cur);
8126032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    ctxt->cur = cur;
8127032268145fad72bbf00c944c1f6a067e5da4a1e0Daniel Veillard    return(ret);
81283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
81293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8131afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPathExpr:
81323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
81333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
81343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [19]   PathExpr ::=   LocationPath
81353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr
81363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr '/' RelativeLocationPath
81373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | FilterExpr '//' RelativeLocationPath
81383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8139afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a path expression.
81403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The / operator and // operators combine an arbitrary expression
81413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and a relative location path. It is an error if the expression
81423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * does not evaluate to a node-set.
81433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * The / operator does composition in the same way as when / is
81443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * used in a location path. As in location paths, // is short for
81453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * /descendant-or-self::node()/.
81463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
81473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8148afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8149afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
81503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int lc = 1;           /* Should we branch to LocationPath ?         */
81513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *name = NULL; /* we may have to preparse a name to find out */
81523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
8154d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack    if ((CUR == '$') || (CUR == '(') ||
8155d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack    	(IS_ASCII_DIGIT(CUR)) ||
8156d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack        (CUR == '\'') || (CUR == '"') ||
8157d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack	(CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
81583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 0;
81593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '*') {
81603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative or absolute location path */
81613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
81623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '/') {
81633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative or absolute location path */
81643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
81653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '@') {
81663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative abbreviated attribute location path */
81673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
81683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '.') {
81693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/* relative abbreviated attribute location path */
81703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	lc = 1;
81713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
81723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
81733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * Problem is finding if we have a name here whether it's:
81743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a nodetype
81753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a function call in which case it's followed by '('
81763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - an axis in which case it's followed by ':'
81773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 *   - a element name
81783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * We do an a priori analysis here rather than having to
81793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * maintain parsed token content through the recursive function
8180081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	 * calls. This looks uglier but makes the code easier to
81813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * read/write/debug.
81823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
81833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
81843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathScanName(ctxt);
81853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
81863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
81873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlGenericError(xmlGenericErrorContext,
81883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    "PathExpr: Axis\n");
81893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
81903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    lc = 1;
81913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
81923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (name != NULL) {
81933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    int len =xmlStrlen(name);
81943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
81963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (NXT(len) != 0) {
81973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (NXT(len) == '/') {
81983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* element name */
81993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
82003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
82013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
82023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
82033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
82043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
820576e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack		} else if (IS_BLANK_CH(NXT(len))) {
820678637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack		    /* ignore blanks */
820778637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack		    ;
82083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if (NXT(len) == ':') {
82093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
82103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
82113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
82123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
82133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
82143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
82153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '(')) {
82163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* Note Type or Function */
82173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if (xmlXPathIsNodeType(name)) {
82183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
82193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		        xmlGenericError(xmlGenericErrorContext,
82203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"PathExpr: Type search\n");
82213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
82223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			lc = 1;
82233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    } else {
82243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
82253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		        xmlGenericError(xmlGenericErrorContext,
82263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor				"PathExpr: function call\n");
82273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
82283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			lc = 0;
82293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    }
82303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    break;
82313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '[')) {
82323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* element name */
82333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
82343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlGenericError(xmlGenericErrorContext,
82353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			    "PathExpr: AbbrRelLocation\n");
82363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
82373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
82383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
82393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else if ((NXT(len) == '<') || (NXT(len) == '>') ||
82403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			   (NXT(len) == '=')) {
82413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
82423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
82433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
82443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    lc = 1;
82453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    break;
82463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
82473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		len++;
82483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
82493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (NXT(len) == 0) {
82503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
82513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlGenericError(xmlGenericErrorContext,
82523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			"PathExpr: AbbrRelLocation\n");
82533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
82543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		/* element name */
82553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		lc = 1;
82563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
82573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
82583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else {
8259081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    /* make sure all cases are covered explicitly */
82603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR(XPATH_EXPR_ERROR);
82613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
82623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
82633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (lc) {
82659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (CUR == '/') {
82669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0);
82679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	} else {
82689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
82693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8270afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompLocationPath(ctxt);
82713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
8272afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompFilterExpr(ctxt);
82733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
82743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((CUR == '/') && (NXT(1) == '/')) {
82753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(2);
82763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
82779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
82789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
82799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
82809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_RESET, ctxt->comp->last, 1, 0);
82819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8282afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompRelativeLocationPath(ctxt);
82833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == '/') {
8284afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompRelativeLocationPath(ctxt);
82853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
82863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
82873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
82883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
82893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
82903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8291afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompUnionExpr:
82923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
82933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
82943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [18]   UnionExpr ::=   PathExpr
82953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *               | UnionExpr '|' PathExpr
82963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8297afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an union expression.
82983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
82993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8300afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8301afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) {
8302afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompPathExpr(ctxt);
83033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
83043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
83053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '|') {
83069e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
83079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
83083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
83103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8311afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	xmlXPathCompPathExpr(ctxt);
83123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0);
83149e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
83153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
83163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
83183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8320afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompUnaryExpr:
83213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
83223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [27]   UnaryExpr ::=   UnionExpr
83243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | '-' UnaryExpr
83253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8326afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an unary expression.
83273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
83283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8329afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8330afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) {
83313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int minus = 0;
83329e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int found = 0;
83333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
833568d7b67ada0941ad7e1d02602f48de4015a67af3Daniel Veillard    while (CUR == '-') {
833668d7b67ada0941ad7e1d02602f48de4015a67af3Daniel Veillard        minus = 1 - minus;
83379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	found = 1;
83383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
83393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
83403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83419e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8342afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompUnionExpr(ctxt);
83433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
83449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (found) {
83459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (minus)
83469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0);
83479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	else
83489e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0);
83493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
83513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8353afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompMultiplicativeExpr:
83543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
83553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [26]   MultiplicativeExpr ::=   UnaryExpr
83573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr MultiplyOperator UnaryExpr
83583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr 'div' UnaryExpr
83593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | MultiplicativeExpr 'mod' UnaryExpr
83603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [34]   MultiplyOperator ::=   '*'
83613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8362afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Additive expression.
83633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
83643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8365afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8366afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) {
8367afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompUnaryExpr(ctxt);
83683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
83693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
83703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '*') ||
83713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) ||
83723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) {
83733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int op = -1;
83749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
83753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '*') {
83773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 0;
83783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
83793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == 'd') {
83803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 1;
83813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(3);
83823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == 'm') {
83833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    op = 2;
83843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(3);
83853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
83863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8387afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompUnaryExpr(ctxt);
83883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
83899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0);
83903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
83913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
83923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
83933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
83943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8395afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompAdditiveExpr:
83963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
83973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
83983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [25]   AdditiveExpr ::=   MultiplicativeExpr
83993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | AdditiveExpr '+' MultiplicativeExpr
84003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                   | AdditiveExpr '-' MultiplicativeExpr
84013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8402afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Additive expression.
84033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
84043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8405afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8406afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) {
84079e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8408afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompMultiplicativeExpr(ctxt);
84093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
84103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
84113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '+') || (CUR == '-')) {
84123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	int plus;
84139e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
84143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '+') plus = 1;
84163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else plus = 0;
84173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
84183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8419afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompMultiplicativeExpr(ctxt);
84203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
84219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0);
84223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
84233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
84243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
84253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8427afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompRelationalExpr:
84283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
84293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [24]   RelationalExpr ::=   AdditiveExpr
84313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '<' AdditiveExpr
84323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '>' AdditiveExpr
84333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '<=' AdditiveExpr
84343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | RelationalExpr '>=' AdditiveExpr
84353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  A <= B > C is allowed ? Answer from James, yes with
84373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (AdditiveExpr <= AdditiveExpr) > AdditiveExpr
84383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  which is basically what got implemented.
84393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8440afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a Relational expression, then push the result
84413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * on the stack
84423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
84433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8444afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8445afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) {
8446afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompAdditiveExpr(ctxt);
84473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
84483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
84493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '<') ||
84503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           (CUR == '>') ||
84513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == '<') && (NXT(1) == '=')) ||
84523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor           ((CUR == '>') && (NXT(1) == '='))) {
84539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int inf, strict;
84549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
84553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '<') inf = 1;
84573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else inf = 0;
84583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (NXT(1) == '=') strict = 0;
84593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else strict = 1;
84603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
84613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!strict) NEXT;
84623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8463afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompAdditiveExpr(ctxt);
84643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
84659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict);
84663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
84673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
84683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
84693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8471afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompEqualityExpr:
84723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
84733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [23]   EqualityExpr ::=   RelationalExpr
84753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | EqualityExpr '=' RelationalExpr
84763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | EqualityExpr '!=' RelationalExpr
84773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  A != B != C is allowed ? Answer from James, yes with
84793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (RelationalExpr = RelationalExpr) = RelationalExpr
84803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  (RelationalExpr != RelationalExpr) != RelationalExpr
84813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  which is basically what got implemented.
84823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8483afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an Equality expression.
84843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
84853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8486afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8487afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) {
8488afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompRelationalExpr(ctxt);
84893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
84903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
84913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) {
84929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int eq;
84939e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
84943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
84953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        if (CUR == '=') eq = 1;
84963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else eq = 0;
84973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
84983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (!eq) NEXT;
84993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8500afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompRelationalExpr(ctxt);
85013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
85029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0);
85033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
85043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
85053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
85063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
85073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8508afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompAndExpr:
85093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
85103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [22]   AndExpr ::=   EqualityExpr
85123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | AndExpr 'and' EqualityExpr
85133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8514afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an AND expression.
85153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8517afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8518afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) {
8519afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompEqualityExpr(ctxt);
85203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
85213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
85223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
85239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
85243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        SKIP(3);
85253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8526afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompEqualityExpr(ctxt);
85273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
85289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0);
85293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
85303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
85313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
85323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
85333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8534591b4be0fe1986b5e71d54c5c063493987ef4285Daniel Veillard * xmlXPathCompileExpr:
85353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
85363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [14]   Expr ::=   OrExpr
85383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [21]   OrExpr ::=   AndExpr
85393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                 | OrExpr 'or' AndExpr
85403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8541afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Parse and compile an expression
85423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8543afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8544afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompileExpr(xmlXPathParserContextPtr ctxt) {
8545afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompAndExpr(ctxt);
85463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    CHECK_ERROR;
85473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
85483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while ((CUR == 'o') && (NXT(1) == 'r')) {
85499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	int op1 = ctxt->comp->last;
85503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        SKIP(2);
85513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
8552afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompAndExpr(ctxt);
85533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
85549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0);
85559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	op1 = ctxt->comp->nbStep;
85563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
85573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
85589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE) {
85599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	/* more ops could be optimized too */
85609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0);
85619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
85623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
85633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
85643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8565afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompPredicate:
85663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
8567d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @filter:  act as a filter
85683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
85693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [8]   Predicate ::=   '[' PredicateExpr ']'
85703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [9]   PredicateExpr ::=   Expr
85713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8572afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a predicate expression
85739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
8574afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8575d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
85769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int op1 = ctxt->comp->last;
85779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
85789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
85799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (CUR != '[') {
85809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
85819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
85829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NEXT;
85839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
85849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
85859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt->comp->last = -1;
8586afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompileExpr(ctxt);
85879e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    CHECK_ERROR;
85889e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
85899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (CUR != ']') {
85909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
85919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
85929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
8593d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (filter)
8594d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
8595d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    else
8596d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
85979e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
85989e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    NEXT;
85999e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    SKIP_BLANKS;
86009e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
86019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
86029e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
8603afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompNodeTest:
86043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
86053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @test:  pointer to a xmlXPathTestVal
86063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @type:  pointer to a xmlXPathTypeVal
86073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @prefix:  placeholder for a possible name prefix
86083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
86093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [7] NodeTest ::=   NameTest
86103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | NodeType '(' ')'
86113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | 'processing-instruction' '(' Literal ')'
86123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
86133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [37] NameTest ::=  '*'
86143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | NCName ':' '*'
86153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		    | QName
86163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [38] NodeType ::= 'comment'
86173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'text'
86183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'processing-instruction'
86193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *		   | 'node'
86203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8621081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the name found and updates @test, @type and @prefix appropriately
86223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
862356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlChar *
8624afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
8625afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	             xmlXPathTypeVal *type, const xmlChar **prefix,
8626afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		     xmlChar *name) {
86273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int blanks;
86283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
86303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	STRANGE;
86313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
86323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
863378637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    *type = (xmlXPathTypeVal) 0;
863478637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    *test = (xmlXPathTestVal) 0;
86353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *prefix = NULL;
86363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
86373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((name == NULL) && (CUR == '*')) {
86393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
86403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * All elements
86413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
86423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
86433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*test = NODE_TEST_ALL;
86443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
86453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
86463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL)
86483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathParseNCName(ctxt);
86493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (name == NULL) {
86503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	XP_ERROR0(XPATH_EXPR_ERROR);
86513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
86523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
865376e95df05556c9610b564b14cf578c8f9e34c9c1William M. Brack    blanks = IS_BLANK_CH(CUR);
86543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
86553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR == '(') {
86563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
86573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
86583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * NodeType or PI search
86593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
86603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (xmlStrEqual(name, BAD_CAST "comment"))
86613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_COMMENT;
86623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "node"))
86633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_NODE;
86643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
86653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_PI;
86663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (xmlStrEqual(name, BAD_CAST "text"))
86673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *type = NODE_TYPE_TEXT;
86683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else {
86693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
86703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
86713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_EXPR_ERROR);
86723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
86733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*test = NODE_TEST_TYPE;
86753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
86763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
86773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*type == NODE_TYPE_PI) {
86783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /*
86793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     * Specific case: search a PI by name.
86803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     */
86813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
86823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
868382e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    name = NULL;
868482e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    if (CUR != ')') {
868582e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		name = xmlXPathParseLiteral(ctxt);
868682e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		CHECK_ERROR 0;
8687ed23b7dc73f6c1146701ece20ed3f03d68366516Daniel Veillard		*test = NODE_TEST_PI;
868882e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard		SKIP_BLANKS;
868982e4971dc2f470c9b6f19cf8b15ff32781067167Daniel Veillard	    }
86903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
86913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR != ')') {
86923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (name != NULL)
86933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
86943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_UNCLOSED_ERROR);
86953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
86963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
86973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(name);
86983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
86993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    *test = NODE_TEST_NAME;
87003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((!blanks) && (CUR == ':')) {
87013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
87023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
8704fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * Since currently the parser context don't have a
8705fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * namespace list associated:
8706fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * The namespace name for this prefix can be computed
8707fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * only at evaluation time. The compilation is done
8708fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	 * outside of any context.
87093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
8710fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#if 0
87113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	*prefix = xmlXPathNsLookup(ctxt->context, name);
87123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (name != NULL)
87133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(name);
87143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*prefix == NULL) {
87153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
87163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8717fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#else
8718fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	*prefix = name;
8719fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard#endif
87203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (CUR == '*') {
87223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    /*
87233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     * All elements
87243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	     */
87253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
87263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    *test = NODE_TEST_ALL;
87273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return(NULL);
87283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
87293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	name = xmlXPathParseNCName(ctxt);
87313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (name == NULL) {
87323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    XP_ERROR0(XPATH_EXPR_ERROR);
87333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
87343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
87353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(name);
87363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
87373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
87383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
87393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathIsAxisName:
87403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @name:  a preparsed name token
87413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [6] AxisName ::=   'ancestor'
87433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'ancestor-or-self'
87443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'attribute'
87453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'child'
87463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'descendant'
87473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'descendant-or-self'
87483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'following'
87493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'following-sibling'
87503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'namespace'
87513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'parent'
87523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'preceding'
87533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'preceding-sibling'
87543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | 'self'
87553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
87563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the axis or 0
87573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
875856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillardstatic xmlXPathAxisVal
87593473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathIsAxisName(const xmlChar *name) {
876078637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal ret = (xmlXPathAxisVal) 0;
87613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    switch (name[0]) {
87623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'a':
87633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "ancestor"))
87643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ANCESTOR;
87653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "ancestor-or-self"))
87663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ANCESTOR_OR_SELF;
87673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "attribute"))
87683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_ATTRIBUTE;
87693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
87703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'c':
87713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "child"))
87723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_CHILD;
87733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
87743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'd':
87753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "descendant"))
87763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_DESCENDANT;
87773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "descendant-or-self"))
87783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_DESCENDANT_OR_SELF;
87793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
87803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'f':
87813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "following"))
87823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_FOLLOWING;
87833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "following-sibling"))
87843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_FOLLOWING_SIBLING;
87853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
87863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'n':
87873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "namespace"))
87883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_NAMESPACE;
87893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
87903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 'p':
87913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "parent"))
87923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PARENT;
87933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "preceding"))
87943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PRECEDING;
87953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "preceding-sibling"))
87963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_PRECEDING_SIBLING;
87973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
87983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	case 's':
87993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (xmlStrEqual(name, BAD_CAST "self"))
88003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		ret = AXIS_SELF;
88013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    break;
88023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
88033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
88043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
88053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
88063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8807afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompStep:
88083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
88093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [4] Step ::=   AxisSpecifier NodeTest Predicate*
88113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | AbbreviatedStep
88123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [12] AbbreviatedStep ::=   '.' | '..'
88143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [5] AxisSpecifier ::= AxisName '::'
88163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  | AbbreviatedAxisSpecifier
88173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * [13] AbbreviatedAxisSpecifier ::= '@'?
88193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Modified for XPtr range support as:
88213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
88223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
88233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedStep
88243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | 'range-to' '(' Expr ')' Predicate*
88253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8826afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile one step in a Location Path
88273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * A location step of . is short for self::node(). This is
88283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * particularly useful in conjunction with //. For example, the
88293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * location path .//para is short for
88303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * self::node()/descendant-or-self::node()/child::para
88313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and so will select all para descendant elements of the context
88323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node.
88333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Similarly, a location step of .. is short for parent::node().
88343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * For example, ../title is short for parent::node()/child::title
88353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * and so will select the title children of the parent of the context
88363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * node.
88373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8838afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8839afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
8840fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
8841fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    int rangeto = 0;
8842fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    int op2 = -1;
8843fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
8844fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard
88453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
88463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '.') && (NXT(1) == '.')) {
88473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP(2);
88483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
88499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT,
88509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
88513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '.') {
88523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	NEXT;
88533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
88543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
88553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlChar *name = NULL;
88563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	const xmlChar *prefix = NULL;
88573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathTestVal test;
885878637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack	xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
88593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathTypeVal type;
8860d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	int op1;
88613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
88623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
88633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * The modification needed for XPointer change to the production
88643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
88653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef LIBXML_XPTR_ENABLED
8866fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	if (ctxt->xptr) {
88673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    name = xmlXPathParseNCName(ctxt);
88683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
8869fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard                op2 = ctxt->comp->last;
88703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlFree(name);
88713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
88723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (CUR != '(') {
88733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    XP_ERROR(XPATH_EXPR_ERROR);
88743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
88753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
88763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
88773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8878afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		xmlXPathCompileExpr(ctxt);
8879fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		/* PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, ctxt->comp->last, 0, 0); */
88803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		CHECK_ERROR;
88813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
88823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
88833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (CUR != ')') {
88843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    XP_ERROR(XPATH_EXPR_ERROR);
88853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
88863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
8887fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		rangeto = 1;
88883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		goto eval_predicates;
88893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
88903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
88913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
88922156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	if (CUR == '*') {
88932156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    axis = AXIS_CHILD;
88942156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	} else {
88952156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (name == NULL)
88962156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		name = xmlXPathParseNCName(ctxt);
88972156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    if (name != NULL) {
88982156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = xmlXPathIsAxisName(name);
88992156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		if (axis != 0) {
89002156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    SKIP_BLANKS;
89012156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    if ((CUR == ':') && (NXT(1) == ':')) {
89022156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			SKIP(2);
89032156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			xmlFree(name);
89042156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			name = NULL;
89052156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    } else {
89062156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			/* an element name can conflict with an axis one :-\ */
89072156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard			axis = AXIS_CHILD;
89082156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		    }
89093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
89103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    axis = AXIS_CHILD;
89113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
89122156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard	    } else if (CUR == '@') {
89132156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		NEXT;
89142156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = AXIS_ATTRIBUTE;
89153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else {
89162156a56bcbf5d83fb3d694123be01beebf84d273Daniel Veillard		axis = AXIS_CHILD;
89173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
89183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
89193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	CHECK_ERROR;
89213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8922afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
89233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (test == 0)
89243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    return;
89253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
89273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
89283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"Basis : computing new set\n");
89293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
89309e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
89313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
89323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext, "Basis : ");
8933fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	if (ctxt->value == NULL)
8934fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "no value\n");
8935fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	else if (ctxt->value->nodesetval == NULL)
8936fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "Empty\n");
8937fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	else
8938fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval);
89393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
89403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89415bb9ccd56a812b65e94e71477389be7826203649Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
89423473f88a7abdf4e585e267288fb77e898c580d2bOwen Tayloreval_predicates:
89435bb9ccd56a812b65e94e71477389be7826203649Daniel Veillard#endif
8944d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	op1 = ctxt->comp->last;
8945d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	ctxt->comp->last = -1;
8946d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
89473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
89483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (CUR == '[') {
8949d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    xmlXPathCompPredicate(ctxt, 0);
89503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
8951d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
8952fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
8953fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	if (rangeto) {
8954fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0);
8955fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	} else
8956fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard#endif
8957fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	    PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
8958fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard			   test, type, (void *)prefix, (void *)name);
8959d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
89603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
89613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef DEBUG_STEP
89623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlGenericError(xmlGenericErrorContext, "Step : ");
8963fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    if (ctxt->value == NULL)
8964fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "no value\n");
8965fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    else if (ctxt->value->nodesetval == NULL)
8966fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericError(xmlGenericErrorContext, "Empty\n");
8967fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard    else
8968fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard	xmlGenericErrorContextNodeSet(xmlGenericErrorContext,
8969fd0c3ebb0931af19ab3b4da3493f027fca849cf7Daniel Veillard		ctxt->value->nodesetval);
89703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
89713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
89723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
89733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
8974afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompRelativeLocationPath:
89753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
89763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
89773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [3]   RelativeLocationPath ::=   Step
89783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | RelativeLocationPath '/' Step
89793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedRelativeLocationPath
89803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [11]  AbbreviatedRelativeLocationPath ::=   RelativeLocationPath '//' Step
89813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8982afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a relative location path.
89833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
8984afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
8985afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompRelativeLocationPath
89863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor(xmlXPathParserContextPtr ctxt) {
89873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
89883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((CUR == '/') && (NXT(1) == '/')) {
89893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP(2);
89903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
89919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
89929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		         NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
89933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if (CUR == '/') {
89943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
89953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
89963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
8997afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompStep(ctxt);
89983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
89993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    while (CUR == '/') {
90003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((CUR == '/') && (NXT(1) == '/')) {
90013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP(2);
90023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
90039e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
90043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9005afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompStep(ctxt);
90063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	} else if (CUR == '/') {
90073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    NEXT;
90083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    SKIP_BLANKS;
9009afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    xmlXPathCompStep(ctxt);
90103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
90113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	SKIP_BLANKS;
90123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
90133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
90143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
90153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
9016afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathCompLocationPath:
90173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath Parser context
90183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
90193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [1]   LocationPath ::=   RelativeLocationPath
90203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbsoluteLocationPath
90213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [2]   AbsoluteLocationPath ::=   '/' RelativeLocationPath?
90223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                     | AbbreviatedAbsoluteLocationPath
90233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *  [10]   AbbreviatedAbsoluteLocationPath ::=
90243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                           '//' RelativeLocationPath
90253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
9026afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile a location path
9027afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
90283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * // is short for /descendant-or-self::node()/. For example,
90293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * //para is short for /descendant-or-self::node()/child::para and
90303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * so will select any para element in the document (even a para element
90313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * that is a document element will be selected by //para since the
90323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * document element node is a child of the root node); div//para is
90333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * short for div/descendant-or-self::node()/child::para and so will
90343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * select all para descendants of div children.
90353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
9036afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardstatic void
9037afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
90383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    SKIP_BLANKS;
90393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (CUR != '/') {
9040afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        xmlXPathCompRelativeLocationPath(ctxt);
90413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
90423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (CUR == '/') {
90433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if ((CUR == '/') && (NXT(1) == '/')) {
90443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP(2);
90453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		SKIP_BLANKS;
90469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
90479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9048afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		xmlXPathCompRelativeLocationPath(ctxt);
90493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    } else if (CUR == '/') {
90503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		NEXT;
9051608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		SKIP_BLANKS;
9052608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		if ((CUR != 0 ) &&
9053d1757abcb891e01a9017f4aad041cc306d0d467bWilliam M. Brack		    ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') ||
9054608ad0791b3b35072c8021ea4f66cf9d700394b9Daniel Veillard		     (CUR == '@') || (CUR == '*')))
9055afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard		    xmlXPathCompRelativeLocationPath(ctxt);
90563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
90573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
90583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
90593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
90603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
90619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/************************************************************************
90629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *									*
90639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * 		XPath precompiled expression evaluation			*
90649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *									*
90659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard ************************************************************************/
90669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9067f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9068d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
9069d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
90709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
9071d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * xmlXPathNodeCollectAndTest:
9072d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath Parser context
9073d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @op:  the XPath precompiled step operation
9074f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  pointer to the first element in document order
9075f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  pointer to the last element in document order
90769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
9077d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * This is the function implementing a step: based on the current list
9078d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * of nodes, it builds up a new list, looking at all nodes under that
9079081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * axis and selecting them. It also does the predicate filtering
9080d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
9081d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * Pushes the new NodeSet resulting from the search.
9082f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9083081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the number of nodes traversed
90849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
9085f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9086d8df6c0e8c883e1d618388d266015dda36731440Daniel VeillardxmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
9087f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                           xmlXPathStepOpPtr op,
9088f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard			   xmlNodePtr * first, xmlNodePtr * last)
9089f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
909078637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
909178637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
909278637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
9093d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    const xmlChar *prefix = op->value4;
9094d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    const xmlChar *name = op->value5;
9095e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    const xmlChar *URI = NULL;
90969e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
9097d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9098f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int n = 0;
9099d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9100f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int i, t = 0;
9101d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodeSetPtr ret, list;
9102d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathTraversalFunction next = NULL;
9103f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
910475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    xmlNodeSetPtr (*mergeNodeSet) (xmlNodeSetPtr, xmlNodeSetPtr);
9105d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodePtr cur = NULL;
9106d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathObjectPtr obj;
9107d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodeSetPtr nodelist;
9108d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlNodePtr tmp;
9109d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    CHECK_TYPE0(XPATH_NODESET);
9111d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    obj = valuePop(ctxt);
9112d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    addNode = xmlXPathNodeSetAdd;
911375be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard    mergeNodeSet = xmlXPathNodeSetMerge;
9114e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    if (prefix != NULL) {
9115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        URI = xmlXPathNsLookup(ctxt->context, prefix);
91162c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack        if (URI == NULL) {
91172c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	    xmlXPathFreeObject(obj);
9118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
91192c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	}
9120e043ee17c26c41c6d50c38d07d69dd1900d8ad01Daniel Veillard    }
9121d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "new step : ");
9123d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9124d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (axis) {
9125d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ANCESTOR:
9126d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
9128d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9129f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestor;
9131f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9132d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ANCESTOR_OR_SELF:
9133d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9134f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9135f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'ancestors-or-self' ");
9136d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestorOrSelf;
9139f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9140d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_ATTRIBUTE:
9141d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9142f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
9143d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9144f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9145f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9146f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAttribute;
914775be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
9148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9149d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_CHILD:
9150d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9151f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
9152d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9153f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9154f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextChild;
915575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
9156f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9157d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_DESCENDANT:
9158d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9159f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
9160d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9161f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9162f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendant;
9163f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9164d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_DESCENDANT_OR_SELF:
9165d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9166f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9167f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'descendant-or-self' ");
9168d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9169f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9170f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendantOrSelf;
9171f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9172d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_FOLLOWING:
9173d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9174f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
9175d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9176f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9177f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowing;
9178f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9179d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_FOLLOWING_SIBLING:
9180d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9181f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9182f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'following-siblings' ");
9183d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9184f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9185f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowingSibling;
9186f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9187d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_NAMESPACE:
9188d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9189f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
9190d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9191f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9192f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9193f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
919475be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
9195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9196d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PARENT:
9197d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
9199d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9200f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9201f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextParent;
9202f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9203d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PRECEDING:
9204d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9205f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
9206d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9207f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingInternal;
9209f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9210d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_PRECEDING_SIBLING:
9211d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9212f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'preceding-sibling' ");
9214d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9215f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9216f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingSibling;
9217f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9218d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        case AXIS_SELF:
9219d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9220f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
9221d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9222f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9224f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextSelf;
922575be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard	    mergeNodeSet = xmlXPathNodeSetMergeUnique;
9226f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9227d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
92282c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack    if (next == NULL) {
92292c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	xmlXPathFreeObject(obj);
9230f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
92312c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack    }
9232d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9233d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    nodelist = obj->nodesetval;
9234d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    if (nodelist == NULL) {
9235f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlXPathFreeObject(obj);
9236f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
9237f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
9238d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
9239d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    addNode = xmlXPathNodeSetAddUnique;
9240d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ret = NULL;
9241d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9242d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9243f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    " context contains %d nodes\n", nodelist->nodeNr);
9244d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (test) {
9245f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NONE:
9246f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9247f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for none !!!\n");
9248f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9249f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_TYPE:
9250f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9251f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for type %d\n", type);
9252f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9253f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_PI:
9254f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for PI !!!\n");
9256f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9257f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_ALL:
9258f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9259f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for *\n");
9260f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9261f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NS:
9262f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9263f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for namespace %s\n",
9264f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            prefix);
9265f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9266f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NAME:
9267f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9268f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for name %s\n", name);
9269f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (prefix != NULL)
9270f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlGenericError(xmlGenericErrorContext,
9271f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                "           with namespace %s\n", prefix);
9272f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9273d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
9274d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "Testing : ");
9275d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9276d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    /*
9277d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * 2.3 Node Tests
9278d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For the attribute axis, the principal node type is attribute.
9279d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For the namespace axis, the principal node type is namespace.
9280d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *  - For other axes, the principal node type is element.
9281d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     *
9282d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * A node test * is true for any node of the
9283cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard     * principal node type. For example, child::* will
9284d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     * select all element children of the context node
9285d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard     */
9286d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    tmp = ctxt->context->node;
9287f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < nodelist->nodeNr; i++) {
9288d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard        ctxt->context->node = nodelist->nodeTab[i];
9289d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9290f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = NULL;
9291f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        list = xmlXPathNodeSetCreate(NULL);
9292f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        do {
9293f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur = next(ctxt, cur);
9294f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (cur == NULL)
9295f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9296f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((first != NULL) && (*first == cur))
9297f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9298f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9299f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (first != NULL) && (*first != NULL) &&
9300f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(*first, cur) >= 0))
9301f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9302f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((last != NULL) && (*last == cur))
9303f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9304f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9305f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(last != NULL) && (*last != NULL) &&
9306f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(cur, *last) >= 0))
9307f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9308d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard            t++;
9309f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP
9310d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard            xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
9311d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9312f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            switch (test) {
9313d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_NONE:
9314f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = tmp;
93152c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack		    xmlXPathFreeObject(obj);
9316f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    STRANGE return(t);
9317d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_TYPE:
9318f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((cur->type == type) ||
9319f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ((type == NODE_TYPE_NODE) &&
9320f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         ((cur->type == XML_DOCUMENT_NODE) ||
9321f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_HTML_DOCUMENT_NODE) ||
9322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_ELEMENT_NODE) ||
9323f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Sanin                          (cur->type == XML_NAMESPACE_DECL) ||
9324f8cb6dda89d3866c796c8cfb2ba377d12822bf24Aleksey Sanin                          (cur->type == XML_ATTRIBUTE_NODE) ||
9325f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_PI_NODE) ||
9326f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_COMMENT_NODE) ||
9327f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_CDATA_SECTION_NODE) ||
93287583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard                          (cur->type == XML_TEXT_NODE))) ||
93297583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard			((type == NODE_TYPE_TEXT) &&
93307583a59b5a0792599a181f77aaf0a39749fada27Daniel Veillard			 (cur->type == XML_CDATA_SECTION_NODE))) {
9331d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9332d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                        n++;
9333d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9334f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        addNode(list, cur);
9335f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9336f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9337d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_PI:
9338f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (cur->type == XML_PI_NODE) {
9339f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((name != NULL) &&
9340f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (!xmlStrEqual(name, cur->name)))
9341f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9342d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9343f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9344d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9345f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        addNode(list, cur);
9346f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9347f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9348d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_ALL:
9349f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (axis == AXIS_ATTRIBUTE) {
9350f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ATTRIBUTE_NODE) {
9351d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9352f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9353d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9354f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9355f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9356f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else if (axis == AXIS_NAMESPACE) {
9357f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_NAMESPACE_DECL) {
9358d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9359f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9360d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9361044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard                            xmlXPathNodeSetAddNs(list, ctxt->context->node,
9362044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				                 (xmlNsPtr) cur);
9363f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9364f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else {
9365f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ELEMENT_NODE) {
9366f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (prefix == NULL) {
9367d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9368f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9369d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9370f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9371f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            } else if ((cur->ns != NULL) &&
9372f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                       (xmlStrEqual(URI, cur->ns->href))) {
9373d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9374f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9375d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9376f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9377f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9378f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9379f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9380f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9381f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NS:{
9382f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        TODO;
9383f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        break;
9384f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9385d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard                case NODE_TEST_NAME:
9386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    switch (cur->type) {
9387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ELEMENT_NODE:
9388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (xmlStrEqual(name, cur->name)) {
9389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (prefix == NULL) {
9390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (cur->ns == NULL) {
9391d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9392f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9393d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        addNode(list, cur);
9395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                } else {
9397f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if ((cur->ns != NULL) &&
9398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        (xmlStrEqual(URI,
9399f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     cur->ns->href))) {
9400d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9402d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9403f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        addNode(list, cur);
9404f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9405f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ATTRIBUTE_NODE:{
9409f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlAttrPtr attr = (xmlAttrPtr) cur;
9410f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9411f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (xmlStrEqual(name, attr->name)) {
9412f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (prefix == NULL) {
9413f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns == NULL) ||
9414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (attr->ns->prefix == NULL)) {
9415d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9416f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9417d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9418f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list,
9419f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    (xmlNodePtr) attr);
9420f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9421f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    } else {
9422f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns != NULL) &&
9423f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (xmlStrEqual(URI,
9424f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         attr->ns->
9425f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         href))) {
9426d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9427f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9428d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list,
9430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    (xmlNodePtr) attr);
9431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9432f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9433f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9434f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                break;
9435f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9436f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_NAMESPACE_DECL:
9437f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (cur->type == XML_NAMESPACE_DECL) {
9438f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlNsPtr ns = (xmlNsPtr) cur;
9439f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9440f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if ((ns->prefix != NULL) && (name != NULL)
9441f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    && (xmlStrEqual(ns->prefix, name))) {
94428b8d2254fa1604efd37b3ba92eaeb2e40b2909a8Daniel Veillard#ifdef DEBUG_STEP
9443f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    n++;
94448b8d2254fa1604efd37b3ba92eaeb2e40b2909a8Daniel Veillard#endif
9445044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				    xmlXPathNodeSetAddNs(list,
9446044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					ctxt->context->node, (xmlNsPtr) cur);
9447f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9450f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        default:
9451f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9452f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9453f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9454f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9455f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9456f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } while (cur != NULL);
9457f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9458f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        /*
9459f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard         * If there is some predicate filtering do it now
9460f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard         */
94616fbcf42aa301dca50737c65fb738752328ca3a4cDaniel Veillard        if ((op->ch2 != -1) && (list != NULL) && (list->nodeNr > 0)) {
9462f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathObjectPtr obj2;
9463f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9464f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathWrapNodeSet(list));
9465f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch2]);
9466f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9467f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            obj2 = valuePop(ctxt);
9468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            list = obj2->nodesetval;
9469f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            obj2->nodesetval = NULL;
9470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(obj2);
94712c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	    if (ctxt->error != XPATH_EXPRESSION_OK) {
94722c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack		xmlXPathFreeObject(obj);
94732c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack		xmlXPathFreeNodeSet(list);
94742c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack		return(0);
94752c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	    }
9476f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
9477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        if (ret == NULL) {
9478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ret = list;
9479f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } else {
948075be0130855fe02d238bbbf19a04d3c5eb45f494Daniel Veillard            ret = mergeNodeSet(ret, list);
9481f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeNodeSet(list);
9482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        }
9483d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    }
9484d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    ctxt->context->node = tmp;
9485d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#ifdef DEBUG_STEP
9486d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9487f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "\nExamined %d nodes, found %d nodes at that step\n",
9488f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    t, n);
9489d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard#endif
9490d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(ret));
94910ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->boolval) && (obj->user != NULL)) {
94920ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->boolval = 1;
94930ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->user = obj->user;
94940ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->user = NULL;
94950ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->boolval = 0;
94960ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    }
94970ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    xmlXPathFreeObject(obj);
9498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(t);
9499d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard}
9500d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9501d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard/**
9502f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathNodeCollectAndTestNth:
9503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath Parser context
9504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  the XPath precompiled step operation
9505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @indx:  the index to collect
9506f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  pointer to the first element in document order
9507f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  pointer to the last element in document order
9508f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9509f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * This is the function implementing a step: based on the current list
9510f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * of nodes, it builds up a new list, looking at all nodes under that
9511081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * axis and selecting them. It also does the predicate filtering
9512f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9513f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Pushes the new NodeSet resulting from the search.
9514f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of node traversed
9515f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
9516f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9517f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathNodeCollectAndTestNth(xmlXPathParserContextPtr ctxt,
9518f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlXPathStepOpPtr op, int indx,
9519f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                              xmlNodePtr * first, xmlNodePtr * last)
9520f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
952178637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
952278637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
952378637da0ea1c833dfdfad87a9aa5bea14510d08aWilliam M. Brack    xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
9524f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *prefix = op->value4;
9525f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *name = op->value5;
9526f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    const xmlChar *URI = NULL;
9527f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int n = 0, t = 0;
9528f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9529f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int i;
9530f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodeSetPtr list;
9531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathTraversalFunction next = NULL;
9532f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
9533f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr cur = NULL;
9534f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr obj;
9535f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodeSetPtr nodelist;
9536f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlNodePtr tmp;
9537f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9538f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    CHECK_TYPE0(XPATH_NODESET);
9539f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    obj = valuePop(ctxt);
9540f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    addNode = xmlXPathNodeSetAdd;
9541f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (prefix != NULL) {
9542f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        URI = xmlXPathNsLookup(ctxt->context, prefix);
95432c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack        if (URI == NULL) {
95442c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	    xmlXPathFreeObject(obj);
9545f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
95462c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	}
9547f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9548f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9549f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "new step : ");
9550f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (first != NULL) {
9551f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (*first != NULL)
9552f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "first = %s ",
9553f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    (*first)->name);
9554f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	else
9555f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "first = NULL ");
9556f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9557f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (last != NULL) {
9558f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	if (*last != NULL)
9559f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "last = %s ",
9560f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		    (*last)->name);
9561f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	else
9562f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    xmlGenericError(xmlGenericErrorContext, "last = NULL ");
9563f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9565f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (axis) {
9566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ANCESTOR:
9567f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9568f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'ancestors' ");
9569f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9570f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9571f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestor;
9572f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9573f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ANCESTOR_OR_SELF:
9574f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9575f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9576f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'ancestors-or-self' ");
9577f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9578f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9579f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAncestorOrSelf;
9580f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9581f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_ATTRIBUTE:
9582f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9583f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'attributes' ");
9584f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9585f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9586f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9587f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextAttribute;
9588f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9589f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_CHILD:
9590f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9591f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'child' ");
9592f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9593f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9594f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextChild;
9595f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9596f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_DESCENDANT:
9597f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9598f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'descendant' ");
9599f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9600f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9601f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendant;
9602f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9603f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_DESCENDANT_OR_SELF:
9604f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9605f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9606f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'descendant-or-self' ");
9607f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9608f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9609f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextDescendantOrSelf;
9610f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9611f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_FOLLOWING:
9612f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9613f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'following' ");
9614f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9615f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9616f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowing;
9617f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9618f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_FOLLOWING_SIBLING:
9619f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9620f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9621f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'following-siblings' ");
9622f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9623f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9624f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextFollowingSibling;
9625f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9626f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_NAMESPACE:
9627f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9628f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'namespace' ");
9629f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9630f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9631f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9632f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
9633f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9634f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PARENT:
9635f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9636f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'parent' ");
9637f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9638f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9639f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextParent;
9640f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9641f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PRECEDING:
9642f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9643f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'preceding' ");
9644f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9645f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9646f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingInternal;
9647f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9648f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_PRECEDING_SIBLING:
9649f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9650f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9651f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "axis 'preceding-sibling' ");
9652f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9653f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9654f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextPrecedingSibling;
9655f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9656f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case AXIS_SELF:
9657f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9658f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext, "axis 'self' ");
9659f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9660f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            first = NULL;
9661f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    last = NULL;
9662f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            next = xmlXPathNextSelf;
9663f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
96652c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack    if (next == NULL) {
96662c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack	xmlXPathFreeObject(obj);
9667f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
96682c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack    }
9669f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9670f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    nodelist = obj->nodesetval;
9671f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (nodelist == NULL) {
9672f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        xmlXPathFreeObject(obj);
9673f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
9674f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        return(0);
9675f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9676f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    addNode = xmlXPathNodeSetAddUnique;
9677f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9678f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9679f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    " context contains %d nodes\n", nodelist->nodeNr);
9680f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (test) {
9681f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NONE:
9682f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9683f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for none !!!\n");
9684f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9685f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_TYPE:
9686f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9687f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for type %d\n", type);
9688f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9689f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_PI:
9690f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9691f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for PI !!!\n");
9692f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9693f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_ALL:
9694f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9695f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for *\n");
9696f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9697f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NS:
9698f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9699f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for namespace %s\n",
9700f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            prefix);
9701f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9702f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case NODE_TEST_NAME:
9703f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlGenericError(xmlGenericErrorContext,
9704f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            "           searching for name %s\n", name);
9705f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (prefix != NULL)
9706f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlGenericError(xmlGenericErrorContext,
9707f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                "           with namespace %s\n", prefix);
9708f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            break;
9709f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9710f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext, "Testing : ");
9711f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9712f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    /*
9713f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * 2.3 Node Tests
9714f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For the attribute axis, the principal node type is attribute.
9715f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For the namespace axis, the principal node type is namespace.
9716f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *  - For other axes, the principal node type is element.
9717f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     *
9718f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * A node test * is true for any node of the
9719cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard     * principal node type. For example, child::* will
9720f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     * select all element children of the context node
9721f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard     */
9722f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    tmp = ctxt->context->node;
9723f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    list = xmlXPathNodeSetCreate(NULL);
9724f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    for (i = 0; i < nodelist->nodeNr; i++) {
9725f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        ctxt->context->node = nodelist->nodeTab[i];
9726f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9727f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        cur = NULL;
9728f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        n = 0;
9729f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        do {
9730f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur = next(ctxt, cur);
9731f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (cur == NULL)
9732f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                break;
9733f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((first != NULL) && (*first == cur))
9734f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9735f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9736f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (first != NULL) && (*first != NULL) &&
9737f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(*first, cur) >= 0))
9738f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9739f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if ((last != NULL) && (*last == cur))
9740f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9741f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (((t % 256) == 0) &&
9742f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	        (last != NULL) && (*last != NULL) &&
9743f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		(xmlXPathCmpNodes(cur, *last) >= 0))
9744f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		break;
9745f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            t++;
9746f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            switch (test) {
9747f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NONE:
9748f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = tmp;
9749f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    STRANGE return(0);
9750f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_TYPE:
9751f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((cur->type == type) ||
9752f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ((type == NODE_TYPE_NODE) &&
9753f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         ((cur->type == XML_DOCUMENT_NODE) ||
9754f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_HTML_DOCUMENT_NODE) ||
9755f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_ELEMENT_NODE) ||
9756f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_PI_NODE) ||
9757f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_COMMENT_NODE) ||
9758f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                          (cur->type == XML_CDATA_SECTION_NODE) ||
97598606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard                          (cur->type == XML_TEXT_NODE))) ||
97608606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard			((type == NODE_TYPE_TEXT) &&
97618606bbbc0a04293afd7541033d6a83c4943a6f02Daniel Veillard			 (cur->type == XML_CDATA_SECTION_NODE))) {
9762f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9763f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (n == indx)
9764f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9765f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9766f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9767f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_PI:
9768f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (cur->type == XML_PI_NODE) {
9769f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((name != NULL) &&
9770f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (!xmlStrEqual(name, cur->name)))
9771f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9772f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        n++;
9773f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (n == indx)
9774f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            addNode(list, cur);
9775f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9776f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9777f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_ALL:
9778f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (axis == AXIS_ATTRIBUTE) {
9779f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ATTRIBUTE_NODE) {
9780f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9781f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (n == indx)
9782f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                addNode(list, cur);
9783f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9784f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else if (axis == AXIS_NAMESPACE) {
9785f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_NAMESPACE_DECL) {
9786f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            n++;
9787f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (n == indx)
9788044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard				xmlXPathNodeSetAddNs(list, ctxt->context->node,
9789044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard						     (xmlNsPtr) cur);
9790f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9791f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    } else {
9792f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (cur->type == XML_ELEMENT_NODE) {
9793f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (prefix == NULL) {
9794f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9795f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (n == indx)
9796f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    addNode(list, cur);
9797f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            } else if ((cur->ns != NULL) &&
9798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                       (xmlStrEqual(URI, cur->ns->href))) {
9799f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                n++;
9800f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (n == indx)
9801f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    addNode(list, cur);
9802f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9803f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9804f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NS:{
9807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        TODO;
9808f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        break;
9809f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9810f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                case NODE_TEST_NAME:
9811f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    switch (cur->type) {
9812f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ELEMENT_NODE:
9813f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (xmlStrEqual(name, cur->name)) {
9814f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (prefix == NULL) {
9815f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (cur->ns == NULL) {
9816f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9817f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if (n == indx)
9818f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list, cur);
9819f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9820f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                } else {
9821f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if ((cur->ns != NULL) &&
9822f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        (xmlStrEqual(URI,
9823f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     cur->ns->href))) {
9824f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        n++;
9825f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if (n == indx)
9826f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            addNode(list, cur);
9827f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9828f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9829f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9830f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_ATTRIBUTE_NODE:{
9832f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlAttrPtr attr = (xmlAttrPtr) cur;
9833f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9834f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if (xmlStrEqual(name, attr->name)) {
9835f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (prefix == NULL) {
9836f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns == NULL) ||
9837f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (attr->ns->prefix == NULL)) {
9838f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9839f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            if (n == indx)
9840f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                addNode(list, cur);
9841f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9842f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    } else {
9843f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        if ((attr->ns != NULL) &&
9844f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            (xmlStrEqual(URI,
9845f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         attr->ns->
9846f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                         href))) {
9847f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            n++;
9848f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            if (n == indx)
9849f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                addNode(list, cur);
9850f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        }
9851f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    }
9852f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9853f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                break;
9854f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        case XML_NAMESPACE_DECL:
9856f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            if (cur->type == XML_NAMESPACE_DECL) {
9857f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlNsPtr ns = (xmlNsPtr) cur;
9858f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9859f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                if ((ns->prefix != NULL) && (name != NULL)
9860f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    && (xmlStrEqual(ns->prefix, name))) {
9861f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    n++;
9862f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                    if (n == indx)
9863044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					xmlXPathNodeSetAddNs(list,
9864044fc6b7476798cbb95277b4905e5111d7c2775dDaniel Veillard					   ctxt->context->node, (xmlNsPtr) cur);
9865f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                }
9866f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            }
9867f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9868f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        default:
9869f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            break;
9870f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9871f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9872f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    break;
9873f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9874f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        } while (n < indx);
9875f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
9876f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    ctxt->context->node = tmp;
9877f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_STEP_NTH
9878f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlGenericError(xmlGenericErrorContext,
9879f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "\nExamined %d nodes, found %d nodes at that step\n",
9880f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    t, list->nodeNr);
9881f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
9882f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    valuePush(ctxt, xmlXPathWrapNodeSet(list));
98830ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    if ((obj->boolval) && (obj->user != NULL)) {
98840ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->boolval = 1;
98850ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	ctxt->value->user = obj->user;
98860ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->user = NULL;
98870ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard	obj->boolval = 0;
98880ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    }
98890ab5caba5b47a2cdafa83059ec3e02fde78d6262Daniel Veillard    xmlXPathFreeObject(obj);
9890f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return(t);
9891f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
9892f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9893f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
9894f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEvalFirst:
9895d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
9896d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard * @op:  an XPath compiled operation
9897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @first:  the first elem found so far
9898d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard *
9899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation searching only the first
9900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * element in document order
9901f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
9902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Returns the number of examined objects.
9903d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard */
9904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
9905f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
9906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathStepOpPtr op, xmlNodePtr * first)
9907f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
9908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0, cur;
9909d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathCompExprPtr comp;
9910d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
9911d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard
9912556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
9913d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    comp = ctxt->comp;
9914d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard    switch (op->op) {
9915f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
9916f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9917f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
9918f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total =
9919f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
9920f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        first);
9921556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9922f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
9923f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
9924f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
9925f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
9926f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9927f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * limit tree traversing to first node in the result
9928f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9929f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
9930f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                *first = ctxt->value->nodesetval->nodeTab[0];
9931f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
9932f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur =
9933f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
9934f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        first);
9935556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9936f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9937f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
9938f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9939f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
9940f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
9941f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9942f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
9943f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
9944f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
9945f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
9946f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            /* optimizer */
9947f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (total > cur)
9948f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		xmlXPathCompSwap(op);
9949f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total + cur);
9950f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
9951f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
9952f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
9953f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
9954f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9955f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9956556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9957f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9959556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
9961f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9962f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
9963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
9964f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9965556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
9967f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
9968556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
9969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
9970f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
9971f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
9972f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
9973f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
9974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9975f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
9976556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
9977f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9978f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
9979f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
9980f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
9981f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
9982f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
9983f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
9984f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
9985f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
9986f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
9987f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
9988f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9989f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
9990f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
9991f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
9992f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
9993f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
9994f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathNodeCollectAndTestNth(ctxt, op, indx,
9995f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                          first, NULL);
9996f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
9997f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
9998f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
9999f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10000f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL);
10001f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10002f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10003f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
10004f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
10005f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
10006f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10007f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
10008f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10009f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total +=
10010f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
10011f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            first);
10012556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10013f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10014f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10015f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL))
10016f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10017f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10018f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        default:
10019f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (xmlXPathCompOpEval(ctxt, op));
10020f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10021f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
1002242596ad20cdf1925dd79ea801cbe598b6e7b7aecDaniel Veillard
10023f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
10024f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEvalLast:
10025f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
10026f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  an XPath compiled operation
10027f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @last:  the last elem found so far
10028f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
10029f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation searching only the last
10030f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * element in document order
10031f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
10032081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the number of nodes traversed
10033f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
10034f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
10035f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
10036f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                       xmlNodePtr * last)
10037f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
10038f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0, cur;
10039f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathCompExprPtr comp;
10040f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
10041ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack    xmlNodePtr bak;
10042ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack    xmlDocPtr bakd;
10043ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack    int pp;
10044ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack    int cs;
100459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10046556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
10047f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp = ctxt->comp;
10048f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (op->op) {
10049f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
10050f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10051f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
10052ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    bakd = ctxt->context->doc;
10053ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    bak = ctxt->context->node;
10054ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    pp = ctxt->context->proximityPosition;
10055ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    cs = ctxt->context->contextSize;
10056f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total =
10057f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
10058556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10059f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10060f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10061f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
10062f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
10063f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10064f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * limit tree traversing to first node in the result
10065f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10066f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10067f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                *last =
10068f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->value->nodesetval->nodeTab[ctxt->value->
10069f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     nodesetval->nodeNr -
10070f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                     1];
10071f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10072ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    ctxt->context->doc = bakd;
10073ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    ctxt->context->node = bak;
10074ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    ctxt->context->proximityPosition = pp;
10075ce4fc56e1b56253ae794b47515948f3bc3142024William M. Brack	    ctxt->context->contextSize = cs;
10076f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            cur =
10077f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
10078556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10079f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10080f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10081f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL)
10082f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval->nodeNr >= 1)) {
10083f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10084f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10085f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
10086f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10087f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10088f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10089f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10090f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
10091f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
10092f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10093f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10094f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            /* optimizer */
10095f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	    if (total > cur)
10096f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard		xmlXPathCompSwap(op);
10097f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total + cur);
10098f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
10099f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
10100f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10101f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
10102f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10103f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10104556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10105f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10106f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10107556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10108f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
10109f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10110f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
10111f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10112f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10113556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10114f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10115f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10116556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10117f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
10118f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10119f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
10120f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
10121f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (0);
10122f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10123f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10124556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10125f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10126f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10127f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
10128f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10129f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
10130f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
10131f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
10132f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
10133f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
10134f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
10135f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10136f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10137f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
10138f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
10139f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
10140f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10141f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
10142f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10143f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathNodeCollectAndTestNth(ctxt, op,
10144f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              indx, NULL,
10145f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              last);
10146f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10147f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10148f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10149f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10150f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last);
10151f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10152f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10153f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
10154f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
10155f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
10156f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10157f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
10158f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10159f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total +=
10160f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1],
10161f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                           last);
10162556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10163f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL)
10164f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->type == XPATH_NODESET)
10165f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                && (ctxt->value->nodesetval != NULL))
10166f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10167f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10168f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        default:
10169f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (xmlXPathCompOpEval(ctxt, op));
10170f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
10171f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard}
101729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10173f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard/**
10174f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * xmlXPathCompOpEval:
10175f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @ctxt:  the XPath parser context with the compiled expression
10176f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * @op:  an XPath compiled operation
10177f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard *
10178f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard * Evaluate the Precompiled XPath operation
10179081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack * Returns the number of nodes traversed
10180f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard */
10181f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillardstatic int
10182f06307e2c172284bb41376c396f757bdac9bdd19Daniel VeillardxmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
10183f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard{
10184f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int total = 0;
10185f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    int equal, ret;
10186f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathCompExprPtr comp;
10187f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    xmlXPathObjectPtr arg1, arg2;
101887089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard    xmlNodePtr bak;
101897089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard    xmlDocPtr bakd;
101906000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack    int pp;
10191692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack    int cs;
101929e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10193556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard    CHECK_ERROR0;
10194f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp = ctxt->comp;
10195f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    switch (op->op) {
10196f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_END:
10197f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (0);
10198f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_AND:
101997089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
102007089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
102016000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10202692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10203f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10204556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10205f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
10206f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
10207f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10208f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
102097089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
102107089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
102116000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10212692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10213f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10214556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    if (ctxt->error) {
10215556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathFreeObject(arg2);
10216556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		return(0);
10217556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    }
10218f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
10219f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10220f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->boolval &= arg2->boolval;
10221f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10222f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10223f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10224f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_OR:
102257089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
102267089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
102276000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10228692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10229f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10230556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10231f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
10232f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
10233f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10234f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
102357089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
102367089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
102376000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10238692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10239f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10240556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    if (ctxt->error) {
10241556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathFreeObject(arg2);
10242556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		return(0);
10243556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    }
10244f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathBooleanFunction(ctxt, 1);
10245f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10246f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->boolval |= arg2->boolval;
10247f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10248f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10249f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10250f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_EQUAL:
102517089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
102527089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
102536000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10254692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10255f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10256556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
102577089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
102587089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
102596000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10260692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10261f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10262556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
102630c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    if (op->value)
102640c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack        	equal = xmlXPathEqualValues(ctxt);
102650c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    else
102660c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack		equal = xmlXPathNotEqualValues(ctxt);
102670c022ad8234a9228288c651f5e6a9bce7efcd789William M. Brack	    valuePush(ctxt, xmlXPathNewBoolean(equal));
10268f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10269f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_CMP:
102707089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
102717089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
102726000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10273692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10274f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10275556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
102767089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
102777089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
102786000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10279692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10280f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10281556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10282f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
10283f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewBoolean(ret));
10284f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10285f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_PLUS:
102867089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
102877089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
102886000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10289692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10290f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10291556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
102927089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard            if (op->ch2 != -1) {
102937089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard		ctxt->context->doc = bakd;
102947089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard		ctxt->context->node = bak;
102956000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack		ctxt->context->proximityPosition = pp;
10296692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack		ctxt->context->contextSize = cs;
10297f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
102987089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    }
10299556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10300f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value == 0)
10301f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathSubValues(ctxt);
10302f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 1)
10303f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathAddValues(ctxt);
10304f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 2)
10305f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathValueFlipSign(ctxt);
10306f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 3) {
10307f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CAST_TO_NUMBER;
10308f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NUMBER);
10309f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10310f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10311f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_MULT:
103127089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
103137089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
103146000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10315692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10316f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10317556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
103187089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
103197089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
103206000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10321692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10322f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10323556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10324f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->value == 0)
10325f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathMultValues(ctxt);
10326f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 1)
10327f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathDivValues(ctxt);
10328f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            else if (op->value == 2)
10329f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathModValues(ctxt);
10330f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10331f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_UNION:
103327089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bakd = ctxt->context->doc;
103337089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    bak = ctxt->context->node;
103346000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    pp = ctxt->context->proximityPosition;
10335692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    cs = ctxt->context->contextSize;
10336f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10337556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
103387089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->doc = bakd;
103397089d6bfac04415e3373dd7d5e92f9989d052e4aDaniel Veillard	    ctxt->context->node = bak;
103406000af549b49464a3b1947fc582998a1c9ff7c79William M. Brack	    ctxt->context->proximityPosition = pp;
10341692092b5886073a8cd1c97bb7d57579e4a9cfc3fWilliam M. Brack	    ctxt->context->contextSize = cs;
10342f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10343556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10344f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10345f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg2 = valuePop(ctxt);
10346f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10347f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            CHECK_TYPE0(XPATH_NODESET);
10348f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1 = valuePop(ctxt);
10349f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10350f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
10351f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    arg2->nodesetval);
10352f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, arg1);
10353f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathFreeObject(arg2);
10354f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10355f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ROOT:
10356f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            xmlXPathRoot(ctxt);
10357f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10358f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_NODE:
10359f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10360f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10361556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10362f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10363f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10364556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10365f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node));
10366f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10367f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RESET:
10368f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10369f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10370556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10371f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch2 != -1)
10372f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
10373556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10374f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            ctxt->context->node = NULL;
10375f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10376f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_COLLECT:{
10377f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 == -1)
10378f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10379f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10380f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10381556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10382f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10383f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10384f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for [n] selection where n is a number
10385f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10386f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch2 != -1) &&
10387f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_PREDICATE) &&
10388f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch1 == -1) &&
10389f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].ch2 != -1) &&
10390f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[comp->steps[op->ch2].ch2].op ==
10391f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     XPATH_OP_VALUE)) {
10392f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10393f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[comp->steps[op->ch2].ch2].value4;
10395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER)) {
10396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        int indx = (int) val->floatval;
10397f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10398f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (val->floatval == (float) indx) {
10399f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10400f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathNodeCollectAndTestNth(ctxt, op,
10401f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              indx, NULL,
10402f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                              NULL);
10403f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10404f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10405f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10406f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10407f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL);
10408f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10409f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10410f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VALUE:
10411f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            valuePush(ctxt,
10412f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                      xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
10413f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10414f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_VARIABLE:{
10415556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		xmlXPathObjectPtr val;
10416556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard
10417f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10418f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10419f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10420556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                if (op->value5 == NULL) {
10421556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    val = xmlXPathVariableLookup(ctxt->context, op->value4);
10422556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (val == NULL) {
10423556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
10424556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return(0);
10425556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10426556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                    valuePush(ctxt, val);
10427556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		} else {
10428f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    const xmlChar *URI;
10429f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10430f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    URI = xmlXPathNsLookup(ctxt->context, op->value5);
10431f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (URI == NULL) {
10432f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlGenericError(xmlGenericErrorContext,
10433cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                        "xmlXPathCompOpEval: variable %s bound to undefined prefix %s\n",
10434f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        op->value4, op->value5);
10435f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10436f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10437556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    val = xmlXPathVariableLookupNS(ctxt->context,
10438556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                                                       op->value4, URI);
10439556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (val == NULL) {
10440556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_UNDEF_VARIABLE_ERROR;
10441556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return(0);
10442556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10443556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard                    valuePush(ctxt, val);
10444f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10445f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10446f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10447f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_FUNCTION:{
10448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFunction func;
10449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                const xmlChar *oldFunc, *oldFuncURI;
10450556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		int i;
10451f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10452f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10453f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10454f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10455556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		if (ctxt->valueNr < op->value) {
10456556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    xmlGenericError(xmlGenericErrorContext,
10457cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard			    "xmlXPathCompOpEval: parameter error\n");
10458556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    ctxt->error = XPATH_INVALID_OPERAND;
10459556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    return (total);
10460556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		}
10461556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		for (i = 0; i < op->value; i++)
10462556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
10463556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			xmlGenericError(xmlGenericErrorContext,
10464cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard				"xmlXPathCompOpEval: parameter error\n");
10465556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			ctxt->error = XPATH_INVALID_OPERAND;
10466556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			return (total);
10467556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    }
10468f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->cache != NULL)
10469ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack                    XML_CAST_FPTR(func) = op->cache;
10470f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                else {
10471f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    const xmlChar *URI = NULL;
10472f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10473f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (op->value5 == NULL)
10474f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        func =
10475f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFunctionLookup(ctxt->context,
10476f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   op->value4);
10477f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    else {
10478f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        URI = xmlXPathNsLookup(ctxt->context, op->value5);
10479f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (URI == NULL) {
10480f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlGenericError(xmlGenericErrorContext,
10481cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                            "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
10482f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                            op->value4, op->value5);
10483f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            return (total);
10484f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10485f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        func = xmlXPathFunctionLookupNS(ctxt->context,
10486f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                        op->value4, URI);
10487f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10488f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (func == NULL) {
10489f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlGenericError(xmlGenericErrorContext,
10490cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard                                        "xmlXPathCompOpEval: function %s not found\n",
10491f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                        op->value4);
10492f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
10493f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10494ad0e67c57f26f691fc120d5c5336cee9885cf324William M. Brack                    op->cache = XML_CAST_FPTR(func);
10495f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    op->cacheURI = (void *) URI;
10496f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10497f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldFunc = ctxt->context->function;
10498f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldFuncURI = ctxt->context->functionURI;
10499f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->function = op->value4;
10500f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->functionURI = op->cacheURI;
10501f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                func(ctxt, op->value);
10502f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->function = oldFunc;
10503f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->functionURI = oldFuncURI;
10504f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10505f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10506f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_ARG:
10507088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    bakd = ctxt->context->doc;
10508088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    bak = ctxt->context->node;
10509645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    pp = ctxt->context->proximityPosition;
10510645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    cs = ctxt->context->contextSize;
10511f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10512f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10513645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    ctxt->context->contextSize = cs;
10514645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    ctxt->context->proximityPosition = pp;
10515088bf1163080cbbb72ba9d4a52ab08cc7c8ff6c7Daniel Veillard	    ctxt->context->node = bak;
10516645a924a9d50d8e0eced5dd7277214a65756c2e1William M. Brack	    ctxt->context->doc = bakd;
10517556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
1051872ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack            if (op->ch2 != -1) {
10519f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
1052072ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack	        ctxt->context->doc = bakd;
1052172ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack	        ctxt->context->node = bak;
1052272ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack	        CHECK_ERROR0;
1052372ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack	    }
10524f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
10525f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_PREDICATE:
10526f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_FILTER:{
10527f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr res;
10528f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr obj, tmp;
10529f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr newset = NULL;
10530f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr oldset;
10531f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodePtr oldnode;
105323794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		xmlDocPtr oldDoc;
10533f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                int i;
10534f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10535f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10536f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for ()[1] selection i.e. the first elem
10537f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10538f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch1 != -1) && (op->ch2 != -1) &&
10539f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
10540f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_VALUE)) {
10541f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathObjectPtr val;
10542f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10543f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    val = comp->steps[op->ch2].value4;
10544f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((val != NULL) && (val->type == XPATH_NUMBER) &&
10545f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (val->floatval == 1.0)) {
10546f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlNodePtr first = NULL;
10547f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10548f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10549f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEvalFirst(ctxt,
10550f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    &comp->steps[op->ch1],
10551f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                    &first);
10552556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			CHECK_ERROR0;
10553f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10554f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The nodeset should be in document order,
10555f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Keep only the first value
10556f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10557f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((ctxt->value != NULL) &&
10558f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->type == XPATH_NODESET) &&
10559f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval != NULL) &&
10560f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeNr > 1))
10561f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeNr = 1;
10562f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10563f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10564f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10565f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10566f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Optimization for ()[last()] selection i.e. the last elem
10567f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10568f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((op->ch1 != -1) && (op->ch2 != -1) &&
10569f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
10570f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
10571f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    int f = comp->steps[op->ch2].ch1;
10572f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10573f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((f != -1) &&
10574f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].op == XPATH_OP_FUNCTION) &&
10575f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value5 == NULL) &&
10576f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value == 0) &&
10577f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (comp->steps[f].value4 != NULL) &&
10578f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        (xmlStrEqual
10579f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         (comp->steps[f].value4, BAD_CAST "last"))) {
10580f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlNodePtr last = NULL;
10581f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10582f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10583f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEvalLast(ctxt,
10584f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch1],
10585f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &last);
10586556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard			CHECK_ERROR0;
10587f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10588f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The nodeset should be in document order,
10589f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Keep only the last value
10590f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10591f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if ((ctxt->value != NULL) &&
10592f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->type == XPATH_NODESET) &&
10593f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval != NULL) &&
10594f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeTab != NULL) &&
10595f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            (ctxt->value->nodesetval->nodeNr > 1)) {
10596f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeTab[0] =
10597f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                ctxt->value->nodesetval->nodeTab[ctxt->
10598f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 value->
10599f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 nodesetval->
10600f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 nodeNr -
10601f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                                 1];
10602f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            ctxt->value->nodesetval->nodeNr = 1;
10603f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10604f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10605f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10606f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10607f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10608f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10609f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10610f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10611556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		CHECK_ERROR0;
10612f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch2 == -1)
10613f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10614f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (ctxt->value == NULL)
10615f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10616f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10617f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldnode = ctxt->context->node;
106189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10619f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
10620f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10621f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Hum are we filtering the result of an XPointer expression
10622f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10623f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (ctxt->value->type == XPATH_LOCATIONSET) {
10624f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlLocationSetPtr newlocset = NULL;
10625f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlLocationSetPtr oldlocset;
10626f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10627f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10628f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * Extract the old locset, and then evaluate the result of the
10629f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * expression for all the element in the locset. use it to grow
10630f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * up a new locset.
10631f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10632f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    CHECK_TYPE0(XPATH_LOCATIONSET);
10633f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    obj = valuePop(ctxt);
10634f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    oldlocset = obj->user;
10635f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10636f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10637f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
10638f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = 0;
10639f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = 0;
10640f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10641f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10642f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10643f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
10644f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10645f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10646f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10647f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, obj);
10648f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        CHECK_ERROR0;
10649f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        return (total);
10650f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10651f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    newlocset = xmlXPtrLocationSetCreate(NULL);
10652f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10653f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldlocset->locNr; i++) {
10654f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10655f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of a
10656f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * single item in the nodelocset.
10657f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10658f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldlocset->locTab[i]->user;
10659f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = oldlocset->locNr;
10660f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = i + 1;
10661f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10662f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        valuePush(ctxt, tmp);
10663f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10664f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10665f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10666f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10667f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
106682c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			if (ctxt->error != XPATH_EXPRESSION_OK) {
106692c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    xmlXPathFreeObject(obj);
106702c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    return(0);
106712c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			}
10672f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10673f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10674f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * The result of the evaluation need to be tested to
10675f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * decided whether the filter succeeded or not
10676f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10677f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10678f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
10679f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPtrLocationSetAdd(newlocset,
10680f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                  xmlXPathObjectCopy
10681f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                  (oldlocset->locTab[i]));
10682f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10683f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10684f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10685f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10686f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10687f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10688f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10689f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10690f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10691f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10692f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10693f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10694f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10695f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10696f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10697f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10698f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * The result is used as the new evaluation locset.
10699f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10700f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathFreeObject(obj);
10701f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10702f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = -1;
10703f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = -1;
10704f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
10705f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = oldnode;
10706f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10707f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
107089e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
107099e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
10710f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10711f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * Extract the old set, and then evaluate the result of the
10712f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * expression for all the element in the set. use it to grow
10713f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * up a new set.
10714f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10715f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                CHECK_TYPE0(XPATH_NODESET);
10716f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                obj = valuePop(ctxt);
10717f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldset = obj->nodesetval;
10718f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10719f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                oldnode = ctxt->context->node;
107203794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		oldDoc = ctxt->context->doc;
10721f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
10722f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10723f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if ((oldset == NULL) || (oldset->nodeNr == 0)) {
10724f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = 0;
10725f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = 0;
107268fad8bff2c2e0b064a6d48d4eeb663804de5545fWilliam M. Brack/*
10727f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (op->ch2 != -1)
10728f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        total +=
10729f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathCompOpEval(ctxt,
10730f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                               &comp->steps[op->ch2]);
10731556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard		    CHECK_ERROR0;
10732f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    res = valuePop(ctxt);
10733f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    if (res != NULL)
10734f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathFreeObject(res);
107358fad8bff2c2e0b064a6d48d4eeb663804de5545fWilliam M. Brack*/
10736f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, obj);
10737f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = oldnode;
10738f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    CHECK_ERROR0;
10739f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                } else {
10740f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10741f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * Initialize the new set.
107423794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		     * Also set the xpath document in case things like
107433794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		     * key() evaluation are attempted on the predicate
10744f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10745f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    newset = xmlXPathNodeSetCreate(NULL);
10746f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10747f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    for (i = 0; i < oldset->nodeNr; i++) {
10748f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10749f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Run the evaluation with a node list made of
10750f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * a single item in the nodeset.
10751f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10752f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = oldset->nodeTab[i];
107533794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack			if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) &&
107543794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack			    (oldset->nodeTab[i]->doc != NULL))
107553794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		            ctxt->context->doc = oldset->nodeTab[i]->doc;
10756f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10757f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
10758f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->contextSize = oldset->nodeNr;
10759f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->proximityPosition = i + 1;
10760f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10761f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10762f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10763f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10764f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
107652c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			if (ctxt->error != XPATH_EXPRESSION_OK) {
107662c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    xmlXPathFreeNodeSet(newset);
107672c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    xmlXPathFreeObject(obj);
107682c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    return(0);
107692c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			}
10770f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10771f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10772081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                         * The result of the evaluation needs to be tested to
10773081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                         * decide whether the filter succeeded or not
10774f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10775f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
10776f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
10777f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]);
10778f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10779f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10780f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10781f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10782f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10783f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10784f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10785f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10786f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10787f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10788f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10789f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10790f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10791f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
10792f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10793f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    /*
10794f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     * The result is used as the new evaluation set.
10795f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                     */
10796f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    xmlXPathFreeObject(obj);
10797f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->node = NULL;
10798f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->contextSize = -1;
10799f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    ctxt->context->proximityPosition = -1;
108003794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		    /* may want to move this past the '}' later */
108013794b9e84ac51072830a0b34d1ddd0378c0f7cb6William M. Brack		    ctxt->context->doc = oldDoc;
10802f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    valuePush(ctxt, xmlXPathWrapNodeSet(newset));
10803f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10804f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = oldnode;
10805f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10806f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
10807f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_SORT:
10808f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if (op->ch1 != -1)
10809f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10810556c668f04a45a3aafc52b8445c821569807dd19Daniel Veillard	    CHECK_ERROR0;
10811f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            if ((ctxt->value != NULL) &&
10812f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                (ctxt->value->type == XPATH_NODESET) &&
10813f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                (ctxt->value->nodesetval != NULL))
10814f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathNodeSetSort(ctxt->value->nodesetval);
10815f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            return (total);
108169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#ifdef LIBXML_XPTR_ENABLED
10817f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard        case XPATH_OP_RANGETO:{
10818f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr range;
10819f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr res, obj;
10820f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathObjectPtr tmp;
10821081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                xmlLocationSetPtr newlocset = NULL;
10822081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack		    xmlLocationSetPtr oldlocset;
10823f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlNodeSetPtr oldset;
1082472ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack                int i, j;
10825f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10826f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch1 != -1)
10827f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    total +=
10828f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
10829f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                if (op->ch2 == -1)
10830f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    return (total);
10831f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10832081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                if (ctxt->value->type == XPATH_LOCATIONSET) {
10833081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    /*
10834081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                     * Extract the old locset, and then evaluate the result of the
10835081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                     * expression for all the element in the locset. use it to grow
10836081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                     * up a new locset.
10837081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                     */
10838081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    CHECK_TYPE0(XPATH_LOCATIONSET);
10839081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    obj = valuePop(ctxt);
10840081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    oldlocset = obj->user;
10841f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10842081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    if ((oldlocset == NULL) || (oldlocset->locNr == 0)) {
1084372ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack		        ctxt->context->node = NULL;
10844081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        ctxt->context->contextSize = 0;
10845081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        ctxt->context->proximityPosition = 0;
10846081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        total += xmlXPathCompOpEval(ctxt,&comp->steps[op->ch2]);
10847081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        res = valuePop(ctxt);
10848081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        if (res != NULL)
10849081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            xmlXPathFreeObject(res);
10850081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        valuePush(ctxt, obj);
10851081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        CHECK_ERROR0;
10852081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        return (total);
10853081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    }
10854081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    newlocset = xmlXPtrLocationSetCreate(NULL);
10855f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10856081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    for (i = 0; i < oldlocset->locNr; i++) {
10857f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10858081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                         * Run the evaluation with a node list made of a
10859081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                         * single item in the nodelocset.
10860f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10861f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        ctxt->context->node = oldlocset->locTab[i]->user;
10862f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        ctxt->context->contextSize = oldlocset->locNr;
10863f7eb794c142e31ca895f2d7743f872a809e514abWilliam M. Brack                        ctxt->context->proximityPosition = i + 1;
10864f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        tmp = xmlXPathNewNodeSet(ctxt->context->node);
10865f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        valuePush(ctxt, tmp);
10866f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10867f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (op->ch2 != -1)
10868f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            total +=
10869f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                xmlXPathCompOpEval(ctxt,
10870f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                                                   &comp->steps[op->ch2]);
108712c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			if (ctxt->error != XPATH_EXPRESSION_OK) {
108722c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    xmlXPathFreeObject(obj);
108732c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    return(0);
108742c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			}
10875f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10876f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        res = valuePop(ctxt);
1087772ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			if (res->type == XPATH_LOCATIONSET) {
1087872ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    xmlLocationSetPtr rloc =
1087972ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			        (xmlLocationSetPtr)res->user;
1088072ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    for (j=0; j<rloc->locNr; j++) {
1088172ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			        range = xmlXPtrNewRange(
1088272ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				  oldlocset->locTab[i]->user,
1088372ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				  oldlocset->locTab[i]->index,
1088472ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				  rloc->locTab[j]->user2,
1088572ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				  rloc->locTab[j]->index2);
1088672ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				if (range != NULL) {
1088772ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				    xmlXPtrLocationSetAdd(newlocset, range);
1088872ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				}
1088972ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    }
1089072ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			} else {
1089172ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    range = xmlXPtrNewRangeNodeObject(
1089272ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack				(xmlNodePtr)oldlocset->locTab[i]->user, res);
1089372ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack                            if (range != NULL) {
1089472ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack                                xmlXPtrLocationSetAdd(newlocset,range);
1089572ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack			    }
10896f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10897f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10898f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        /*
10899f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         * Cleanup
10900f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                         */
10901f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (res != NULL)
10902f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10903f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        if (ctxt->value == tmp) {
10904f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            res = valuePop(ctxt);
10905f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                            xmlXPathFreeObject(res);
10906f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        }
10907f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10908f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                        ctxt->context->node = NULL;
10909f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    }
1091072ee48d55f9002544d011826e2897b5054b7e32cWilliam M. Brack		} else {	/* Not a location set */
10911081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    CHECK_TYPE0(XPATH_NODESET);
10912081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    obj = valuePop(ctxt);
10913081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    oldset = obj->nodesetval;
10914081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    ctxt->context->node = NULL;
10915081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
10916081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    newlocset = xmlXPtrLocationSetCreate(NULL);
10917081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
10918081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    if (oldset != NULL) {
10919081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        for (i = 0; i < oldset->nodeNr; i++) {
10920081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            /*
10921081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             * Run the evaluation with a node list made of a single item
10922081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             * in the nodeset.
10923081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             */
10924081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            ctxt->context->node = oldset->nodeTab[i];
10925081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            tmp = xmlXPathNewNodeSet(ctxt->context->node);
10926081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            valuePush(ctxt, tmp);
10927081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
10928081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            if (op->ch2 != -1)
10929081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                total +=
10930081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                    xmlXPathCompOpEval(ctxt,
10931081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                                   &comp->steps[op->ch2]);
109322c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    if (ctxt->error != XPATH_EXPRESSION_OK) {
109332c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack				xmlXPathFreeObject(obj);
109342c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack				return(0);
109352c19a7bf2ee0f78485840cac50f2a989f5efe476William M. Brack			    }
10936081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
10937081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            res = valuePop(ctxt);
10938081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            range =
10939081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                xmlXPtrNewRangeNodeObject(oldset->nodeTab[i],
10940081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                                      res);
10941081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            if (range != NULL) {
10942081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                xmlXPtrLocationSetAdd(newlocset, range);
10943081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            }
10944081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
10945081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            /*
10946081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             * Cleanup
10947081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                             */
10948081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            if (res != NULL)
10949081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                xmlXPathFreeObject(res);
10950081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            if (ctxt->value == tmp) {
10951081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                res = valuePop(ctxt);
10952081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                                xmlXPathFreeObject(res);
10953081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            }
10954081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack
10955081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                            ctxt->context->node = NULL;
10956081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                        }
10957081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                    }
10958f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                }
10959f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
10960f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                /*
10961f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 * The result is used as the new evaluation set.
10962f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                 */
10963f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                xmlXPathFreeObject(obj);
10964f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->node = NULL;
10965f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->contextSize = -1;
10966f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                ctxt->context->proximityPosition = -1;
10967081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack                valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
10968f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                return (total);
10969f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard            }
109709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard#endif /* LIBXML_XPTR_ENABLED */
109719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
109729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlGenericError(xmlGenericErrorContext,
10973f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard                    "XPath: unknown precompiled operation %d\n", op->op);
10974f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    return (total);
109759e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
109769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
1097756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1097856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard/**
1097956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * xmlXPathRunStreamEval:
1098056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @ctxt:  the XPath parser context with the compiled expression
1098156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
1098256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Evaluate the Precompiled Streamable XPath expression in the given context.
1098356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard */
1098456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardstatic xmlXPathObjectPtr
1098556de87ee0d147d04a041eb1ec95048566375bc3fDaniel VeillardxmlXPathRunStreamEval(xmlXPathContextPtr ctxt, xmlPatternPtr comp) {
1098656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int max_depth;
1098756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int from_root;
1098856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int ret, depth;
1098912d37ab63441baf9e03db70168cc1d0d6f1c2373William M. Brack    xmlNodePtr cur = NULL, limit = NULL;
1099056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlXPathObjectPtr retval;
1099156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlStreamCtxtPtr patstream;
1099256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1099356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int nb_nodes = 0;
1099456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1099556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if ((ctxt == NULL) || (comp == NULL))
1099656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(NULL);
1099756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    max_depth = xmlPatternMaxDepth(comp);
1099856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (max_depth == -1)
1099956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(NULL);
1100056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (max_depth == -2)
1100156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        max_depth = 10000;
1100256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    from_root = xmlPatternFromRoot(comp);
1100356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (from_root < 0)
1100456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(NULL);
11005fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#if 0
11006fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    printf("stream eval: depth %d from root %d\n", max_depth, from_root);
11007fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#endif
1100856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1100956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    retval = xmlXPathNewNodeSet(NULL);
1101056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (retval == NULL)
1101156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(NULL);
1101256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1101356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if ((from_root) && (max_depth == 0)) {
1101456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	xmlXPathNodeSetAddUnique(retval->nodesetval, (xmlNodePtr) ctxt->doc);
1101556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	return(retval);
1101656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } else if (max_depth == 0) {
1101756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	xmlXPathNodeSetAddUnique(retval->nodesetval, ctxt->node);
1101856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	return(retval);
1101956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1102056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (from_root) {
1102112d37ab63441baf9e03db70168cc1d0d6f1c2373William M. Brack        cur = (xmlNodePtr)ctxt->doc;
1102256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } else if (ctxt->node != NULL) {
1102356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        switch (ctxt->node->type) {
1102456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ELEMENT_NODE:
1102556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DOCUMENT_NODE:
1102656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DOCUMENT_FRAG_NODE:
1102756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_HTML_DOCUMENT_NODE:
1102856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef LIBXML_DOCB_ENABLED
1102956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DOCB_DOCUMENT_NODE:
1103056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1103156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	        cur = ctxt->node;
1103256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		break;
1103356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ATTRIBUTE_NODE:
1103456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_TEXT_NODE:
1103556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_CDATA_SECTION_NODE:
1103656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ENTITY_REF_NODE:
1103756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ENTITY_NODE:
1103856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_PI_NODE:
1103956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_COMMENT_NODE:
1104056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_NOTATION_NODE:
1104156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DTD_NODE:
1104256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_DOCUMENT_TYPE_NODE:
1104356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ELEMENT_DECL:
1104456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ATTRIBUTE_DECL:
1104556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_ENTITY_DECL:
1104656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_NAMESPACE_DECL:
1104756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_XINCLUDE_START:
1104856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            case XML_XINCLUDE_END:
1104956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		break;
1105056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1105156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	limit = cur;
1105256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1105356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (cur == NULL)
1105456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(retval);
1105556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1105656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    patstream = xmlPatternGetStreamCtxt(comp);
1105756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (patstream == NULL) {
1105856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(retval);
1105956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1106056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1106156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (from_root) {
1106256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	ret = xmlStreamPush(patstream, NULL, NULL);
1106356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ret < 0) {
1106456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	} else if (ret == 1) {
1106556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    xmlXPathNodeSetAddUnique(retval->nodesetval, cur);
1106656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1106756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1106856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1106956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    depth = 0;
1107056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    goto scan_children;
1107156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    do {
1107256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardnext_node:
1107356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        nb_nodes++;
1107456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (cur->type == XML_ELEMENT_NODE) {
1107556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    ret = xmlStreamPush(patstream, cur->name,
1107656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard				(cur->ns ? cur->ns->href : NULL));
1107756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (ret < 0) {
1107856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    } else if (ret == 1) {
1107956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		xmlXPathNodeSetAddUnique(retval->nodesetval, cur);
1108056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1108156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if ((cur->children == NULL) || (depth >= max_depth)) {
1108256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		ret = xmlStreamPop(patstream);
11083fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack		while (cur->next != NULL) {
11084fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack		    cur = cur->next;
11085fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack		    if ((cur->type != XML_ENTITY_DECL) &&
11086fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack			(cur->type != XML_DTD_NODE))
11087fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack			goto next_node;
11088fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack		}
1108956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1109056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1109156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1109256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardscan_children:
1109356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if ((cur->children != NULL) && (depth < max_depth)) {
1109456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    /*
1109556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	     * Do not descend on entities declarations
1109656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	     */
1109756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (cur->children->type != XML_ENTITY_DECL) {
1109856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		cur = cur->children;
1109956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		depth++;
1110056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		/*
1110156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		 * Skip DTDs
1110256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		 */
1110356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		if (cur->type != XML_DTD_NODE)
1110456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    continue;
1110556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1110656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1110756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1110856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (cur == limit)
1110956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    break;
1111056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1111156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	while (cur->next != NULL) {
1111256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    cur = cur->next;
1111356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if ((cur->type != XML_ENTITY_DECL) &&
1111456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		(cur->type != XML_DTD_NODE))
1111556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		goto next_node;
1111656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1111756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1111856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	do {
1111956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    cur = cur->parent;
1112056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    depth--;
1112156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if ((cur == NULL) || (cur == limit))
1112256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	        goto done;
11123fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack	    if (cur->type == XML_ELEMENT_NODE)
11124fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack	        ret = xmlStreamPop(patstream);
1112556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (cur->next != NULL) {
1112656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		cur = cur->next;
1112756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		break;
1112856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1112956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	} while (cur != NULL);
1113056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1113156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } while ((cur != NULL) && (depth >= 0));
1113256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillarddone:
11133fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#if 0
11134fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    printf("stream eval: checked %d nodes selected %d\n",
11135fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard           nb_nodes, retval->nodesetval->nodeNr);
11136fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard#endif
1113756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlFreeStreamCtxt(patstream);
1113856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    return(retval);
1113956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard}
1114056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif /* XPATH_STREAMING */
1114156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
111429e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
111439e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathRunEval:
111449e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctxt:  the XPath parser context with the compiled expression
111459e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
111469e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Evaluate the Precompiled XPath expression in the given context.
111479e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
11148fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardstatic void
111499e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathRunEval(xmlXPathParserContextPtr ctxt) {
111509e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompExprPtr comp;
111519e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
111529e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((ctxt == NULL) || (ctxt->comp == NULL))
111539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return;
111549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
111559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->valueTab == NULL) {
111569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	/* Allocate the value stack */
111579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueTab = (xmlXPathObjectPtr *)
111589e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard			 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
111599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (ctxt->valueTab == NULL) {
11160d96f6d34295c8ce73c15c60115e970132e6fd18eDaniel Veillard	    xmlXPathPErrMemory(ctxt, "creating evaluation context\n");
111619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlFree(ctxt);
111629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	}
111639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueNr = 0;
111649e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->valueMax = 10;
111659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	ctxt->value = NULL;
111669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
1116756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1116856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (ctxt->comp->stream) {
1116956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        xmlXPathObjectPtr ret;
1117056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        ret = xmlXPathRunStreamEval(ctxt->context, ctxt->comp->stream);
1117156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ret != NULL) {
1117256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    valuePush(ctxt, ret);
1117356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return;
1117456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1117556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1117656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
111779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    comp = ctxt->comp;
1117829b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin    if(comp->last < 0) {
1117929b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	xmlGenericError(xmlGenericErrorContext,
1118029b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	    "xmlXPathRunEval: last is less than zero\n");
1118129b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin	return;
1118229b6f76c5326616aed5dcff9cb55145137863e97Aleksey Sanin    }
111839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
111849e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
111859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11186afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/************************************************************************
11187afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *									*
11188afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * 			Public interfaces				*
11189afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *									*
11190afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard ************************************************************************/
11191afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
11192afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
11193fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * xmlXPathEvalPredicate:
11194fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @ctxt:  the XPath context
11195fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * @res:  the Predicate Expression evaluation result
11196fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
11197fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * Evaluate a predicate result for the current node.
11198fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * A PredicateExpr is evaluated by evaluating the Expr and converting
11199fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * the result to a boolean. If the result is a number, the result will
11200fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * be converted to true if the number is equal to the position of the
11201fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * context node in the context node list (as returned by the position
11202fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * function) and will be converted to false otherwise; if the result
11203fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * is not a number, then the result will be converted as if by a call
11204fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard * to the boolean function.
11205fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard *
11206cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if predicate is true, 0 otherwise
11207fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard */
11208fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillardint
11209fbf8a2d0c8145b713099df63d174154a8442e60dDaniel VeillardxmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
11210ce682bc24b79f1dd29b781d4c17f9bf169ce7e32Daniel Veillard    if ((ctxt == NULL) || (res == NULL)) return(0);
11211fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    switch (res->type) {
11212fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_BOOLEAN:
11213fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->boolval);
11214fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_NUMBER:
11215fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->floatval == ctxt->proximityPosition);
11216fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_NODESET:
11217fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_XSLT_TREE:
11218d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard	    if (res->nodesetval == NULL)
11219d8df6c0e8c883e1d618388d266015dda36731440Daniel Veillard		return(0);
11220fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return(res->nodesetval->nodeNr != 0);
11221fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        case XPATH_STRING:
11222fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    return((res->stringval != NULL) &&
11223fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	           (xmlStrlen(res->stringval) != 0));
11224fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard        default:
11225fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard	    STRANGE
11226fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    }
11227fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard    return(0);
11228fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard}
11229fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard
11230fbf8a2d0c8145b713099df63d174154a8442e60dDaniel Veillard/**
11231afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathEvaluatePredicateResult:
11232afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @ctxt:  the XPath Parser context
11233afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @res:  the Predicate Expression evaluation result
11234afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11235afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Evaluate a predicate result for the current node.
11236afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * A PredicateExpr is evaluated by evaluating the Expr and converting
11237afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * the result to a boolean. If the result is a number, the result will
11238afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * be converted to true if the number is equal to the position of the
11239afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * context node in the context node list (as returned by the position
11240afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * function) and will be converted to false otherwise; if the result
11241afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * is not a number, then the result will be converted as if by a call
11242afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * to the boolean function.
11243afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11244cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns 1 if predicate is true, 0 otherwise
11245afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
11246afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardint
11247afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
11248afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard                                xmlXPathObjectPtr res) {
11249ce682bc24b79f1dd29b781d4c17f9bf169ce7e32Daniel Veillard    if ((ctxt == NULL) || (res == NULL)) return(0);
11250afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    switch (res->type) {
11251afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_BOOLEAN:
11252afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->boolval);
11253afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_NUMBER:
112549ea6231ecef04c848b688355b8f7532dd5e4c6f8Daniel Veillard#if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200))
112557c4eb63bb01d754b17860cd7dc2ab2fef81f6a08Daniel Veillard	    return((res->floatval == ctxt->context->proximityPosition) &&
112567c4eb63bb01d754b17860cd7dc2ab2fef81f6a08Daniel Veillard	           (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/
112572582a338bff77569b5aadbba8f40e1f3862d090dDaniel Veillard#else
11258afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->floatval == ctxt->context->proximityPosition);
112592582a338bff77569b5aadbba8f40e1f3862d090dDaniel Veillard#endif
11260afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_NODESET:
11261afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_XSLT_TREE:
1126273639a73c5a51c3739595f54c338bb531c1319c2Daniel Veillard	    if (res->nodesetval == NULL)
11263911f49a0a02d13f5432ddd75ff497290619be924Daniel Veillard		return(0);
11264afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return(res->nodesetval->nodeNr != 0);
11265afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        case XPATH_STRING:
11266afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    return((res->stringval != NULL) &&
11267afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	           (xmlStrlen(res->stringval) != 0));
11268081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack#ifdef LIBXML_XPTR_ENABLED
11269081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	case XPATH_LOCATIONSET:{
11270081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    xmlLocationSetPtr ptr = res->user;
11271081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    if (ptr == NULL)
11272081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	        return(0);
11273081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    return (ptr->locNr != 0);
11274081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack	    }
11275081719182de3d15e6a438f32fdc3d1ca240a08e8William M. Brack#endif
11276afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard        default:
11277afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard	    STRANGE
11278afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    }
11279afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    return(0);
11280afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
11281afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
1128256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1128356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard/**
1128456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * xmlXPathTryStreamCompile:
1128556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @ctxt: an XPath context
1128656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @str:  the XPath expression
1128756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
1128856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Try to compile the XPath expression as a streamable subset.
1128956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
1129056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Returns the compiled expression or NULL if failed to compile.
1129156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard */
1129256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardstatic xmlXPathCompExprPtr
1129356de87ee0d147d04a041eb1ec95048566375bc3fDaniel VeillardxmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
1129456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    /*
1129556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     * Optimization: use streaming patterns when the XPath expression can
1129656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     * be compiled to a stream lookup
1129756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     */
1129856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlPatternPtr stream;
1129956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlXPathCompExprPtr comp;
1130056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlDictPtr dict = NULL;
1130156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    const xmlChar **namespaces = NULL;
1130256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlNsPtr ns;
1130356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int i, j;
1130456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1130556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) &&
1130656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        (!xmlStrchr(str, '@'))) {
1130756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ctxt != NULL) {
1130856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    dict = ctxt->dict;
1130956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (ctxt->nsNr > 0) {
11310dbfe05aff4d242e31fcd7621a4901a6fa10b988eDaniel Veillard		namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*));
1131156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		if (namespaces == NULL) {
1131256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    xmlXPathErrMemory(ctxt, "allocating namespaces array\n");
1131356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    return(NULL);
1131456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		}
1131556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		for (i = 0, j = 0; (j < ctxt->nsNr); j++) {
1131656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    ns = ctxt->namespaces[j];
1131756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    namespaces[i++] = ns->href;
1131856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		    namespaces[i++] = ns->prefix;
1131956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		}
1132056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		namespaces[i++] = NULL;
1132156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		namespaces[i++] = NULL;
1132256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1132356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1132456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11325ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	stream = xmlPatterncompile(str, dict, XML_PATTERN_XPATH,
11326ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack			&namespaces[0]);
1132756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) {
1132856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp = xmlXPathNewCompExpr();
1132956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (comp == NULL) {
1133056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		xmlXPathErrMemory(ctxt, "allocating streamable expression\n");
1133156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		return(NULL);
1133256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    }
1133356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp->stream = stream;
1133456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp->dict = dict;
1133556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (comp->dict)
1133656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard		xmlDictReference(comp->dict);
1133756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return(comp);
1133856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
1133956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	xmlFreePattern(stream);
1134056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1134156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    return(NULL);
1134256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard}
1134356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif /* XPATH_STREAMING */
1134456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11345afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
113464773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * xmlXPathCtxtCompile:
113474773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * @ctxt: an XPath context
11348afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @str:  the XPath expression
11349afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11350afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Compile an XPath expression
11351afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11352591b4be0fe1986b5e71d54c5c063493987ef4285Daniel Veillard * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
11353afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *         the caller has to free the object.
11354afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
11355afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathCompExprPtr
113564773df2a58be83e1b9b1b55840371acf37386820Daniel VeillardxmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
113574773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    xmlXPathParserContextPtr pctxt;
11358afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathCompExprPtr comp;
11359afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
1136056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1136156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    comp = xmlXPathTryStreamCompile(ctxt, str);
1136256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp != NULL)
1136356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(comp);
1136456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1136556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11366afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathInit();
11367afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
113684773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    pctxt = xmlXPathNewParserContext(str, ctxt);
113694773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    xmlXPathCompileExpr(pctxt);
11370ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard
113714773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if( pctxt->error != XPATH_EXPRESSION_OK )
11372ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard    {
113734773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard        xmlXPathFreeParserContext(pctxt);
11374ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard        return (0);
11375ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard    }
11376ae9733aeaf99e5d967b6b2cd961c98bf58cfbb4cDaniel Veillard
113774773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    if (*pctxt->cur != 0) {
1137850fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	/*
1137950fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * aleksey: in some cases this line prints *second* error message
1138050fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * (see bug #78858) and probably this should be fixed.
1138150fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * However, we are not sure that all error messages are printed
1138250fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 * out in other places. It's not critical so we leave it as-is for now
1138350fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin	 */
113844773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
1138540af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard	comp = NULL;
1138640af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    } else {
113874773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	comp = pctxt->comp;
113884773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard	pctxt->comp = NULL;
1138940af649f9b5b32f97879f10432c56bb5ef60c958Daniel Veillard    }
113904773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    xmlXPathFreeParserContext(pctxt);
11391f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if (comp != NULL) {
11392ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard	comp->expr = xmlStrdup(str);
11393ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
11394f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->string = xmlStrdup(str);
11395f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->nb = 0;
11396f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
11397ceb09b956efa2cf1ec41c1887394396e5a6030f2Daniel Veillard    }
11398afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    return(comp);
11399afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
11400afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard
114019e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard/**
114024773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * xmlXPathCompile:
114034773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * @str:  the XPath expression
114044773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard *
114054773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * Compile an XPath expression
114064773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard *
114074773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
114084773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard *         the caller has to free the object.
114094773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard */
114104773df2a58be83e1b9b1b55840371acf37386820Daniel VeillardxmlXPathCompExprPtr
114114773df2a58be83e1b9b1b55840371acf37386820Daniel VeillardxmlXPathCompile(const xmlChar *str) {
114124773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard    return(xmlXPathCtxtCompile(NULL, str));
114134773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard}
114144773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard
114154773df2a58be83e1b9b1b55840371acf37386820Daniel Veillard/**
114169e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * xmlXPathCompiledEval:
114179e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @comp:  the compiled XPath expression
114189e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * @ctx:  the XPath context
114199e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
114209e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard * Evaluate the Precompiled XPath expression in the given context.
114219e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *
11422cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
114239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard *         the caller has to free the object.
114249e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard */
114259e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathObjectPtr
114269e7160d45a18bfa26d708e22ba991f7670d0128bDaniel VeillardxmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx) {
114279e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathParserContextPtr ctxt;
114289e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathObjectPtr res, tmp, init = NULL;
114299e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    int stack = 0;
114308146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
114318146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    static int reentance = 0;
114328146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
114339e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11434f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    CHECK_CTXT(ctx)
11435f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack
11436f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    if (comp == NULL)
114379e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	return(NULL);
114389e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathInit();
114399e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
114408146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
114418146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    reentance++;
114428146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    if (reentance > 1)
114438146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard	xmlXPathDisableOptimizer = 1;
114448146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
114458146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard
11446f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#ifdef DEBUG_EVAL_COUNTS
11447f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    comp->nb++;
11448f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    if ((comp->string != NULL) && (comp->nb > 100)) {
11449f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	fprintf(stderr, "100 x %s\n", comp->string);
11450f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard	comp->nb = 0;
11451f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard    }
11452f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard#endif
114539e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    ctxt = xmlXPathCompParserContext(comp, ctx);
114549e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathRunEval(ctxt);
114559e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
114569e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->value == NULL) {
114579e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlGenericError(xmlGenericErrorContext,
11458cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompiledEval: evaluation failed\n");
114599e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = NULL;
114609e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    } else {
114619e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = valuePop(ctxt);
114629e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
114639e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11464f06307e2c172284bb41376c396f757bdac9bdd19Daniel Veillard
114659e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    do {
114669e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        tmp = valuePop(ctxt);
114679e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	if (tmp != NULL) {
114689e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    if (tmp != init)
114699e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard		stack++;
114709e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	    xmlXPathFreeObject(tmp);
114719e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard        }
114729e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    } while (tmp != NULL);
114739e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if ((stack != 0) && (res != NULL)) {
114749e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlGenericError(xmlGenericErrorContext,
11475cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard		"xmlXPathCompiledEval: %d object left on the stack\n",
114769e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	        stack);
114779e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
114789e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    if (ctxt->error != XPATH_EXPRESSION_OK) {
114799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	xmlXPathFreeObject(res);
114809e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard	res = NULL;
114819e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    }
114829e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
114839e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11484afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    ctxt->comp = NULL;
114859e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    xmlXPathFreeParserContext(ctxt);
114868146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#ifndef LIBXML_THREAD_ENABLED
114878146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard    reentance--;
114888146394d05edb4f9c3eba3d97884d4e50fd6a92aDaniel Veillard#endif
114899e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard    return(res);
114909e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard}
114919e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
11492afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard/**
11493afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * xmlXPathEvalExpr:
11494afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * @ctxt:  the XPath Parser context
11495afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard *
11496afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * Parse and evaluate an XPath expression in the given context,
11497afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard * then push the result on the context stack
11498afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard */
11499afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillardvoid
11500afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel VeillardxmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
1150156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1150256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    xmlXPathCompExprPtr comp;
1150356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1150456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
11505a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (ctxt == NULL) return;
1150656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
1150756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1150856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base);
1150956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp != NULL) {
1151056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        if (ctxt->comp != NULL)
1151156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    xmlXPathFreeCompExpr(ctxt->comp);
1151256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        ctxt->comp = comp;
1151356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ctxt->cur != NULL)
1151456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    while (*ctxt->cur != 0) ctxt->cur++;
1151556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } else
1151656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1151756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    {
1151856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	xmlXPathCompileExpr(ctxt);
1151956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1152050fe8b1732048003f47b32b009507fe6cdecd39fAleksey Sanin    CHECK_ERROR;
11521afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard    xmlXPathRunEval(ctxt);
11522afcbe1cb12ae42a3be93249730e631d795d63a4fDaniel Veillard}
115239e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
115243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
115253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEval:
115263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
115273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctx:  the XPath context
115283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
115293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Evaluate the XPath Location Path in the given context.
115303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
11531cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
115323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         the caller has to free the object.
115333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
115343473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
115353473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
115363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr ctxt;
115373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr res, tmp, init = NULL;
115383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int stack = 0;
115393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11540f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    CHECK_CTXT(ctx)
115413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11542f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    xmlXPathInit();
115433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
115443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ctxt = xmlXPathNewParserContext(str, ctx);
115453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathEvalExpr(ctxt);
115463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
115473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->value == NULL) {
115483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
115493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEval: evaluation failed\n");
115503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
1155156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    } else if ((*ctxt->cur != 0) && (ctxt->comp != NULL)
1155256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#ifdef XPATH_STREAMING
1155356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard            && (ctxt->comp->stream == NULL)
1155456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard#endif
1155556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	      ) {
115563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
115573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
115583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
115593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = valuePop(ctxt);
115603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
115613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
115623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
115633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        tmp = valuePop(ctxt);
115643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (tmp != NULL) {
115653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (tmp != init)
115663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		stack++;
115673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(tmp);
115683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        }
115693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (tmp != NULL);
115703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((stack != 0) && (res != NULL)) {
115713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
115723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEval: %d object left on the stack\n",
115733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        stack);
115743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
115753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ctxt->error != XPATH_EXPRESSION_OK) {
115763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPathFreeObject(res);
115773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
115783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
115799e7160d45a18bfa26d708e22ba991f7670d0128bDaniel Veillard
115803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeParserContext(ctxt);
115813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(res);
115823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
115833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
115843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
115853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathEvalExpression:
115863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @str:  the XPath expression
115873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
115883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
115893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Evaluate the XPath expression in the given context.
115903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
115913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
115923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         the caller has to free the object.
115933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
115943473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathObjectPtr
115953473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
115963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathParserContextPtr pctxt;
115973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathObjectPtr res, tmp;
115983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    int stack = 0;
115993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11600f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    CHECK_CTXT(ctxt)
116013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
11602f13f77f0e6a7876063d5fba15c096befb0827cedWilliam M. Brack    xmlXPathInit();
116033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
116043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    pctxt = xmlXPathNewParserContext(str, ctxt);
116053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathEvalExpr(pctxt);
116063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
116073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (*pctxt->cur != 0) {
116083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
116093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = NULL;
116103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else {
116113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res = valuePop(pctxt);
116123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
116133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    do {
116143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        tmp = valuePop(pctxt);
116153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (tmp != NULL) {
116163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlXPathFreeObject(tmp);
116173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    stack++;
116183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
116193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } while (tmp != NULL);
116203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((stack != 0) && (res != NULL)) {
116213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlGenericError(xmlGenericErrorContext,
116223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		"xmlXPathEvalExpression: %d object left on the stack\n",
116233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	        stack);
116243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
116253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathFreeParserContext(pctxt);
116263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(res);
116273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
116283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1162942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard/************************************************************************
1163042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *									*
1163142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *	Extra functions not pertaining to the XPath spec		*
1163242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *									*
1163342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard ************************************************************************/
1163442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard/**
1163542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * xmlXPathEscapeUriFunction:
1163642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * @ctxt:  the XPath Parser context
1163742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * @nargs:  the number of arguments
1163842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1163942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Implement the escape-uri() XPath function
1164042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *    string escape-uri(string $str, bool $escape-reserved)
1164142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1164242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * This function applies the URI escaping rules defined in section 2 of [RFC
1164342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * 2396] to the string supplied as $uri-part, which typically represents all
1164442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * or part of a URI. The effect of the function is to replace any special
1164542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * character in the string by an escape sequence of the form %xx%yy...,
1164642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * where xxyy... is the hexadecimal representation of the octets used to
1164742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * represent the character in UTF-8.
1164842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1164942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * The set of characters that are escaped depends on the setting of the
1165042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * boolean argument $escape-reserved.
1165142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1165242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * If $escape-reserved is true, all characters are escaped other than lower
1165342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * case letters a-z, upper case letters A-Z, digits 0-9, and the characters
1165442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!"
1165542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only
1165642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and
1165742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * A-F).
1165842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1165942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * If $escape-reserved is false, the behavior differs in that characters
1166042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * referred to in [RFC 2396] as reserved characters are not escaped. These
1166142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",".
1166242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1166342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * [RFC 2396] does not define whether escaped URIs should use lower case or
1166442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * upper case for hexadecimal digits. To ensure that escaped URIs can be
1166542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * compared using string comparison functions, this function must always use
1166642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * the upper-case letters A-F.
1166742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1166842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Generally, $escape-reserved should be set to true when escaping a string
1166942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * that is to form a single part of a URI, and to false when escaping an
1167042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * entire URI or URI reference.
1167142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1167242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * In the case of non-ascii characters, the string is encoded according to
1167342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * utf-8 and then converted according to RFC 2396.
1167442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1167542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard * Examples
1167642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), true())
1167742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%2FLos%20Angeles%23ocean"
1167842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), false())
1167942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *  returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles%23ocean"
1168042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard *
1168142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard */
11682118aed78f360f51d182770e62b251ef324707aa2Daniel Veillardstatic void
1168342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel VeillardxmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1168442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathObjectPtr str;
1168542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    int escape_reserved;
1168642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlBufferPtr target;
1168742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlChar *cptr;
1168842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlChar escape[4];
1168942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1169042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    CHECK_ARITY(2);
1169142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1169242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape_reserved = xmlXPathPopBoolean(ctxt);
1169342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1169442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    CAST_TO_STRING;
1169542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    str = valuePop(ctxt);
1169642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1169742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    target = xmlBufferCreate();
1169842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1169942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape[0] = '%';
1170042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    escape[3] = 0;
1170142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1170242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    if (target) {
1170342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	for (cptr = str->stringval; *cptr; cptr++) {
1170442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    if ((*cptr >= 'A' && *cptr <= 'Z') ||
1170542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr >= 'a' && *cptr <= 'z') ||
1170642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr >= '0' && *cptr <= '9') ||
1170742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '-' || *cptr == '_' || *cptr == '.' ||
1170842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '!' || *cptr == '~' || *cptr == '*' ||
1170942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		*cptr == '\''|| *cptr == '(' || *cptr == ')' ||
1171042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(*cptr == '%' &&
1171142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 ((cptr[1] >= 'A' && cptr[1] <= 'F') ||
1171242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[1] >= 'a' && cptr[1] <= 'f') ||
1171342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[1] >= '0' && cptr[1] <= '9')) &&
1171442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 ((cptr[2] >= 'A' && cptr[2] <= 'F') ||
1171542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[2] >= 'a' && cptr[2] <= 'f') ||
1171642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  (cptr[2] >= '0' && cptr[2] <= '9'))) ||
1171742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		(!escape_reserved &&
1171842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		 (*cptr == ';' || *cptr == '/' || *cptr == '?' ||
1171942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == ':' || *cptr == '@' || *cptr == '&' ||
1172042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == '=' || *cptr == '+' || *cptr == '$' ||
1172142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		  *cptr == ','))) {
1172242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		xmlBufferAdd(target, cptr, 1);
1172342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    } else {
1172442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		if ((*cptr >> 4) < 10)
1172542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[1] = '0' + (*cptr >> 4);
1172642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		else
1172742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[1] = 'A' - 10 + (*cptr >> 4);
1172842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		if ((*cptr & 0xF) < 10)
1172942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[2] = '0' + (*cptr & 0xF);
1173042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		else
1173142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		    escape[2] = 'A' - 10 + (*cptr & 0xF);
1173242766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1173342766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard		xmlBufferAdd(target, &escape[0], 3);
1173442766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	    }
1173542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	}
1173642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    }
1173742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target)));
1173842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlBufferFree(target);
1173942766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathFreeObject(str);
1174042766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard}
1174142766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
117423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
117433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlXPathRegisterAllFunctions:
117443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @ctxt:  the XPath context
117453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
117463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Registers all default XPath functions in this context
117473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
117483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
117493473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
117503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor{
117513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
117523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathBooleanFunction);
117533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
117543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathCeilingFunction);
117553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
117563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathCountFunction);
117573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
117583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathConcatFunction);
117593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
117603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathContainsFunction);
117613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
117623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathIdFunction);
117633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
117643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathFalseFunction);
117653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
117663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathFloorFunction);
117673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
117683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLastFunction);
117693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
117703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLangFunction);
117713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
117723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathLocalNameFunction);
117733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
117743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNotFunction);
117753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
117763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNameFunction);
117773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
117783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNamespaceURIFunction);
117793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
117803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNormalizeFunction);
117813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
117823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathNumberFunction);
117833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
117843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathPositionFunction);
117853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
117863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathRoundFunction);
117873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
117883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStringFunction);
117893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
117903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStringLengthFunction);
117913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
117923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathStartsWithFunction);
117933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
117943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringFunction);
117953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
117963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringBeforeFunction);
117973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
117983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSubstringAfterFunction);
117993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
118003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathSumFunction);
118013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
118023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathTrueFunction);
118033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
118043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                         xmlXPathTranslateFunction);
1180542766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard
1180642766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard    xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
1180742766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard	 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
1180842766c0eea0fa40c7b721fa4c9cf56b4c484b4c7Daniel Veillard                         xmlXPathEscapeUriFunction);
118093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
118103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
118113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif /* LIBXML_XPATH_ENABLED */
118125d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#define bottom_xpath
118135d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#include "elfgcchack.h"
11814