xref: /aosp_15_r20/external/libxml2/xpath.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker  * xpath.c: XML Path Language implementation
3*7c568831SAndroid Build Coastguard Worker  *          XPath is a language for addressing parts of an XML document,
4*7c568831SAndroid Build Coastguard Worker  *          designed to be used by both XSLT and XPointer
5*7c568831SAndroid Build Coastguard Worker  *
6*7c568831SAndroid Build Coastguard Worker  * Reference: W3C Recommendation 16 November 1999
7*7c568831SAndroid Build Coastguard Worker  *     http://www.w3.org/TR/1999/REC-xpath-19991116
8*7c568831SAndroid Build Coastguard Worker  * Public reference:
9*7c568831SAndroid Build Coastguard Worker  *     http://www.w3.org/TR/xpath
10*7c568831SAndroid Build Coastguard Worker  *
11*7c568831SAndroid Build Coastguard Worker  * See Copyright for the status of this software
12*7c568831SAndroid Build Coastguard Worker  *
13*7c568831SAndroid Build Coastguard Worker  * Author: [email protected]
14*7c568831SAndroid Build Coastguard Worker  *
15*7c568831SAndroid Build Coastguard Worker  */
16*7c568831SAndroid Build Coastguard Worker 
17*7c568831SAndroid Build Coastguard Worker /* To avoid EBCDIC trouble when parsing on zOS */
18*7c568831SAndroid Build Coastguard Worker #if defined(__MVS__)
19*7c568831SAndroid Build Coastguard Worker #pragma convert("ISO8859-1")
20*7c568831SAndroid Build Coastguard Worker #endif
21*7c568831SAndroid Build Coastguard Worker 
22*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
23*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
24*7c568831SAndroid Build Coastguard Worker 
25*7c568831SAndroid Build Coastguard Worker #include <limits.h>
26*7c568831SAndroid Build Coastguard Worker #include <string.h>
27*7c568831SAndroid Build Coastguard Worker #include <stddef.h>
28*7c568831SAndroid Build Coastguard Worker #include <math.h>
29*7c568831SAndroid Build Coastguard Worker #include <float.h>
30*7c568831SAndroid Build Coastguard Worker #include <ctype.h>
31*7c568831SAndroid Build Coastguard Worker 
32*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
33*7c568831SAndroid Build Coastguard Worker #include <libxml/tree.h>
34*7c568831SAndroid Build Coastguard Worker #include <libxml/xpath.h>
35*7c568831SAndroid Build Coastguard Worker #include <libxml/xpathInternals.h>
36*7c568831SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
37*7c568831SAndroid Build Coastguard Worker #include <libxml/hash.h>
38*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_DEBUG_ENABLED
39*7c568831SAndroid Build Coastguard Worker #include <libxml/debugXML.h>
40*7c568831SAndroid Build Coastguard Worker #endif
41*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
42*7c568831SAndroid Build Coastguard Worker #include <libxml/threads.h>
43*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_PATTERN_ENABLED
44*7c568831SAndroid Build Coastguard Worker #include <libxml/pattern.h>
45*7c568831SAndroid Build Coastguard Worker #endif
46*7c568831SAndroid Build Coastguard Worker 
47*7c568831SAndroid Build Coastguard Worker #include "private/buf.h"
48*7c568831SAndroid Build Coastguard Worker #include "private/error.h"
49*7c568831SAndroid Build Coastguard Worker #include "private/xpath.h"
50*7c568831SAndroid Build Coastguard Worker 
51*7c568831SAndroid Build Coastguard Worker /* Disabled for now */
52*7c568831SAndroid Build Coastguard Worker #if 0
53*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_PATTERN_ENABLED
54*7c568831SAndroid Build Coastguard Worker #define XPATH_STREAMING
55*7c568831SAndroid Build Coastguard Worker #endif
56*7c568831SAndroid Build Coastguard Worker #endif
57*7c568831SAndroid Build Coastguard Worker 
58*7c568831SAndroid Build Coastguard Worker /**
59*7c568831SAndroid Build Coastguard Worker  * WITH_TIM_SORT:
60*7c568831SAndroid Build Coastguard Worker  *
61*7c568831SAndroid Build Coastguard Worker  * Use the Timsort algorithm provided in timsort.h to sort
62*7c568831SAndroid Build Coastguard Worker  * nodeset as this is a great improvement over the old Shell sort
63*7c568831SAndroid Build Coastguard Worker  * used in xmlXPathNodeSetSort()
64*7c568831SAndroid Build Coastguard Worker  */
65*7c568831SAndroid Build Coastguard Worker #define WITH_TIM_SORT
66*7c568831SAndroid Build Coastguard Worker 
67*7c568831SAndroid Build Coastguard Worker /*
68*7c568831SAndroid Build Coastguard Worker * XP_OPTIMIZED_NON_ELEM_COMPARISON:
69*7c568831SAndroid Build Coastguard Worker * If defined, this will use xmlXPathCmpNodesExt() instead of
70*7c568831SAndroid Build Coastguard Worker * xmlXPathCmpNodes(). The new function is optimized comparison of
71*7c568831SAndroid Build Coastguard Worker * non-element nodes; actually it will speed up comparison only if
72*7c568831SAndroid Build Coastguard Worker * xmlXPathOrderDocElems() was called in order to index the elements of
73*7c568831SAndroid Build Coastguard Worker * a tree in document order; Libxslt does such an indexing, thus it will
74*7c568831SAndroid Build Coastguard Worker * benefit from this optimization.
75*7c568831SAndroid Build Coastguard Worker */
76*7c568831SAndroid Build Coastguard Worker #define XP_OPTIMIZED_NON_ELEM_COMPARISON
77*7c568831SAndroid Build Coastguard Worker 
78*7c568831SAndroid Build Coastguard Worker /*
79*7c568831SAndroid Build Coastguard Worker * XP_OPTIMIZED_FILTER_FIRST:
80*7c568831SAndroid Build Coastguard Worker * If defined, this will optimize expressions like "key('foo', 'val')[b][1]"
81*7c568831SAndroid Build Coastguard Worker * in a way, that it stop evaluation at the first node.
82*7c568831SAndroid Build Coastguard Worker */
83*7c568831SAndroid Build Coastguard Worker #define XP_OPTIMIZED_FILTER_FIRST
84*7c568831SAndroid Build Coastguard Worker 
85*7c568831SAndroid Build Coastguard Worker /*
86*7c568831SAndroid Build Coastguard Worker  * XPATH_MAX_STEPS:
87*7c568831SAndroid Build Coastguard Worker  * when compiling an XPath expression we arbitrary limit the maximum
88*7c568831SAndroid Build Coastguard Worker  * number of step operation in the compiled expression. 1000000 is
89*7c568831SAndroid Build Coastguard Worker  * an insanely large value which should never be reached under normal
90*7c568831SAndroid Build Coastguard Worker  * circumstances
91*7c568831SAndroid Build Coastguard Worker  */
92*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_STEPS 1000000
93*7c568831SAndroid Build Coastguard Worker 
94*7c568831SAndroid Build Coastguard Worker /*
95*7c568831SAndroid Build Coastguard Worker  * XPATH_MAX_STACK_DEPTH:
96*7c568831SAndroid Build Coastguard Worker  * when evaluating an XPath expression we arbitrary limit the maximum
97*7c568831SAndroid Build Coastguard Worker  * number of object allowed to be pushed on the stack. 1000000 is
98*7c568831SAndroid Build Coastguard Worker  * an insanely large value which should never be reached under normal
99*7c568831SAndroid Build Coastguard Worker  * circumstances
100*7c568831SAndroid Build Coastguard Worker  */
101*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_STACK_DEPTH 1000000
102*7c568831SAndroid Build Coastguard Worker 
103*7c568831SAndroid Build Coastguard Worker /*
104*7c568831SAndroid Build Coastguard Worker  * XPATH_MAX_NODESET_LENGTH:
105*7c568831SAndroid Build Coastguard Worker  * when evaluating an XPath expression nodesets are created and we
106*7c568831SAndroid Build Coastguard Worker  * arbitrary limit the maximum length of those node set. 10000000 is
107*7c568831SAndroid Build Coastguard Worker  * an insanely large value which should never be reached under normal
108*7c568831SAndroid Build Coastguard Worker  * circumstances, one would first need to construct an in memory tree
109*7c568831SAndroid Build Coastguard Worker  * with more than 10 millions nodes.
110*7c568831SAndroid Build Coastguard Worker  */
111*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_NODESET_LENGTH 10000000
112*7c568831SAndroid Build Coastguard Worker 
113*7c568831SAndroid Build Coastguard Worker /*
114*7c568831SAndroid Build Coastguard Worker  * XPATH_MAX_RECRUSION_DEPTH:
115*7c568831SAndroid Build Coastguard Worker  * Maximum amount of nested functions calls when parsing or evaluating
116*7c568831SAndroid Build Coastguard Worker  * expressions
117*7c568831SAndroid Build Coastguard Worker  */
118*7c568831SAndroid Build Coastguard Worker #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
119*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 500
120*7c568831SAndroid Build Coastguard Worker #elif defined(_WIN32)
121*7c568831SAndroid Build Coastguard Worker /* Windows typically limits stack size to 1MB. */
122*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 1000
123*7c568831SAndroid Build Coastguard Worker #else
124*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 5000
125*7c568831SAndroid Build Coastguard Worker #endif
126*7c568831SAndroid Build Coastguard Worker 
127*7c568831SAndroid Build Coastguard Worker /*
128*7c568831SAndroid Build Coastguard Worker  * TODO:
129*7c568831SAndroid Build Coastguard Worker  * There are a few spots where some tests are done which depend upon ascii
130*7c568831SAndroid Build Coastguard Worker  * data.  These should be enhanced for full UTF8 support (see particularly
131*7c568831SAndroid Build Coastguard Worker  * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
132*7c568831SAndroid Build Coastguard Worker  */
133*7c568831SAndroid Build Coastguard Worker 
134*7c568831SAndroid Build Coastguard Worker #if defined(LIBXML_XPATH_ENABLED)
135*7c568831SAndroid Build Coastguard Worker 
136*7c568831SAndroid Build Coastguard Worker /************************************************************************
137*7c568831SAndroid Build Coastguard Worker  *									*
138*7c568831SAndroid Build Coastguard Worker  *			Floating point stuff				*
139*7c568831SAndroid Build Coastguard Worker  *									*
140*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
141*7c568831SAndroid Build Coastguard Worker 
142*7c568831SAndroid Build Coastguard Worker double xmlXPathNAN = 0.0;
143*7c568831SAndroid Build Coastguard Worker double xmlXPathPINF = 0.0;
144*7c568831SAndroid Build Coastguard Worker double xmlXPathNINF = 0.0;
145*7c568831SAndroid Build Coastguard Worker 
146*7c568831SAndroid Build Coastguard Worker /**
147*7c568831SAndroid Build Coastguard Worker  * xmlXPathInit:
148*7c568831SAndroid Build Coastguard Worker  *
149*7c568831SAndroid Build Coastguard Worker  * DEPRECATED: Alias for xmlInitParser.
150*7c568831SAndroid Build Coastguard Worker  */
151*7c568831SAndroid Build Coastguard Worker void
xmlXPathInit(void)152*7c568831SAndroid Build Coastguard Worker xmlXPathInit(void) {
153*7c568831SAndroid Build Coastguard Worker     xmlInitParser();
154*7c568831SAndroid Build Coastguard Worker }
155*7c568831SAndroid Build Coastguard Worker 
156*7c568831SAndroid Build Coastguard Worker /**
157*7c568831SAndroid Build Coastguard Worker  * xmlInitXPathInternal:
158*7c568831SAndroid Build Coastguard Worker  *
159*7c568831SAndroid Build Coastguard Worker  * Initialize the XPath environment
160*7c568831SAndroid Build Coastguard Worker  */
161*7c568831SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
162*7c568831SAndroid Build Coastguard Worker void
xmlInitXPathInternal(void)163*7c568831SAndroid Build Coastguard Worker xmlInitXPathInternal(void) {
164*7c568831SAndroid Build Coastguard Worker #if defined(NAN) && defined(INFINITY)
165*7c568831SAndroid Build Coastguard Worker     xmlXPathNAN = NAN;
166*7c568831SAndroid Build Coastguard Worker     xmlXPathPINF = INFINITY;
167*7c568831SAndroid Build Coastguard Worker     xmlXPathNINF = -INFINITY;
168*7c568831SAndroid Build Coastguard Worker #else
169*7c568831SAndroid Build Coastguard Worker     /* MSVC doesn't allow division by zero in constant expressions. */
170*7c568831SAndroid Build Coastguard Worker     double zero = 0.0;
171*7c568831SAndroid Build Coastguard Worker     xmlXPathNAN = 0.0 / zero;
172*7c568831SAndroid Build Coastguard Worker     xmlXPathPINF = 1.0 / zero;
173*7c568831SAndroid Build Coastguard Worker     xmlXPathNINF = -xmlXPathPINF;
174*7c568831SAndroid Build Coastguard Worker #endif
175*7c568831SAndroid Build Coastguard Worker }
176*7c568831SAndroid Build Coastguard Worker 
177*7c568831SAndroid Build Coastguard Worker /**
178*7c568831SAndroid Build Coastguard Worker  * xmlXPathIsNaN:
179*7c568831SAndroid Build Coastguard Worker  * @val:  a double value
180*7c568831SAndroid Build Coastguard Worker  *
181*7c568831SAndroid Build Coastguard Worker  * Checks whether a double is a NaN.
182*7c568831SAndroid Build Coastguard Worker  *
183*7c568831SAndroid Build Coastguard Worker  * Returns 1 if the value is a NaN, 0 otherwise
184*7c568831SAndroid Build Coastguard Worker  */
185*7c568831SAndroid Build Coastguard Worker int
xmlXPathIsNaN(double val)186*7c568831SAndroid Build Coastguard Worker xmlXPathIsNaN(double val) {
187*7c568831SAndroid Build Coastguard Worker #ifdef isnan
188*7c568831SAndroid Build Coastguard Worker     return isnan(val);
189*7c568831SAndroid Build Coastguard Worker #else
190*7c568831SAndroid Build Coastguard Worker     return !(val == val);
191*7c568831SAndroid Build Coastguard Worker #endif
192*7c568831SAndroid Build Coastguard Worker }
193*7c568831SAndroid Build Coastguard Worker 
194*7c568831SAndroid Build Coastguard Worker /**
195*7c568831SAndroid Build Coastguard Worker  * xmlXPathIsInf:
196*7c568831SAndroid Build Coastguard Worker  * @val:  a double value
197*7c568831SAndroid Build Coastguard Worker  *
198*7c568831SAndroid Build Coastguard Worker  * Checks whether a double is an infinity.
199*7c568831SAndroid Build Coastguard Worker  *
200*7c568831SAndroid Build Coastguard Worker  * Returns 1 if the value is +Infinite, -1 if -Infinite, 0 otherwise
201*7c568831SAndroid Build Coastguard Worker  */
202*7c568831SAndroid Build Coastguard Worker int
xmlXPathIsInf(double val)203*7c568831SAndroid Build Coastguard Worker xmlXPathIsInf(double val) {
204*7c568831SAndroid Build Coastguard Worker #ifdef isinf
205*7c568831SAndroid Build Coastguard Worker     return isinf(val) ? (val > 0 ? 1 : -1) : 0;
206*7c568831SAndroid Build Coastguard Worker #else
207*7c568831SAndroid Build Coastguard Worker     if (val >= xmlXPathPINF)
208*7c568831SAndroid Build Coastguard Worker         return 1;
209*7c568831SAndroid Build Coastguard Worker     if (val <= -xmlXPathPINF)
210*7c568831SAndroid Build Coastguard Worker         return -1;
211*7c568831SAndroid Build Coastguard Worker     return 0;
212*7c568831SAndroid Build Coastguard Worker #endif
213*7c568831SAndroid Build Coastguard Worker }
214*7c568831SAndroid Build Coastguard Worker 
215*7c568831SAndroid Build Coastguard Worker /*
216*7c568831SAndroid Build Coastguard Worker  * TODO: when compatibility allows remove all "fake node libxslt" strings
217*7c568831SAndroid Build Coastguard Worker  *       the test should just be name[0] = ' '
218*7c568831SAndroid Build Coastguard Worker  */
219*7c568831SAndroid Build Coastguard Worker 
220*7c568831SAndroid Build Coastguard Worker static const xmlNs xmlXPathXMLNamespaceStruct = {
221*7c568831SAndroid Build Coastguard Worker     NULL,
222*7c568831SAndroid Build Coastguard Worker     XML_NAMESPACE_DECL,
223*7c568831SAndroid Build Coastguard Worker     XML_XML_NAMESPACE,
224*7c568831SAndroid Build Coastguard Worker     BAD_CAST "xml",
225*7c568831SAndroid Build Coastguard Worker     NULL,
226*7c568831SAndroid Build Coastguard Worker     NULL
227*7c568831SAndroid Build Coastguard Worker };
228*7c568831SAndroid Build Coastguard Worker static const xmlNs *const xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
229*7c568831SAndroid Build Coastguard Worker 
230*7c568831SAndroid Build Coastguard Worker static void
231*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes);
232*7c568831SAndroid Build Coastguard Worker 
233*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
234*7c568831SAndroid Build Coastguard Worker /**
235*7c568831SAndroid Build Coastguard Worker  * xmlXPathCmpNodesExt:
236*7c568831SAndroid Build Coastguard Worker  * @node1:  the first node
237*7c568831SAndroid Build Coastguard Worker  * @node2:  the second node
238*7c568831SAndroid Build Coastguard Worker  *
239*7c568831SAndroid Build Coastguard Worker  * Compare two nodes w.r.t document order.
240*7c568831SAndroid Build Coastguard Worker  * This one is optimized for handling of non-element nodes.
241*7c568831SAndroid Build Coastguard Worker  *
242*7c568831SAndroid Build Coastguard Worker  * Returns -2 in case of error 1 if first point < second point, 0 if
243*7c568831SAndroid Build Coastguard Worker  *         it's the same node, -1 otherwise
244*7c568831SAndroid Build Coastguard Worker  */
245*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCmpNodesExt(xmlNodePtr node1,xmlNodePtr node2)246*7c568831SAndroid Build Coastguard Worker xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
247*7c568831SAndroid Build Coastguard Worker     int depth1, depth2;
248*7c568831SAndroid Build Coastguard Worker     int misc = 0, precedence1 = 0, precedence2 = 0;
249*7c568831SAndroid Build Coastguard Worker     xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
250*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur, root;
251*7c568831SAndroid Build Coastguard Worker     ptrdiff_t l1, l2;
252*7c568831SAndroid Build Coastguard Worker 
253*7c568831SAndroid Build Coastguard Worker     if ((node1 == NULL) || (node2 == NULL))
254*7c568831SAndroid Build Coastguard Worker 	return(-2);
255*7c568831SAndroid Build Coastguard Worker 
256*7c568831SAndroid Build Coastguard Worker     if (node1 == node2)
257*7c568831SAndroid Build Coastguard Worker 	return(0);
258*7c568831SAndroid Build Coastguard Worker 
259*7c568831SAndroid Build Coastguard Worker     /*
260*7c568831SAndroid Build Coastguard Worker      * a couple of optimizations which will avoid computations in most cases
261*7c568831SAndroid Build Coastguard Worker      */
262*7c568831SAndroid Build Coastguard Worker     switch (node1->type) {
263*7c568831SAndroid Build Coastguard Worker 	case XML_ELEMENT_NODE:
264*7c568831SAndroid Build Coastguard Worker 	    if (node2->type == XML_ELEMENT_NODE) {
265*7c568831SAndroid Build Coastguard Worker 		if ((0 > (ptrdiff_t) node1->content) &&
266*7c568831SAndroid Build Coastguard Worker 		    (0 > (ptrdiff_t) node2->content) &&
267*7c568831SAndroid Build Coastguard Worker 		    (node1->doc == node2->doc))
268*7c568831SAndroid Build Coastguard Worker 		{
269*7c568831SAndroid Build Coastguard Worker 		    l1 = -((ptrdiff_t) node1->content);
270*7c568831SAndroid Build Coastguard Worker 		    l2 = -((ptrdiff_t) node2->content);
271*7c568831SAndroid Build Coastguard Worker 		    if (l1 < l2)
272*7c568831SAndroid Build Coastguard Worker 			return(1);
273*7c568831SAndroid Build Coastguard Worker 		    if (l1 > l2)
274*7c568831SAndroid Build Coastguard Worker 			return(-1);
275*7c568831SAndroid Build Coastguard Worker 		} else
276*7c568831SAndroid Build Coastguard Worker 		    goto turtle_comparison;
277*7c568831SAndroid Build Coastguard Worker 	    }
278*7c568831SAndroid Build Coastguard Worker 	    break;
279*7c568831SAndroid Build Coastguard Worker 	case XML_ATTRIBUTE_NODE:
280*7c568831SAndroid Build Coastguard Worker 	    precedence1 = 1; /* element is owner */
281*7c568831SAndroid Build Coastguard Worker 	    miscNode1 = node1;
282*7c568831SAndroid Build Coastguard Worker 	    node1 = node1->parent;
283*7c568831SAndroid Build Coastguard Worker 	    misc = 1;
284*7c568831SAndroid Build Coastguard Worker 	    break;
285*7c568831SAndroid Build Coastguard Worker 	case XML_TEXT_NODE:
286*7c568831SAndroid Build Coastguard Worker 	case XML_CDATA_SECTION_NODE:
287*7c568831SAndroid Build Coastguard Worker 	case XML_COMMENT_NODE:
288*7c568831SAndroid Build Coastguard Worker 	case XML_PI_NODE: {
289*7c568831SAndroid Build Coastguard Worker 	    miscNode1 = node1;
290*7c568831SAndroid Build Coastguard Worker 	    /*
291*7c568831SAndroid Build Coastguard Worker 	    * Find nearest element node.
292*7c568831SAndroid Build Coastguard Worker 	    */
293*7c568831SAndroid Build Coastguard Worker 	    if (node1->prev != NULL) {
294*7c568831SAndroid Build Coastguard Worker 		do {
295*7c568831SAndroid Build Coastguard Worker 		    node1 = node1->prev;
296*7c568831SAndroid Build Coastguard Worker 		    if (node1->type == XML_ELEMENT_NODE) {
297*7c568831SAndroid Build Coastguard Worker 			precedence1 = 3; /* element in prev-sibl axis */
298*7c568831SAndroid Build Coastguard Worker 			break;
299*7c568831SAndroid Build Coastguard Worker 		    }
300*7c568831SAndroid Build Coastguard Worker 		    if (node1->prev == NULL) {
301*7c568831SAndroid Build Coastguard Worker 			precedence1 = 2; /* element is parent */
302*7c568831SAndroid Build Coastguard Worker 			/*
303*7c568831SAndroid Build Coastguard Worker 			* URGENT TODO: Are there any cases, where the
304*7c568831SAndroid Build Coastguard Worker 			* parent of such a node is not an element node?
305*7c568831SAndroid Build Coastguard Worker 			*/
306*7c568831SAndroid Build Coastguard Worker 			node1 = node1->parent;
307*7c568831SAndroid Build Coastguard Worker 			break;
308*7c568831SAndroid Build Coastguard Worker 		    }
309*7c568831SAndroid Build Coastguard Worker 		} while (1);
310*7c568831SAndroid Build Coastguard Worker 	    } else {
311*7c568831SAndroid Build Coastguard Worker 		precedence1 = 2; /* element is parent */
312*7c568831SAndroid Build Coastguard Worker 		node1 = node1->parent;
313*7c568831SAndroid Build Coastguard Worker 	    }
314*7c568831SAndroid Build Coastguard Worker 	    if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
315*7c568831SAndroid Build Coastguard Worker 		(0 <= (ptrdiff_t) node1->content)) {
316*7c568831SAndroid Build Coastguard Worker 		/*
317*7c568831SAndroid Build Coastguard Worker 		* Fallback for whatever case.
318*7c568831SAndroid Build Coastguard Worker 		*/
319*7c568831SAndroid Build Coastguard Worker 		node1 = miscNode1;
320*7c568831SAndroid Build Coastguard Worker 		precedence1 = 0;
321*7c568831SAndroid Build Coastguard Worker 	    } else
322*7c568831SAndroid Build Coastguard Worker 		misc = 1;
323*7c568831SAndroid Build Coastguard Worker 	}
324*7c568831SAndroid Build Coastguard Worker 	    break;
325*7c568831SAndroid Build Coastguard Worker 	case XML_NAMESPACE_DECL:
326*7c568831SAndroid Build Coastguard Worker 	    /*
327*7c568831SAndroid Build Coastguard Worker 	    * TODO: why do we return 1 for namespace nodes?
328*7c568831SAndroid Build Coastguard Worker 	    */
329*7c568831SAndroid Build Coastguard Worker 	    return(1);
330*7c568831SAndroid Build Coastguard Worker 	default:
331*7c568831SAndroid Build Coastguard Worker 	    break;
332*7c568831SAndroid Build Coastguard Worker     }
333*7c568831SAndroid Build Coastguard Worker     switch (node2->type) {
334*7c568831SAndroid Build Coastguard Worker 	case XML_ELEMENT_NODE:
335*7c568831SAndroid Build Coastguard Worker 	    break;
336*7c568831SAndroid Build Coastguard Worker 	case XML_ATTRIBUTE_NODE:
337*7c568831SAndroid Build Coastguard Worker 	    precedence2 = 1; /* element is owner */
338*7c568831SAndroid Build Coastguard Worker 	    miscNode2 = node2;
339*7c568831SAndroid Build Coastguard Worker 	    node2 = node2->parent;
340*7c568831SAndroid Build Coastguard Worker 	    misc = 1;
341*7c568831SAndroid Build Coastguard Worker 	    break;
342*7c568831SAndroid Build Coastguard Worker 	case XML_TEXT_NODE:
343*7c568831SAndroid Build Coastguard Worker 	case XML_CDATA_SECTION_NODE:
344*7c568831SAndroid Build Coastguard Worker 	case XML_COMMENT_NODE:
345*7c568831SAndroid Build Coastguard Worker 	case XML_PI_NODE: {
346*7c568831SAndroid Build Coastguard Worker 	    miscNode2 = node2;
347*7c568831SAndroid Build Coastguard Worker 	    if (node2->prev != NULL) {
348*7c568831SAndroid Build Coastguard Worker 		do {
349*7c568831SAndroid Build Coastguard Worker 		    node2 = node2->prev;
350*7c568831SAndroid Build Coastguard Worker 		    if (node2->type == XML_ELEMENT_NODE) {
351*7c568831SAndroid Build Coastguard Worker 			precedence2 = 3; /* element in prev-sibl axis */
352*7c568831SAndroid Build Coastguard Worker 			break;
353*7c568831SAndroid Build Coastguard Worker 		    }
354*7c568831SAndroid Build Coastguard Worker 		    if (node2->prev == NULL) {
355*7c568831SAndroid Build Coastguard Worker 			precedence2 = 2; /* element is parent */
356*7c568831SAndroid Build Coastguard Worker 			node2 = node2->parent;
357*7c568831SAndroid Build Coastguard Worker 			break;
358*7c568831SAndroid Build Coastguard Worker 		    }
359*7c568831SAndroid Build Coastguard Worker 		} while (1);
360*7c568831SAndroid Build Coastguard Worker 	    } else {
361*7c568831SAndroid Build Coastguard Worker 		precedence2 = 2; /* element is parent */
362*7c568831SAndroid Build Coastguard Worker 		node2 = node2->parent;
363*7c568831SAndroid Build Coastguard Worker 	    }
364*7c568831SAndroid Build Coastguard Worker 	    if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
365*7c568831SAndroid Build Coastguard Worker 		(0 <= (ptrdiff_t) node2->content))
366*7c568831SAndroid Build Coastguard Worker 	    {
367*7c568831SAndroid Build Coastguard Worker 		node2 = miscNode2;
368*7c568831SAndroid Build Coastguard Worker 		precedence2 = 0;
369*7c568831SAndroid Build Coastguard Worker 	    } else
370*7c568831SAndroid Build Coastguard Worker 		misc = 1;
371*7c568831SAndroid Build Coastguard Worker 	}
372*7c568831SAndroid Build Coastguard Worker 	    break;
373*7c568831SAndroid Build Coastguard Worker 	case XML_NAMESPACE_DECL:
374*7c568831SAndroid Build Coastguard Worker 	    return(1);
375*7c568831SAndroid Build Coastguard Worker 	default:
376*7c568831SAndroid Build Coastguard Worker 	    break;
377*7c568831SAndroid Build Coastguard Worker     }
378*7c568831SAndroid Build Coastguard Worker     if (misc) {
379*7c568831SAndroid Build Coastguard Worker 	if (node1 == node2) {
380*7c568831SAndroid Build Coastguard Worker 	    if (precedence1 == precedence2) {
381*7c568831SAndroid Build Coastguard Worker 		/*
382*7c568831SAndroid Build Coastguard Worker 		* The ugly case; but normally there aren't many
383*7c568831SAndroid Build Coastguard Worker 		* adjacent non-element nodes around.
384*7c568831SAndroid Build Coastguard Worker 		*/
385*7c568831SAndroid Build Coastguard Worker 		cur = miscNode2->prev;
386*7c568831SAndroid Build Coastguard Worker 		while (cur != NULL) {
387*7c568831SAndroid Build Coastguard Worker 		    if (cur == miscNode1)
388*7c568831SAndroid Build Coastguard Worker 			return(1);
389*7c568831SAndroid Build Coastguard Worker 		    if (cur->type == XML_ELEMENT_NODE)
390*7c568831SAndroid Build Coastguard Worker 			return(-1);
391*7c568831SAndroid Build Coastguard Worker 		    cur = cur->prev;
392*7c568831SAndroid Build Coastguard Worker 		}
393*7c568831SAndroid Build Coastguard Worker 		return (-1);
394*7c568831SAndroid Build Coastguard Worker 	    } else {
395*7c568831SAndroid Build Coastguard Worker 		/*
396*7c568831SAndroid Build Coastguard Worker 		* Evaluate based on higher precedence wrt to the element.
397*7c568831SAndroid Build Coastguard Worker 		* TODO: This assumes attributes are sorted before content.
398*7c568831SAndroid Build Coastguard Worker 		*   Is this 100% correct?
399*7c568831SAndroid Build Coastguard Worker 		*/
400*7c568831SAndroid Build Coastguard Worker 		if (precedence1 < precedence2)
401*7c568831SAndroid Build Coastguard Worker 		    return(1);
402*7c568831SAndroid Build Coastguard Worker 		else
403*7c568831SAndroid Build Coastguard Worker 		    return(-1);
404*7c568831SAndroid Build Coastguard Worker 	    }
405*7c568831SAndroid Build Coastguard Worker 	}
406*7c568831SAndroid Build Coastguard Worker 	/*
407*7c568831SAndroid Build Coastguard Worker 	* Special case: One of the helper-elements is contained by the other.
408*7c568831SAndroid Build Coastguard Worker 	* <foo>
409*7c568831SAndroid Build Coastguard Worker 	*   <node2>
410*7c568831SAndroid Build Coastguard Worker 	*     <node1>Text-1(precedence1 == 2)</node1>
411*7c568831SAndroid Build Coastguard Worker 	*   </node2>
412*7c568831SAndroid Build Coastguard Worker 	*   Text-6(precedence2 == 3)
413*7c568831SAndroid Build Coastguard Worker 	* </foo>
414*7c568831SAndroid Build Coastguard Worker 	*/
415*7c568831SAndroid Build Coastguard Worker 	if ((precedence2 == 3) && (precedence1 > 1)) {
416*7c568831SAndroid Build Coastguard Worker 	    cur = node1->parent;
417*7c568831SAndroid Build Coastguard Worker 	    while (cur) {
418*7c568831SAndroid Build Coastguard Worker 		if (cur == node2)
419*7c568831SAndroid Build Coastguard Worker 		    return(1);
420*7c568831SAndroid Build Coastguard Worker 		cur = cur->parent;
421*7c568831SAndroid Build Coastguard Worker 	    }
422*7c568831SAndroid Build Coastguard Worker 	}
423*7c568831SAndroid Build Coastguard Worker 	if ((precedence1 == 3) && (precedence2 > 1)) {
424*7c568831SAndroid Build Coastguard Worker 	    cur = node2->parent;
425*7c568831SAndroid Build Coastguard Worker 	    while (cur) {
426*7c568831SAndroid Build Coastguard Worker 		if (cur == node1)
427*7c568831SAndroid Build Coastguard Worker 		    return(-1);
428*7c568831SAndroid Build Coastguard Worker 		cur = cur->parent;
429*7c568831SAndroid Build Coastguard Worker 	    }
430*7c568831SAndroid Build Coastguard Worker 	}
431*7c568831SAndroid Build Coastguard Worker     }
432*7c568831SAndroid Build Coastguard Worker 
433*7c568831SAndroid Build Coastguard Worker     /*
434*7c568831SAndroid Build Coastguard Worker      * Speedup using document order if available.
435*7c568831SAndroid Build Coastguard Worker      */
436*7c568831SAndroid Build Coastguard Worker     if ((node1->type == XML_ELEMENT_NODE) &&
437*7c568831SAndroid Build Coastguard Worker 	(node2->type == XML_ELEMENT_NODE) &&
438*7c568831SAndroid Build Coastguard Worker 	(0 > (ptrdiff_t) node1->content) &&
439*7c568831SAndroid Build Coastguard Worker 	(0 > (ptrdiff_t) node2->content) &&
440*7c568831SAndroid Build Coastguard Worker 	(node1->doc == node2->doc)) {
441*7c568831SAndroid Build Coastguard Worker 
442*7c568831SAndroid Build Coastguard Worker 	l1 = -((ptrdiff_t) node1->content);
443*7c568831SAndroid Build Coastguard Worker 	l2 = -((ptrdiff_t) node2->content);
444*7c568831SAndroid Build Coastguard Worker 	if (l1 < l2)
445*7c568831SAndroid Build Coastguard Worker 	    return(1);
446*7c568831SAndroid Build Coastguard Worker 	if (l1 > l2)
447*7c568831SAndroid Build Coastguard Worker 	    return(-1);
448*7c568831SAndroid Build Coastguard Worker     }
449*7c568831SAndroid Build Coastguard Worker 
450*7c568831SAndroid Build Coastguard Worker turtle_comparison:
451*7c568831SAndroid Build Coastguard Worker 
452*7c568831SAndroid Build Coastguard Worker     if (node1 == node2->prev)
453*7c568831SAndroid Build Coastguard Worker 	return(1);
454*7c568831SAndroid Build Coastguard Worker     if (node1 == node2->next)
455*7c568831SAndroid Build Coastguard Worker 	return(-1);
456*7c568831SAndroid Build Coastguard Worker     /*
457*7c568831SAndroid Build Coastguard Worker      * compute depth to root
458*7c568831SAndroid Build Coastguard Worker      */
459*7c568831SAndroid Build Coastguard Worker     for (depth2 = 0, cur = node2; cur->parent != NULL; cur = cur->parent) {
460*7c568831SAndroid Build Coastguard Worker 	if (cur->parent == node1)
461*7c568831SAndroid Build Coastguard Worker 	    return(1);
462*7c568831SAndroid Build Coastguard Worker 	depth2++;
463*7c568831SAndroid Build Coastguard Worker     }
464*7c568831SAndroid Build Coastguard Worker     root = cur;
465*7c568831SAndroid Build Coastguard Worker     for (depth1 = 0, cur = node1; cur->parent != NULL; cur = cur->parent) {
466*7c568831SAndroid Build Coastguard Worker 	if (cur->parent == node2)
467*7c568831SAndroid Build Coastguard Worker 	    return(-1);
468*7c568831SAndroid Build Coastguard Worker 	depth1++;
469*7c568831SAndroid Build Coastguard Worker     }
470*7c568831SAndroid Build Coastguard Worker     /*
471*7c568831SAndroid Build Coastguard Worker      * Distinct document (or distinct entities :-( ) case.
472*7c568831SAndroid Build Coastguard Worker      */
473*7c568831SAndroid Build Coastguard Worker     if (root != cur) {
474*7c568831SAndroid Build Coastguard Worker 	return(-2);
475*7c568831SAndroid Build Coastguard Worker     }
476*7c568831SAndroid Build Coastguard Worker     /*
477*7c568831SAndroid Build Coastguard Worker      * get the nearest common ancestor.
478*7c568831SAndroid Build Coastguard Worker      */
479*7c568831SAndroid Build Coastguard Worker     while (depth1 > depth2) {
480*7c568831SAndroid Build Coastguard Worker 	depth1--;
481*7c568831SAndroid Build Coastguard Worker 	node1 = node1->parent;
482*7c568831SAndroid Build Coastguard Worker     }
483*7c568831SAndroid Build Coastguard Worker     while (depth2 > depth1) {
484*7c568831SAndroid Build Coastguard Worker 	depth2--;
485*7c568831SAndroid Build Coastguard Worker 	node2 = node2->parent;
486*7c568831SAndroid Build Coastguard Worker     }
487*7c568831SAndroid Build Coastguard Worker     while (node1->parent != node2->parent) {
488*7c568831SAndroid Build Coastguard Worker 	node1 = node1->parent;
489*7c568831SAndroid Build Coastguard Worker 	node2 = node2->parent;
490*7c568831SAndroid Build Coastguard Worker 	/* should not happen but just in case ... */
491*7c568831SAndroid Build Coastguard Worker 	if ((node1 == NULL) || (node2 == NULL))
492*7c568831SAndroid Build Coastguard Worker 	    return(-2);
493*7c568831SAndroid Build Coastguard Worker     }
494*7c568831SAndroid Build Coastguard Worker     /*
495*7c568831SAndroid Build Coastguard Worker      * Find who's first.
496*7c568831SAndroid Build Coastguard Worker      */
497*7c568831SAndroid Build Coastguard Worker     if (node1 == node2->prev)
498*7c568831SAndroid Build Coastguard Worker 	return(1);
499*7c568831SAndroid Build Coastguard Worker     if (node1 == node2->next)
500*7c568831SAndroid Build Coastguard Worker 	return(-1);
501*7c568831SAndroid Build Coastguard Worker     /*
502*7c568831SAndroid Build Coastguard Worker      * Speedup using document order if available.
503*7c568831SAndroid Build Coastguard Worker      */
504*7c568831SAndroid Build Coastguard Worker     if ((node1->type == XML_ELEMENT_NODE) &&
505*7c568831SAndroid Build Coastguard Worker 	(node2->type == XML_ELEMENT_NODE) &&
506*7c568831SAndroid Build Coastguard Worker 	(0 > (ptrdiff_t) node1->content) &&
507*7c568831SAndroid Build Coastguard Worker 	(0 > (ptrdiff_t) node2->content) &&
508*7c568831SAndroid Build Coastguard Worker 	(node1->doc == node2->doc)) {
509*7c568831SAndroid Build Coastguard Worker 
510*7c568831SAndroid Build Coastguard Worker 	l1 = -((ptrdiff_t) node1->content);
511*7c568831SAndroid Build Coastguard Worker 	l2 = -((ptrdiff_t) node2->content);
512*7c568831SAndroid Build Coastguard Worker 	if (l1 < l2)
513*7c568831SAndroid Build Coastguard Worker 	    return(1);
514*7c568831SAndroid Build Coastguard Worker 	if (l1 > l2)
515*7c568831SAndroid Build Coastguard Worker 	    return(-1);
516*7c568831SAndroid Build Coastguard Worker     }
517*7c568831SAndroid Build Coastguard Worker 
518*7c568831SAndroid Build Coastguard Worker     for (cur = node1->next;cur != NULL;cur = cur->next)
519*7c568831SAndroid Build Coastguard Worker 	if (cur == node2)
520*7c568831SAndroid Build Coastguard Worker 	    return(1);
521*7c568831SAndroid Build Coastguard Worker     return(-1); /* assume there is no sibling list corruption */
522*7c568831SAndroid Build Coastguard Worker }
523*7c568831SAndroid Build Coastguard Worker #endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */
524*7c568831SAndroid Build Coastguard Worker 
525*7c568831SAndroid Build Coastguard Worker /*
526*7c568831SAndroid Build Coastguard Worker  * Wrapper for the Timsort algorithm from timsort.h
527*7c568831SAndroid Build Coastguard Worker  */
528*7c568831SAndroid Build Coastguard Worker #ifdef WITH_TIM_SORT
529*7c568831SAndroid Build Coastguard Worker #define SORT_NAME libxml_domnode
530*7c568831SAndroid Build Coastguard Worker #define SORT_TYPE xmlNodePtr
531*7c568831SAndroid Build Coastguard Worker /**
532*7c568831SAndroid Build Coastguard Worker  * wrap_cmp:
533*7c568831SAndroid Build Coastguard Worker  * @x: a node
534*7c568831SAndroid Build Coastguard Worker  * @y: another node
535*7c568831SAndroid Build Coastguard Worker  *
536*7c568831SAndroid Build Coastguard Worker  * Comparison function for the Timsort implementation
537*7c568831SAndroid Build Coastguard Worker  *
538*7c568831SAndroid Build Coastguard Worker  * Returns -2 in case of error -1 if first point < second point, 0 if
539*7c568831SAndroid Build Coastguard Worker  *         it's the same node, +1 otherwise
540*7c568831SAndroid Build Coastguard Worker  */
541*7c568831SAndroid Build Coastguard Worker static
542*7c568831SAndroid Build Coastguard Worker int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
543*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
wrap_cmp(xmlNodePtr x,xmlNodePtr y)544*7c568831SAndroid Build Coastguard Worker     static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
545*7c568831SAndroid Build Coastguard Worker     {
546*7c568831SAndroid Build Coastguard Worker         int res = xmlXPathCmpNodesExt(x, y);
547*7c568831SAndroid Build Coastguard Worker         return res == -2 ? res : -res;
548*7c568831SAndroid Build Coastguard Worker     }
549*7c568831SAndroid Build Coastguard Worker #else
wrap_cmp(xmlNodePtr x,xmlNodePtr y)550*7c568831SAndroid Build Coastguard Worker     static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
551*7c568831SAndroid Build Coastguard Worker     {
552*7c568831SAndroid Build Coastguard Worker         int res = xmlXPathCmpNodes(x, y);
553*7c568831SAndroid Build Coastguard Worker         return res == -2 ? res : -res;
554*7c568831SAndroid Build Coastguard Worker     }
555*7c568831SAndroid Build Coastguard Worker #endif
556*7c568831SAndroid Build Coastguard Worker #define SORT_CMP(x, y)  (wrap_cmp(x, y))
557*7c568831SAndroid Build Coastguard Worker #include "timsort.h"
558*7c568831SAndroid Build Coastguard Worker #endif /* WITH_TIM_SORT */
559*7c568831SAndroid Build Coastguard Worker 
560*7c568831SAndroid Build Coastguard Worker /************************************************************************
561*7c568831SAndroid Build Coastguard Worker  *									*
562*7c568831SAndroid Build Coastguard Worker  *			Error handling routines				*
563*7c568831SAndroid Build Coastguard Worker  *									*
564*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
565*7c568831SAndroid Build Coastguard Worker 
566*7c568831SAndroid Build Coastguard Worker /**
567*7c568831SAndroid Build Coastguard Worker  * XP_ERRORNULL:
568*7c568831SAndroid Build Coastguard Worker  * @X:  the error code
569*7c568831SAndroid Build Coastguard Worker  *
570*7c568831SAndroid Build Coastguard Worker  * Macro to raise an XPath error and return NULL.
571*7c568831SAndroid Build Coastguard Worker  */
572*7c568831SAndroid Build Coastguard Worker #define XP_ERRORNULL(X)							\
573*7c568831SAndroid Build Coastguard Worker     { xmlXPathErr(ctxt, X); return(NULL); }
574*7c568831SAndroid Build Coastguard Worker 
575*7c568831SAndroid Build Coastguard Worker /*
576*7c568831SAndroid Build Coastguard Worker  * The array xmlXPathErrorMessages corresponds to the enum xmlXPathError
577*7c568831SAndroid Build Coastguard Worker  */
578*7c568831SAndroid Build Coastguard Worker static const char* const xmlXPathErrorMessages[] = {
579*7c568831SAndroid Build Coastguard Worker     "Ok\n",
580*7c568831SAndroid Build Coastguard Worker     "Number encoding\n",
581*7c568831SAndroid Build Coastguard Worker     "Unfinished literal\n",
582*7c568831SAndroid Build Coastguard Worker     "Start of literal\n",
583*7c568831SAndroid Build Coastguard Worker     "Expected $ for variable reference\n",
584*7c568831SAndroid Build Coastguard Worker     "Undefined variable\n",
585*7c568831SAndroid Build Coastguard Worker     "Invalid predicate\n",
586*7c568831SAndroid Build Coastguard Worker     "Invalid expression\n",
587*7c568831SAndroid Build Coastguard Worker     "Missing closing curly brace\n",
588*7c568831SAndroid Build Coastguard Worker     "Unregistered function\n",
589*7c568831SAndroid Build Coastguard Worker     "Invalid operand\n",
590*7c568831SAndroid Build Coastguard Worker     "Invalid type\n",
591*7c568831SAndroid Build Coastguard Worker     "Invalid number of arguments\n",
592*7c568831SAndroid Build Coastguard Worker     "Invalid context size\n",
593*7c568831SAndroid Build Coastguard Worker     "Invalid context position\n",
594*7c568831SAndroid Build Coastguard Worker     "Memory allocation error\n",
595*7c568831SAndroid Build Coastguard Worker     "Syntax error\n",
596*7c568831SAndroid Build Coastguard Worker     "Resource error\n",
597*7c568831SAndroid Build Coastguard Worker     "Sub resource error\n",
598*7c568831SAndroid Build Coastguard Worker     "Undefined namespace prefix\n",
599*7c568831SAndroid Build Coastguard Worker     "Encoding error\n",
600*7c568831SAndroid Build Coastguard Worker     "Char out of XML range\n",
601*7c568831SAndroid Build Coastguard Worker     "Invalid or incomplete context\n",
602*7c568831SAndroid Build Coastguard Worker     "Stack usage error\n",
603*7c568831SAndroid Build Coastguard Worker     "Forbidden variable\n",
604*7c568831SAndroid Build Coastguard Worker     "Operation limit exceeded\n",
605*7c568831SAndroid Build Coastguard Worker     "Recursion limit exceeded\n",
606*7c568831SAndroid Build Coastguard Worker     "?? Unknown error ??\n"	/* Must be last in the list! */
607*7c568831SAndroid Build Coastguard Worker };
608*7c568831SAndroid Build Coastguard Worker #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) /	\
609*7c568831SAndroid Build Coastguard Worker 		   sizeof(xmlXPathErrorMessages[0])) - 1)
610*7c568831SAndroid Build Coastguard Worker /**
611*7c568831SAndroid Build Coastguard Worker  * xmlXPathErrMemory:
612*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an XPath context
613*7c568831SAndroid Build Coastguard Worker  *
614*7c568831SAndroid Build Coastguard Worker  * Handle a memory allocation failure.
615*7c568831SAndroid Build Coastguard Worker  */
616*7c568831SAndroid Build Coastguard Worker void
xmlXPathErrMemory(xmlXPathContextPtr ctxt)617*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(xmlXPathContextPtr ctxt)
618*7c568831SAndroid Build Coastguard Worker {
619*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
620*7c568831SAndroid Build Coastguard Worker         return;
621*7c568831SAndroid Build Coastguard Worker     xmlRaiseMemoryError(ctxt->error, NULL, ctxt->userData, XML_FROM_XPATH,
622*7c568831SAndroid Build Coastguard Worker                         &ctxt->lastError);
623*7c568831SAndroid Build Coastguard Worker }
624*7c568831SAndroid Build Coastguard Worker 
625*7c568831SAndroid Build Coastguard Worker /**
626*7c568831SAndroid Build Coastguard Worker  * xmlXPathPErrMemory:
627*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an XPath parser context
628*7c568831SAndroid Build Coastguard Worker  *
629*7c568831SAndroid Build Coastguard Worker  * Handle a memory allocation failure.
630*7c568831SAndroid Build Coastguard Worker  */
631*7c568831SAndroid Build Coastguard Worker void
xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt)632*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt)
633*7c568831SAndroid Build Coastguard Worker {
634*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
635*7c568831SAndroid Build Coastguard Worker         return;
636*7c568831SAndroid Build Coastguard Worker     ctxt->error = XPATH_MEMORY_ERROR;
637*7c568831SAndroid Build Coastguard Worker     xmlXPathErrMemory(ctxt->context);
638*7c568831SAndroid Build Coastguard Worker }
639*7c568831SAndroid Build Coastguard Worker 
640*7c568831SAndroid Build Coastguard Worker /**
641*7c568831SAndroid Build Coastguard Worker  * xmlXPathErr:
642*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a XPath parser context
643*7c568831SAndroid Build Coastguard Worker  * @code:  the error code
644*7c568831SAndroid Build Coastguard Worker  *
645*7c568831SAndroid Build Coastguard Worker  * Handle an XPath error
646*7c568831SAndroid Build Coastguard Worker  */
647*7c568831SAndroid Build Coastguard Worker void
xmlXPathErr(xmlXPathParserContextPtr ctxt,int code)648*7c568831SAndroid Build Coastguard Worker xmlXPathErr(xmlXPathParserContextPtr ctxt, int code)
649*7c568831SAndroid Build Coastguard Worker {
650*7c568831SAndroid Build Coastguard Worker     xmlStructuredErrorFunc schannel = NULL;
651*7c568831SAndroid Build Coastguard Worker     xmlGenericErrorFunc channel = NULL;
652*7c568831SAndroid Build Coastguard Worker     void *data = NULL;
653*7c568831SAndroid Build Coastguard Worker     xmlNodePtr node = NULL;
654*7c568831SAndroid Build Coastguard Worker     int res;
655*7c568831SAndroid Build Coastguard Worker 
656*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
657*7c568831SAndroid Build Coastguard Worker         return;
658*7c568831SAndroid Build Coastguard Worker     if ((code < 0) || (code > MAXERRNO))
659*7c568831SAndroid Build Coastguard Worker 	code = MAXERRNO;
660*7c568831SAndroid Build Coastguard Worker     /* Only report the first error */
661*7c568831SAndroid Build Coastguard Worker     if (ctxt->error != 0)
662*7c568831SAndroid Build Coastguard Worker         return;
663*7c568831SAndroid Build Coastguard Worker 
664*7c568831SAndroid Build Coastguard Worker     ctxt->error = code;
665*7c568831SAndroid Build Coastguard Worker 
666*7c568831SAndroid Build Coastguard Worker     if (ctxt->context != NULL) {
667*7c568831SAndroid Build Coastguard Worker         xmlErrorPtr err = &ctxt->context->lastError;
668*7c568831SAndroid Build Coastguard Worker 
669*7c568831SAndroid Build Coastguard Worker         /* Don't overwrite memory error. */
670*7c568831SAndroid Build Coastguard Worker         if (err->code == XML_ERR_NO_MEMORY)
671*7c568831SAndroid Build Coastguard Worker             return;
672*7c568831SAndroid Build Coastguard Worker 
673*7c568831SAndroid Build Coastguard Worker         /* cleanup current last error */
674*7c568831SAndroid Build Coastguard Worker         xmlResetError(err);
675*7c568831SAndroid Build Coastguard Worker 
676*7c568831SAndroid Build Coastguard Worker         err->domain = XML_FROM_XPATH;
677*7c568831SAndroid Build Coastguard Worker         err->code = code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK;
678*7c568831SAndroid Build Coastguard Worker         err->level = XML_ERR_ERROR;
679*7c568831SAndroid Build Coastguard Worker         if (ctxt->base != NULL) {
680*7c568831SAndroid Build Coastguard Worker             err->str1 = (char *) xmlStrdup(ctxt->base);
681*7c568831SAndroid Build Coastguard Worker             if (err->str1 == NULL) {
682*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
683*7c568831SAndroid Build Coastguard Worker                 return;
684*7c568831SAndroid Build Coastguard Worker             }
685*7c568831SAndroid Build Coastguard Worker         }
686*7c568831SAndroid Build Coastguard Worker         err->int1 = ctxt->cur - ctxt->base;
687*7c568831SAndroid Build Coastguard Worker         err->node = ctxt->context->debugNode;
688*7c568831SAndroid Build Coastguard Worker 
689*7c568831SAndroid Build Coastguard Worker         schannel = ctxt->context->error;
690*7c568831SAndroid Build Coastguard Worker         data = ctxt->context->userData;
691*7c568831SAndroid Build Coastguard Worker         node = ctxt->context->debugNode;
692*7c568831SAndroid Build Coastguard Worker     }
693*7c568831SAndroid Build Coastguard Worker 
694*7c568831SAndroid Build Coastguard Worker     if (schannel == NULL) {
695*7c568831SAndroid Build Coastguard Worker         channel = xmlGenericError;
696*7c568831SAndroid Build Coastguard Worker         data = xmlGenericErrorContext;
697*7c568831SAndroid Build Coastguard Worker     }
698*7c568831SAndroid Build Coastguard Worker 
699*7c568831SAndroid Build Coastguard Worker     res = xmlRaiseError(schannel, channel, data, NULL, node, XML_FROM_XPATH,
700*7c568831SAndroid Build Coastguard Worker                         code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
701*7c568831SAndroid Build Coastguard Worker                         XML_ERR_ERROR, NULL, 0,
702*7c568831SAndroid Build Coastguard Worker                         (const char *) ctxt->base, NULL, NULL,
703*7c568831SAndroid Build Coastguard Worker                         ctxt->cur - ctxt->base, 0,
704*7c568831SAndroid Build Coastguard Worker                         "%s", xmlXPathErrorMessages[code]);
705*7c568831SAndroid Build Coastguard Worker     if (res < 0)
706*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
707*7c568831SAndroid Build Coastguard Worker }
708*7c568831SAndroid Build Coastguard Worker 
709*7c568831SAndroid Build Coastguard Worker /**
710*7c568831SAndroid Build Coastguard Worker  * xmlXPatherror:
711*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
712*7c568831SAndroid Build Coastguard Worker  * @file:  the file name
713*7c568831SAndroid Build Coastguard Worker  * @line:  the line number
714*7c568831SAndroid Build Coastguard Worker  * @no:  the error number
715*7c568831SAndroid Build Coastguard Worker  *
716*7c568831SAndroid Build Coastguard Worker  * Formats an error message.
717*7c568831SAndroid Build Coastguard Worker  */
718*7c568831SAndroid Build Coastguard Worker void
xmlXPatherror(xmlXPathParserContextPtr ctxt,const char * file ATTRIBUTE_UNUSED,int line ATTRIBUTE_UNUSED,int no)719*7c568831SAndroid Build Coastguard Worker xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED,
720*7c568831SAndroid Build Coastguard Worker               int line ATTRIBUTE_UNUSED, int no) {
721*7c568831SAndroid Build Coastguard Worker     xmlXPathErr(ctxt, no);
722*7c568831SAndroid Build Coastguard Worker }
723*7c568831SAndroid Build Coastguard Worker 
724*7c568831SAndroid Build Coastguard Worker /**
725*7c568831SAndroid Build Coastguard Worker  * xmlXPathCheckOpLimit:
726*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
727*7c568831SAndroid Build Coastguard Worker  * @opCount:  the number of operations to be added
728*7c568831SAndroid Build Coastguard Worker  *
729*7c568831SAndroid Build Coastguard Worker  * Adds opCount to the running total of operations and returns -1 if the
730*7c568831SAndroid Build Coastguard Worker  * operation limit is exceeded. Returns 0 otherwise.
731*7c568831SAndroid Build Coastguard Worker  */
732*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCheckOpLimit(xmlXPathParserContextPtr ctxt,unsigned long opCount)733*7c568831SAndroid Build Coastguard Worker xmlXPathCheckOpLimit(xmlXPathParserContextPtr ctxt, unsigned long opCount) {
734*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr xpctxt = ctxt->context;
735*7c568831SAndroid Build Coastguard Worker 
736*7c568831SAndroid Build Coastguard Worker     if ((opCount > xpctxt->opLimit) ||
737*7c568831SAndroid Build Coastguard Worker         (xpctxt->opCount > xpctxt->opLimit - opCount)) {
738*7c568831SAndroid Build Coastguard Worker         xpctxt->opCount = xpctxt->opLimit;
739*7c568831SAndroid Build Coastguard Worker         xmlXPathErr(ctxt, XPATH_OP_LIMIT_EXCEEDED);
740*7c568831SAndroid Build Coastguard Worker         return(-1);
741*7c568831SAndroid Build Coastguard Worker     }
742*7c568831SAndroid Build Coastguard Worker 
743*7c568831SAndroid Build Coastguard Worker     xpctxt->opCount += opCount;
744*7c568831SAndroid Build Coastguard Worker     return(0);
745*7c568831SAndroid Build Coastguard Worker }
746*7c568831SAndroid Build Coastguard Worker 
747*7c568831SAndroid Build Coastguard Worker #define OP_LIMIT_EXCEEDED(ctxt, n) \
748*7c568831SAndroid Build Coastguard Worker     ((ctxt->context->opLimit != 0) && (xmlXPathCheckOpLimit(ctxt, n) < 0))
749*7c568831SAndroid Build Coastguard Worker 
750*7c568831SAndroid Build Coastguard Worker /************************************************************************
751*7c568831SAndroid Build Coastguard Worker  *									*
752*7c568831SAndroid Build Coastguard Worker  *			Parser Types					*
753*7c568831SAndroid Build Coastguard Worker  *									*
754*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
755*7c568831SAndroid Build Coastguard Worker 
756*7c568831SAndroid Build Coastguard Worker /*
757*7c568831SAndroid Build Coastguard Worker  * Types are private:
758*7c568831SAndroid Build Coastguard Worker  */
759*7c568831SAndroid Build Coastguard Worker 
760*7c568831SAndroid Build Coastguard Worker typedef enum {
761*7c568831SAndroid Build Coastguard Worker     XPATH_OP_END=0,
762*7c568831SAndroid Build Coastguard Worker     XPATH_OP_AND,
763*7c568831SAndroid Build Coastguard Worker     XPATH_OP_OR,
764*7c568831SAndroid Build Coastguard Worker     XPATH_OP_EQUAL,
765*7c568831SAndroid Build Coastguard Worker     XPATH_OP_CMP,
766*7c568831SAndroid Build Coastguard Worker     XPATH_OP_PLUS,
767*7c568831SAndroid Build Coastguard Worker     XPATH_OP_MULT,
768*7c568831SAndroid Build Coastguard Worker     XPATH_OP_UNION,
769*7c568831SAndroid Build Coastguard Worker     XPATH_OP_ROOT,
770*7c568831SAndroid Build Coastguard Worker     XPATH_OP_NODE,
771*7c568831SAndroid Build Coastguard Worker     XPATH_OP_COLLECT,
772*7c568831SAndroid Build Coastguard Worker     XPATH_OP_VALUE, /* 11 */
773*7c568831SAndroid Build Coastguard Worker     XPATH_OP_VARIABLE,
774*7c568831SAndroid Build Coastguard Worker     XPATH_OP_FUNCTION,
775*7c568831SAndroid Build Coastguard Worker     XPATH_OP_ARG,
776*7c568831SAndroid Build Coastguard Worker     XPATH_OP_PREDICATE,
777*7c568831SAndroid Build Coastguard Worker     XPATH_OP_FILTER, /* 16 */
778*7c568831SAndroid Build Coastguard Worker     XPATH_OP_SORT /* 17 */
779*7c568831SAndroid Build Coastguard Worker } xmlXPathOp;
780*7c568831SAndroid Build Coastguard Worker 
781*7c568831SAndroid Build Coastguard Worker typedef enum {
782*7c568831SAndroid Build Coastguard Worker     AXIS_ANCESTOR = 1,
783*7c568831SAndroid Build Coastguard Worker     AXIS_ANCESTOR_OR_SELF,
784*7c568831SAndroid Build Coastguard Worker     AXIS_ATTRIBUTE,
785*7c568831SAndroid Build Coastguard Worker     AXIS_CHILD,
786*7c568831SAndroid Build Coastguard Worker     AXIS_DESCENDANT,
787*7c568831SAndroid Build Coastguard Worker     AXIS_DESCENDANT_OR_SELF,
788*7c568831SAndroid Build Coastguard Worker     AXIS_FOLLOWING,
789*7c568831SAndroid Build Coastguard Worker     AXIS_FOLLOWING_SIBLING,
790*7c568831SAndroid Build Coastguard Worker     AXIS_NAMESPACE,
791*7c568831SAndroid Build Coastguard Worker     AXIS_PARENT,
792*7c568831SAndroid Build Coastguard Worker     AXIS_PRECEDING,
793*7c568831SAndroid Build Coastguard Worker     AXIS_PRECEDING_SIBLING,
794*7c568831SAndroid Build Coastguard Worker     AXIS_SELF
795*7c568831SAndroid Build Coastguard Worker } xmlXPathAxisVal;
796*7c568831SAndroid Build Coastguard Worker 
797*7c568831SAndroid Build Coastguard Worker typedef enum {
798*7c568831SAndroid Build Coastguard Worker     NODE_TEST_NONE = 0,
799*7c568831SAndroid Build Coastguard Worker     NODE_TEST_TYPE = 1,
800*7c568831SAndroid Build Coastguard Worker     NODE_TEST_PI = 2,
801*7c568831SAndroid Build Coastguard Worker     NODE_TEST_ALL = 3,
802*7c568831SAndroid Build Coastguard Worker     NODE_TEST_NS = 4,
803*7c568831SAndroid Build Coastguard Worker     NODE_TEST_NAME = 5
804*7c568831SAndroid Build Coastguard Worker } xmlXPathTestVal;
805*7c568831SAndroid Build Coastguard Worker 
806*7c568831SAndroid Build Coastguard Worker typedef enum {
807*7c568831SAndroid Build Coastguard Worker     NODE_TYPE_NODE = 0,
808*7c568831SAndroid Build Coastguard Worker     NODE_TYPE_COMMENT = XML_COMMENT_NODE,
809*7c568831SAndroid Build Coastguard Worker     NODE_TYPE_TEXT = XML_TEXT_NODE,
810*7c568831SAndroid Build Coastguard Worker     NODE_TYPE_PI = XML_PI_NODE
811*7c568831SAndroid Build Coastguard Worker } xmlXPathTypeVal;
812*7c568831SAndroid Build Coastguard Worker 
813*7c568831SAndroid Build Coastguard Worker typedef struct _xmlXPathStepOp xmlXPathStepOp;
814*7c568831SAndroid Build Coastguard Worker typedef xmlXPathStepOp *xmlXPathStepOpPtr;
815*7c568831SAndroid Build Coastguard Worker struct _xmlXPathStepOp {
816*7c568831SAndroid Build Coastguard Worker     xmlXPathOp op;		/* The identifier of the operation */
817*7c568831SAndroid Build Coastguard Worker     int ch1;			/* First child */
818*7c568831SAndroid Build Coastguard Worker     int ch2;			/* Second child */
819*7c568831SAndroid Build Coastguard Worker     int value;
820*7c568831SAndroid Build Coastguard Worker     int value2;
821*7c568831SAndroid Build Coastguard Worker     int value3;
822*7c568831SAndroid Build Coastguard Worker     void *value4;
823*7c568831SAndroid Build Coastguard Worker     void *value5;
824*7c568831SAndroid Build Coastguard Worker     xmlXPathFunction cache;
825*7c568831SAndroid Build Coastguard Worker     void *cacheURI;
826*7c568831SAndroid Build Coastguard Worker };
827*7c568831SAndroid Build Coastguard Worker 
828*7c568831SAndroid Build Coastguard Worker struct _xmlXPathCompExpr {
829*7c568831SAndroid Build Coastguard Worker     int nbStep;			/* Number of steps in this expression */
830*7c568831SAndroid Build Coastguard Worker     int maxStep;		/* Maximum number of steps allocated */
831*7c568831SAndroid Build Coastguard Worker     xmlXPathStepOp *steps;	/* ops for computation of this expression */
832*7c568831SAndroid Build Coastguard Worker     int last;			/* index of last step in expression */
833*7c568831SAndroid Build Coastguard Worker     xmlChar *expr;		/* the expression being computed */
834*7c568831SAndroid Build Coastguard Worker     xmlDictPtr dict;		/* the dictionary to use if any */
835*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
836*7c568831SAndroid Build Coastguard Worker     xmlPatternPtr stream;
837*7c568831SAndroid Build Coastguard Worker #endif
838*7c568831SAndroid Build Coastguard Worker };
839*7c568831SAndroid Build Coastguard Worker 
840*7c568831SAndroid Build Coastguard Worker /************************************************************************
841*7c568831SAndroid Build Coastguard Worker  *									*
842*7c568831SAndroid Build Coastguard Worker  *			Forward declarations				*
843*7c568831SAndroid Build Coastguard Worker  *									*
844*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
845*7c568831SAndroid Build Coastguard Worker 
846*7c568831SAndroid Build Coastguard Worker static void
847*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj);
848*7c568831SAndroid Build Coastguard Worker static int
849*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
850*7c568831SAndroid Build Coastguard Worker                         xmlXPathStepOpPtr op, xmlNodePtr *first);
851*7c568831SAndroid Build Coastguard Worker static int
852*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
853*7c568831SAndroid Build Coastguard Worker 			    xmlXPathStepOpPtr op,
854*7c568831SAndroid Build Coastguard Worker 			    int isPredicate);
855*7c568831SAndroid Build Coastguard Worker static void
856*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObjectEntry(void *obj, const xmlChar *name);
857*7c568831SAndroid Build Coastguard Worker 
858*7c568831SAndroid Build Coastguard Worker /************************************************************************
859*7c568831SAndroid Build Coastguard Worker  *									*
860*7c568831SAndroid Build Coastguard Worker  *			Parser Type functions				*
861*7c568831SAndroid Build Coastguard Worker  *									*
862*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
863*7c568831SAndroid Build Coastguard Worker 
864*7c568831SAndroid Build Coastguard Worker /**
865*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewCompExpr:
866*7c568831SAndroid Build Coastguard Worker  *
867*7c568831SAndroid Build Coastguard Worker  * Create a new Xpath component
868*7c568831SAndroid Build Coastguard Worker  *
869*7c568831SAndroid Build Coastguard Worker  * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error
870*7c568831SAndroid Build Coastguard Worker  */
871*7c568831SAndroid Build Coastguard Worker static xmlXPathCompExprPtr
xmlXPathNewCompExpr(void)872*7c568831SAndroid Build Coastguard Worker xmlXPathNewCompExpr(void) {
873*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr cur;
874*7c568831SAndroid Build Coastguard Worker 
875*7c568831SAndroid Build Coastguard Worker     cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
876*7c568831SAndroid Build Coastguard Worker     if (cur == NULL)
877*7c568831SAndroid Build Coastguard Worker 	return(NULL);
878*7c568831SAndroid Build Coastguard Worker     memset(cur, 0, sizeof(xmlXPathCompExpr));
879*7c568831SAndroid Build Coastguard Worker     cur->maxStep = 10;
880*7c568831SAndroid Build Coastguard Worker     cur->nbStep = 0;
881*7c568831SAndroid Build Coastguard Worker     cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
882*7c568831SAndroid Build Coastguard Worker 	                                   sizeof(xmlXPathStepOp));
883*7c568831SAndroid Build Coastguard Worker     if (cur->steps == NULL) {
884*7c568831SAndroid Build Coastguard Worker 	xmlFree(cur);
885*7c568831SAndroid Build Coastguard Worker 	return(NULL);
886*7c568831SAndroid Build Coastguard Worker     }
887*7c568831SAndroid Build Coastguard Worker     memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
888*7c568831SAndroid Build Coastguard Worker     cur->last = -1;
889*7c568831SAndroid Build Coastguard Worker     return(cur);
890*7c568831SAndroid Build Coastguard Worker }
891*7c568831SAndroid Build Coastguard Worker 
892*7c568831SAndroid Build Coastguard Worker /**
893*7c568831SAndroid Build Coastguard Worker  * xmlXPathFreeCompExpr:
894*7c568831SAndroid Build Coastguard Worker  * @comp:  an XPATH comp
895*7c568831SAndroid Build Coastguard Worker  *
896*7c568831SAndroid Build Coastguard Worker  * Free up the memory allocated by @comp
897*7c568831SAndroid Build Coastguard Worker  */
898*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)899*7c568831SAndroid Build Coastguard Worker xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
900*7c568831SAndroid Build Coastguard Worker {
901*7c568831SAndroid Build Coastguard Worker     xmlXPathStepOpPtr op;
902*7c568831SAndroid Build Coastguard Worker     int i;
903*7c568831SAndroid Build Coastguard Worker 
904*7c568831SAndroid Build Coastguard Worker     if (comp == NULL)
905*7c568831SAndroid Build Coastguard Worker         return;
906*7c568831SAndroid Build Coastguard Worker     if (comp->dict == NULL) {
907*7c568831SAndroid Build Coastguard Worker 	for (i = 0; i < comp->nbStep; i++) {
908*7c568831SAndroid Build Coastguard Worker 	    op = &comp->steps[i];
909*7c568831SAndroid Build Coastguard Worker 	    if (op->value4 != NULL) {
910*7c568831SAndroid Build Coastguard Worker 		if (op->op == XPATH_OP_VALUE)
911*7c568831SAndroid Build Coastguard Worker 		    xmlXPathFreeObject(op->value4);
912*7c568831SAndroid Build Coastguard Worker 		else
913*7c568831SAndroid Build Coastguard Worker 		    xmlFree(op->value4);
914*7c568831SAndroid Build Coastguard Worker 	    }
915*7c568831SAndroid Build Coastguard Worker 	    if (op->value5 != NULL)
916*7c568831SAndroid Build Coastguard Worker 		xmlFree(op->value5);
917*7c568831SAndroid Build Coastguard Worker 	}
918*7c568831SAndroid Build Coastguard Worker     } else {
919*7c568831SAndroid Build Coastguard Worker 	for (i = 0; i < comp->nbStep; i++) {
920*7c568831SAndroid Build Coastguard Worker 	    op = &comp->steps[i];
921*7c568831SAndroid Build Coastguard Worker 	    if (op->value4 != NULL) {
922*7c568831SAndroid Build Coastguard Worker 		if (op->op == XPATH_OP_VALUE)
923*7c568831SAndroid Build Coastguard Worker 		    xmlXPathFreeObject(op->value4);
924*7c568831SAndroid Build Coastguard Worker 	    }
925*7c568831SAndroid Build Coastguard Worker 	}
926*7c568831SAndroid Build Coastguard Worker         xmlDictFree(comp->dict);
927*7c568831SAndroid Build Coastguard Worker     }
928*7c568831SAndroid Build Coastguard Worker     if (comp->steps != NULL) {
929*7c568831SAndroid Build Coastguard Worker         xmlFree(comp->steps);
930*7c568831SAndroid Build Coastguard Worker     }
931*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
932*7c568831SAndroid Build Coastguard Worker     if (comp->stream != NULL) {
933*7c568831SAndroid Build Coastguard Worker         xmlFreePatternList(comp->stream);
934*7c568831SAndroid Build Coastguard Worker     }
935*7c568831SAndroid Build Coastguard Worker #endif
936*7c568831SAndroid Build Coastguard Worker     if (comp->expr != NULL) {
937*7c568831SAndroid Build Coastguard Worker         xmlFree(comp->expr);
938*7c568831SAndroid Build Coastguard Worker     }
939*7c568831SAndroid Build Coastguard Worker 
940*7c568831SAndroid Build Coastguard Worker     xmlFree(comp);
941*7c568831SAndroid Build Coastguard Worker }
942*7c568831SAndroid Build Coastguard Worker 
943*7c568831SAndroid Build Coastguard Worker /**
944*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompExprAdd:
945*7c568831SAndroid Build Coastguard Worker  * @comp:  the compiled expression
946*7c568831SAndroid Build Coastguard Worker  * @ch1: first child index
947*7c568831SAndroid Build Coastguard Worker  * @ch2: second child index
948*7c568831SAndroid Build Coastguard Worker  * @op:  an op
949*7c568831SAndroid Build Coastguard Worker  * @value:  the first int value
950*7c568831SAndroid Build Coastguard Worker  * @value2:  the second int value
951*7c568831SAndroid Build Coastguard Worker  * @value3:  the third int value
952*7c568831SAndroid Build Coastguard Worker  * @value4:  the first string value
953*7c568831SAndroid Build Coastguard Worker  * @value5:  the second string value
954*7c568831SAndroid Build Coastguard Worker  *
955*7c568831SAndroid Build Coastguard Worker  * Add a step to an XPath Compiled Expression
956*7c568831SAndroid Build Coastguard Worker  *
957*7c568831SAndroid Build Coastguard Worker  * Returns -1 in case of failure, the index otherwise
958*7c568831SAndroid Build Coastguard Worker  */
959*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt,int ch1,int ch2,xmlXPathOp op,int value,int value2,int value3,void * value4,void * value5)960*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt, int ch1, int ch2,
961*7c568831SAndroid Build Coastguard Worker    xmlXPathOp op, int value,
962*7c568831SAndroid Build Coastguard Worker    int value2, int value3, void *value4, void *value5) {
963*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp = ctxt->comp;
964*7c568831SAndroid Build Coastguard Worker     if (comp->nbStep >= comp->maxStep) {
965*7c568831SAndroid Build Coastguard Worker 	xmlXPathStepOp *real;
966*7c568831SAndroid Build Coastguard Worker 
967*7c568831SAndroid Build Coastguard Worker         if (comp->maxStep >= XPATH_MAX_STEPS) {
968*7c568831SAndroid Build Coastguard Worker 	    xmlXPathPErrMemory(ctxt);
969*7c568831SAndroid Build Coastguard Worker 	    return(-1);
970*7c568831SAndroid Build Coastguard Worker         }
971*7c568831SAndroid Build Coastguard Worker 	comp->maxStep *= 2;
972*7c568831SAndroid Build Coastguard Worker 	real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
973*7c568831SAndroid Build Coastguard Worker 		                      comp->maxStep * sizeof(xmlXPathStepOp));
974*7c568831SAndroid Build Coastguard Worker 	if (real == NULL) {
975*7c568831SAndroid Build Coastguard Worker 	    comp->maxStep /= 2;
976*7c568831SAndroid Build Coastguard Worker 	    xmlXPathPErrMemory(ctxt);
977*7c568831SAndroid Build Coastguard Worker 	    return(-1);
978*7c568831SAndroid Build Coastguard Worker 	}
979*7c568831SAndroid Build Coastguard Worker 	comp->steps = real;
980*7c568831SAndroid Build Coastguard Worker     }
981*7c568831SAndroid Build Coastguard Worker     comp->last = comp->nbStep;
982*7c568831SAndroid Build Coastguard Worker     comp->steps[comp->nbStep].ch1 = ch1;
983*7c568831SAndroid Build Coastguard Worker     comp->steps[comp->nbStep].ch2 = ch2;
984*7c568831SAndroid Build Coastguard Worker     comp->steps[comp->nbStep].op = op;
985*7c568831SAndroid Build Coastguard Worker     comp->steps[comp->nbStep].value = value;
986*7c568831SAndroid Build Coastguard Worker     comp->steps[comp->nbStep].value2 = value2;
987*7c568831SAndroid Build Coastguard Worker     comp->steps[comp->nbStep].value3 = value3;
988*7c568831SAndroid Build Coastguard Worker     if ((comp->dict != NULL) &&
989*7c568831SAndroid Build Coastguard Worker         ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) ||
990*7c568831SAndroid Build Coastguard Worker 	 (op == XPATH_OP_COLLECT))) {
991*7c568831SAndroid Build Coastguard Worker         if (value4 != NULL) {
992*7c568831SAndroid Build Coastguard Worker 	    comp->steps[comp->nbStep].value4 = (xmlChar *)
993*7c568831SAndroid Build Coastguard Worker 	        (void *)xmlDictLookup(comp->dict, value4, -1);
994*7c568831SAndroid Build Coastguard Worker 	    xmlFree(value4);
995*7c568831SAndroid Build Coastguard Worker 	} else
996*7c568831SAndroid Build Coastguard Worker 	    comp->steps[comp->nbStep].value4 = NULL;
997*7c568831SAndroid Build Coastguard Worker         if (value5 != NULL) {
998*7c568831SAndroid Build Coastguard Worker 	    comp->steps[comp->nbStep].value5 = (xmlChar *)
999*7c568831SAndroid Build Coastguard Worker 	        (void *)xmlDictLookup(comp->dict, value5, -1);
1000*7c568831SAndroid Build Coastguard Worker 	    xmlFree(value5);
1001*7c568831SAndroid Build Coastguard Worker 	} else
1002*7c568831SAndroid Build Coastguard Worker 	    comp->steps[comp->nbStep].value5 = NULL;
1003*7c568831SAndroid Build Coastguard Worker     } else {
1004*7c568831SAndroid Build Coastguard Worker 	comp->steps[comp->nbStep].value4 = value4;
1005*7c568831SAndroid Build Coastguard Worker 	comp->steps[comp->nbStep].value5 = value5;
1006*7c568831SAndroid Build Coastguard Worker     }
1007*7c568831SAndroid Build Coastguard Worker     comp->steps[comp->nbStep].cache = NULL;
1008*7c568831SAndroid Build Coastguard Worker     return(comp->nbStep++);
1009*7c568831SAndroid Build Coastguard Worker }
1010*7c568831SAndroid Build Coastguard Worker 
1011*7c568831SAndroid Build Coastguard Worker #define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5)	\
1012*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprAdd(ctxt, (op1), (op2),			\
1013*7c568831SAndroid Build Coastguard Worker 	                (op), (val), (val2), (val3), (val4), (val5))
1014*7c568831SAndroid Build Coastguard Worker #define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5)			\
1015*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprAdd(ctxt, ctxt->comp->last, -1,		\
1016*7c568831SAndroid Build Coastguard Worker 	                (op), (val), (val2), (val3), (val4), (val5))
1017*7c568831SAndroid Build Coastguard Worker 
1018*7c568831SAndroid Build Coastguard Worker #define PUSH_LEAVE_EXPR(op, val, val2)					\
1019*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
1020*7c568831SAndroid Build Coastguard Worker 
1021*7c568831SAndroid Build Coastguard Worker #define PUSH_UNARY_EXPR(op, ch, val, val2)				\
1022*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
1023*7c568831SAndroid Build Coastguard Worker 
1024*7c568831SAndroid Build Coastguard Worker #define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2)			\
1025*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, (ch1), (ch2), (op),			\
1026*7c568831SAndroid Build Coastguard Worker 			(val), (val2), 0 ,NULL ,NULL)
1027*7c568831SAndroid Build Coastguard Worker 
1028*7c568831SAndroid Build Coastguard Worker /************************************************************************
1029*7c568831SAndroid Build Coastguard Worker  *									*
1030*7c568831SAndroid Build Coastguard Worker  *		XPath object cache structures				*
1031*7c568831SAndroid Build Coastguard Worker  *									*
1032*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
1033*7c568831SAndroid Build Coastguard Worker 
1034*7c568831SAndroid Build Coastguard Worker /* #define XP_DEFAULT_CACHE_ON */
1035*7c568831SAndroid Build Coastguard Worker 
1036*7c568831SAndroid Build Coastguard Worker typedef struct _xmlXPathContextCache xmlXPathContextCache;
1037*7c568831SAndroid Build Coastguard Worker typedef xmlXPathContextCache *xmlXPathContextCachePtr;
1038*7c568831SAndroid Build Coastguard Worker struct _xmlXPathContextCache {
1039*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr nodesetObjs;  /* stringval points to next */
1040*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr miscObjs;     /* stringval points to next */
1041*7c568831SAndroid Build Coastguard Worker     int numNodeset;
1042*7c568831SAndroid Build Coastguard Worker     int maxNodeset;
1043*7c568831SAndroid Build Coastguard Worker     int numMisc;
1044*7c568831SAndroid Build Coastguard Worker     int maxMisc;
1045*7c568831SAndroid Build Coastguard Worker };
1046*7c568831SAndroid Build Coastguard Worker 
1047*7c568831SAndroid Build Coastguard Worker /************************************************************************
1048*7c568831SAndroid Build Coastguard Worker  *									*
1049*7c568831SAndroid Build Coastguard Worker  *		Debugging related functions				*
1050*7c568831SAndroid Build Coastguard Worker  *									*
1051*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
1052*7c568831SAndroid Build Coastguard Worker 
1053*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_DEBUG_ENABLED
1054*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNode(FILE * output,xmlNodePtr cur,int depth)1055*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
1056*7c568831SAndroid Build Coastguard Worker     int i;
1057*7c568831SAndroid Build Coastguard Worker     char shift[100];
1058*7c568831SAndroid Build Coastguard Worker 
1059*7c568831SAndroid Build Coastguard Worker     for (i = 0;((i < depth) && (i < 25));i++)
1060*7c568831SAndroid Build Coastguard Worker         shift[2 * i] = shift[2 * i + 1] = ' ';
1061*7c568831SAndroid Build Coastguard Worker     shift[2 * i] = shift[2 * i + 1] = 0;
1062*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
1063*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "%s", shift);
1064*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "Node is NULL !\n");
1065*7c568831SAndroid Build Coastguard Worker 	return;
1066*7c568831SAndroid Build Coastguard Worker 
1067*7c568831SAndroid Build Coastguard Worker     }
1068*7c568831SAndroid Build Coastguard Worker 
1069*7c568831SAndroid Build Coastguard Worker     if ((cur->type == XML_DOCUMENT_NODE) ||
1070*7c568831SAndroid Build Coastguard Worker 	     (cur->type == XML_HTML_DOCUMENT_NODE)) {
1071*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "%s", shift);
1072*7c568831SAndroid Build Coastguard Worker 	fprintf(output, " /\n");
1073*7c568831SAndroid Build Coastguard Worker     } else if (cur->type == XML_ATTRIBUTE_NODE)
1074*7c568831SAndroid Build Coastguard Worker 	xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
1075*7c568831SAndroid Build Coastguard Worker     else
1076*7c568831SAndroid Build Coastguard Worker 	xmlDebugDumpOneNode(output, cur, depth);
1077*7c568831SAndroid Build Coastguard Worker }
1078*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNodeList(FILE * output,xmlNodePtr cur,int depth)1079*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) {
1080*7c568831SAndroid Build Coastguard Worker     xmlNodePtr tmp;
1081*7c568831SAndroid Build Coastguard Worker     int i;
1082*7c568831SAndroid Build Coastguard Worker     char shift[100];
1083*7c568831SAndroid Build Coastguard Worker 
1084*7c568831SAndroid Build Coastguard Worker     for (i = 0;((i < depth) && (i < 25));i++)
1085*7c568831SAndroid Build Coastguard Worker         shift[2 * i] = shift[2 * i + 1] = ' ';
1086*7c568831SAndroid Build Coastguard Worker     shift[2 * i] = shift[2 * i + 1] = 0;
1087*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
1088*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "%s", shift);
1089*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "Node is NULL !\n");
1090*7c568831SAndroid Build Coastguard Worker 	return;
1091*7c568831SAndroid Build Coastguard Worker 
1092*7c568831SAndroid Build Coastguard Worker     }
1093*7c568831SAndroid Build Coastguard Worker 
1094*7c568831SAndroid Build Coastguard Worker     while (cur != NULL) {
1095*7c568831SAndroid Build Coastguard Worker 	tmp = cur;
1096*7c568831SAndroid Build Coastguard Worker 	cur = cur->next;
1097*7c568831SAndroid Build Coastguard Worker 	xmlDebugDumpOneNode(output, tmp, depth);
1098*7c568831SAndroid Build Coastguard Worker     }
1099*7c568831SAndroid Build Coastguard Worker }
1100*7c568831SAndroid Build Coastguard Worker 
1101*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNodeSet(FILE * output,xmlNodeSetPtr cur,int depth)1102*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
1103*7c568831SAndroid Build Coastguard Worker     int i;
1104*7c568831SAndroid Build Coastguard Worker     char shift[100];
1105*7c568831SAndroid Build Coastguard Worker 
1106*7c568831SAndroid Build Coastguard Worker     for (i = 0;((i < depth) && (i < 25));i++)
1107*7c568831SAndroid Build Coastguard Worker         shift[2 * i] = shift[2 * i + 1] = ' ';
1108*7c568831SAndroid Build Coastguard Worker     shift[2 * i] = shift[2 * i + 1] = 0;
1109*7c568831SAndroid Build Coastguard Worker 
1110*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
1111*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "%s", shift);
1112*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "NodeSet is NULL !\n");
1113*7c568831SAndroid Build Coastguard Worker 	return;
1114*7c568831SAndroid Build Coastguard Worker 
1115*7c568831SAndroid Build Coastguard Worker     }
1116*7c568831SAndroid Build Coastguard Worker 
1117*7c568831SAndroid Build Coastguard Worker     if (cur != NULL) {
1118*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
1119*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < cur->nodeNr;i++) {
1120*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "%s", shift);
1121*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "%d", i + 1);
1122*7c568831SAndroid Build Coastguard Worker 	    xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
1123*7c568831SAndroid Build Coastguard Worker 	}
1124*7c568831SAndroid Build Coastguard Worker     }
1125*7c568831SAndroid Build Coastguard Worker }
1126*7c568831SAndroid Build Coastguard Worker 
1127*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpValueTree(FILE * output,xmlNodeSetPtr cur,int depth)1128*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) {
1129*7c568831SAndroid Build Coastguard Worker     int i;
1130*7c568831SAndroid Build Coastguard Worker     char shift[100];
1131*7c568831SAndroid Build Coastguard Worker 
1132*7c568831SAndroid Build Coastguard Worker     for (i = 0;((i < depth) && (i < 25));i++)
1133*7c568831SAndroid Build Coastguard Worker         shift[2 * i] = shift[2 * i + 1] = ' ';
1134*7c568831SAndroid Build Coastguard Worker     shift[2 * i] = shift[2 * i + 1] = 0;
1135*7c568831SAndroid Build Coastguard Worker 
1136*7c568831SAndroid Build Coastguard Worker     if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) {
1137*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "%s", shift);
1138*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "Value Tree is NULL !\n");
1139*7c568831SAndroid Build Coastguard Worker 	return;
1140*7c568831SAndroid Build Coastguard Worker 
1141*7c568831SAndroid Build Coastguard Worker     }
1142*7c568831SAndroid Build Coastguard Worker 
1143*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%s", shift);
1144*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%d", i + 1);
1145*7c568831SAndroid Build Coastguard Worker     xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);
1146*7c568831SAndroid Build Coastguard Worker }
1147*7c568831SAndroid Build Coastguard Worker 
1148*7c568831SAndroid Build Coastguard Worker /**
1149*7c568831SAndroid Build Coastguard Worker  * xmlXPathDebugDumpObject:
1150*7c568831SAndroid Build Coastguard Worker  * @output:  the FILE * to dump the output
1151*7c568831SAndroid Build Coastguard Worker  * @cur:  the object to inspect
1152*7c568831SAndroid Build Coastguard Worker  * @depth:  indentation level
1153*7c568831SAndroid Build Coastguard Worker  *
1154*7c568831SAndroid Build Coastguard Worker  * Dump the content of the object for debugging purposes
1155*7c568831SAndroid Build Coastguard Worker  */
1156*7c568831SAndroid Build Coastguard Worker void
xmlXPathDebugDumpObject(FILE * output,xmlXPathObjectPtr cur,int depth)1157*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
1158*7c568831SAndroid Build Coastguard Worker     int i;
1159*7c568831SAndroid Build Coastguard Worker     char shift[100];
1160*7c568831SAndroid Build Coastguard Worker 
1161*7c568831SAndroid Build Coastguard Worker     if (output == NULL) return;
1162*7c568831SAndroid Build Coastguard Worker 
1163*7c568831SAndroid Build Coastguard Worker     for (i = 0;((i < depth) && (i < 25));i++)
1164*7c568831SAndroid Build Coastguard Worker         shift[2 * i] = shift[2 * i + 1] = ' ';
1165*7c568831SAndroid Build Coastguard Worker     shift[2 * i] = shift[2 * i + 1] = 0;
1166*7c568831SAndroid Build Coastguard Worker 
1167*7c568831SAndroid Build Coastguard Worker 
1168*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%s", shift);
1169*7c568831SAndroid Build Coastguard Worker 
1170*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
1171*7c568831SAndroid Build Coastguard Worker         fprintf(output, "Object is empty (NULL)\n");
1172*7c568831SAndroid Build Coastguard Worker 	return;
1173*7c568831SAndroid Build Coastguard Worker     }
1174*7c568831SAndroid Build Coastguard Worker     switch(cur->type) {
1175*7c568831SAndroid Build Coastguard Worker         case XPATH_UNDEFINED:
1176*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "Object is uninitialized\n");
1177*7c568831SAndroid Build Coastguard Worker 	    break;
1178*7c568831SAndroid Build Coastguard Worker         case XPATH_NODESET:
1179*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "Object is a Node Set :\n");
1180*7c568831SAndroid Build Coastguard Worker 	    xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
1181*7c568831SAndroid Build Coastguard Worker 	    break;
1182*7c568831SAndroid Build Coastguard Worker 	case XPATH_XSLT_TREE:
1183*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "Object is an XSLT value tree :\n");
1184*7c568831SAndroid Build Coastguard Worker 	    xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth);
1185*7c568831SAndroid Build Coastguard Worker 	    break;
1186*7c568831SAndroid Build Coastguard Worker         case XPATH_BOOLEAN:
1187*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "Object is a Boolean : ");
1188*7c568831SAndroid Build Coastguard Worker 	    if (cur->boolval) fprintf(output, "true\n");
1189*7c568831SAndroid Build Coastguard Worker 	    else fprintf(output, "false\n");
1190*7c568831SAndroid Build Coastguard Worker 	    break;
1191*7c568831SAndroid Build Coastguard Worker         case XPATH_NUMBER:
1192*7c568831SAndroid Build Coastguard Worker 	    switch (xmlXPathIsInf(cur->floatval)) {
1193*7c568831SAndroid Build Coastguard Worker 	    case 1:
1194*7c568831SAndroid Build Coastguard Worker 		fprintf(output, "Object is a number : Infinity\n");
1195*7c568831SAndroid Build Coastguard Worker 		break;
1196*7c568831SAndroid Build Coastguard Worker 	    case -1:
1197*7c568831SAndroid Build Coastguard Worker 		fprintf(output, "Object is a number : -Infinity\n");
1198*7c568831SAndroid Build Coastguard Worker 		break;
1199*7c568831SAndroid Build Coastguard Worker 	    default:
1200*7c568831SAndroid Build Coastguard Worker 		if (xmlXPathIsNaN(cur->floatval)) {
1201*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "Object is a number : NaN\n");
1202*7c568831SAndroid Build Coastguard Worker 		} else if (cur->floatval == 0) {
1203*7c568831SAndroid Build Coastguard Worker                     /* Omit sign for negative zero. */
1204*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "Object is a number : 0\n");
1205*7c568831SAndroid Build Coastguard Worker 		} else {
1206*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "Object is a number : %0g\n", cur->floatval);
1207*7c568831SAndroid Build Coastguard Worker 		}
1208*7c568831SAndroid Build Coastguard Worker 	    }
1209*7c568831SAndroid Build Coastguard Worker 	    break;
1210*7c568831SAndroid Build Coastguard Worker         case XPATH_STRING:
1211*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "Object is a string : ");
1212*7c568831SAndroid Build Coastguard Worker 	    xmlDebugDumpString(output, cur->stringval);
1213*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "\n");
1214*7c568831SAndroid Build Coastguard Worker 	    break;
1215*7c568831SAndroid Build Coastguard Worker 	case XPATH_USERS:
1216*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "Object is user defined\n");
1217*7c568831SAndroid Build Coastguard Worker 	    break;
1218*7c568831SAndroid Build Coastguard Worker     }
1219*7c568831SAndroid Build Coastguard Worker }
1220*7c568831SAndroid Build Coastguard Worker 
1221*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpStepOp(FILE * output,xmlXPathCompExprPtr comp,xmlXPathStepOpPtr op,int depth)1222*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
1223*7c568831SAndroid Build Coastguard Worker 	                     xmlXPathStepOpPtr op, int depth) {
1224*7c568831SAndroid Build Coastguard Worker     int i;
1225*7c568831SAndroid Build Coastguard Worker     char shift[100];
1226*7c568831SAndroid Build Coastguard Worker 
1227*7c568831SAndroid Build Coastguard Worker     for (i = 0;((i < depth) && (i < 25));i++)
1228*7c568831SAndroid Build Coastguard Worker         shift[2 * i] = shift[2 * i + 1] = ' ';
1229*7c568831SAndroid Build Coastguard Worker     shift[2 * i] = shift[2 * i + 1] = 0;
1230*7c568831SAndroid Build Coastguard Worker 
1231*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%s", shift);
1232*7c568831SAndroid Build Coastguard Worker     if (op == NULL) {
1233*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "Step is NULL\n");
1234*7c568831SAndroid Build Coastguard Worker 	return;
1235*7c568831SAndroid Build Coastguard Worker     }
1236*7c568831SAndroid Build Coastguard Worker     switch (op->op) {
1237*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_END:
1238*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "END"); break;
1239*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_AND:
1240*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "AND"); break;
1241*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_OR:
1242*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "OR"); break;
1243*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_EQUAL:
1244*7c568831SAndroid Build Coastguard Worker 	     if (op->value)
1245*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "EQUAL =");
1246*7c568831SAndroid Build Coastguard Worker 	     else
1247*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "EQUAL !=");
1248*7c568831SAndroid Build Coastguard Worker 	     break;
1249*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_CMP:
1250*7c568831SAndroid Build Coastguard Worker 	     if (op->value)
1251*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "CMP <");
1252*7c568831SAndroid Build Coastguard Worker 	     else
1253*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "CMP >");
1254*7c568831SAndroid Build Coastguard Worker 	     if (!op->value2)
1255*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "=");
1256*7c568831SAndroid Build Coastguard Worker 	     break;
1257*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_PLUS:
1258*7c568831SAndroid Build Coastguard Worker 	     if (op->value == 0)
1259*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "PLUS -");
1260*7c568831SAndroid Build Coastguard Worker 	     else if (op->value == 1)
1261*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "PLUS +");
1262*7c568831SAndroid Build Coastguard Worker 	     else if (op->value == 2)
1263*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "PLUS unary -");
1264*7c568831SAndroid Build Coastguard Worker 	     else if (op->value == 3)
1265*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "PLUS unary - -");
1266*7c568831SAndroid Build Coastguard Worker 	     break;
1267*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_MULT:
1268*7c568831SAndroid Build Coastguard Worker 	     if (op->value == 0)
1269*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "MULT *");
1270*7c568831SAndroid Build Coastguard Worker 	     else if (op->value == 1)
1271*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "MULT div");
1272*7c568831SAndroid Build Coastguard Worker 	     else
1273*7c568831SAndroid Build Coastguard Worker 		 fprintf(output, "MULT mod");
1274*7c568831SAndroid Build Coastguard Worker 	     break;
1275*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_UNION:
1276*7c568831SAndroid Build Coastguard Worker 	     fprintf(output, "UNION"); break;
1277*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_ROOT:
1278*7c568831SAndroid Build Coastguard Worker 	     fprintf(output, "ROOT"); break;
1279*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_NODE:
1280*7c568831SAndroid Build Coastguard Worker 	     fprintf(output, "NODE"); break;
1281*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_SORT:
1282*7c568831SAndroid Build Coastguard Worker 	     fprintf(output, "SORT"); break;
1283*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_COLLECT: {
1284*7c568831SAndroid Build Coastguard Worker 	    xmlXPathAxisVal axis = (xmlXPathAxisVal)op->value;
1285*7c568831SAndroid Build Coastguard Worker 	    xmlXPathTestVal test = (xmlXPathTestVal)op->value2;
1286*7c568831SAndroid Build Coastguard Worker 	    xmlXPathTypeVal type = (xmlXPathTypeVal)op->value3;
1287*7c568831SAndroid Build Coastguard Worker 	    const xmlChar *prefix = op->value4;
1288*7c568831SAndroid Build Coastguard Worker 	    const xmlChar *name = op->value5;
1289*7c568831SAndroid Build Coastguard Worker 
1290*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "COLLECT ");
1291*7c568831SAndroid Build Coastguard Worker 	    switch (axis) {
1292*7c568831SAndroid Build Coastguard Worker 		case AXIS_ANCESTOR:
1293*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'ancestors' "); break;
1294*7c568831SAndroid Build Coastguard Worker 		case AXIS_ANCESTOR_OR_SELF:
1295*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'ancestors-or-self' "); break;
1296*7c568831SAndroid Build Coastguard Worker 		case AXIS_ATTRIBUTE:
1297*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'attributes' "); break;
1298*7c568831SAndroid Build Coastguard Worker 		case AXIS_CHILD:
1299*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'child' "); break;
1300*7c568831SAndroid Build Coastguard Worker 		case AXIS_DESCENDANT:
1301*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'descendant' "); break;
1302*7c568831SAndroid Build Coastguard Worker 		case AXIS_DESCENDANT_OR_SELF:
1303*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'descendant-or-self' "); break;
1304*7c568831SAndroid Build Coastguard Worker 		case AXIS_FOLLOWING:
1305*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'following' "); break;
1306*7c568831SAndroid Build Coastguard Worker 		case AXIS_FOLLOWING_SIBLING:
1307*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'following-siblings' "); break;
1308*7c568831SAndroid Build Coastguard Worker 		case AXIS_NAMESPACE:
1309*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'namespace' "); break;
1310*7c568831SAndroid Build Coastguard Worker 		case AXIS_PARENT:
1311*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'parent' "); break;
1312*7c568831SAndroid Build Coastguard Worker 		case AXIS_PRECEDING:
1313*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'preceding' "); break;
1314*7c568831SAndroid Build Coastguard Worker 		case AXIS_PRECEDING_SIBLING:
1315*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'preceding-sibling' "); break;
1316*7c568831SAndroid Build Coastguard Worker 		case AXIS_SELF:
1317*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, " 'self' "); break;
1318*7c568831SAndroid Build Coastguard Worker 	    }
1319*7c568831SAndroid Build Coastguard Worker 	    switch (test) {
1320*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_NONE:
1321*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'none' "); break;
1322*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_TYPE:
1323*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'type' "); break;
1324*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_PI:
1325*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'PI' "); break;
1326*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_ALL:
1327*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'all' "); break;
1328*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_NS:
1329*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'namespace' "); break;
1330*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_NAME:
1331*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'name' "); break;
1332*7c568831SAndroid Build Coastguard Worker 	    }
1333*7c568831SAndroid Build Coastguard Worker 	    switch (type) {
1334*7c568831SAndroid Build Coastguard Worker                 case NODE_TYPE_NODE:
1335*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'node' "); break;
1336*7c568831SAndroid Build Coastguard Worker                 case NODE_TYPE_COMMENT:
1337*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'comment' "); break;
1338*7c568831SAndroid Build Coastguard Worker                 case NODE_TYPE_TEXT:
1339*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'text' "); break;
1340*7c568831SAndroid Build Coastguard Worker                 case NODE_TYPE_PI:
1341*7c568831SAndroid Build Coastguard Worker 		    fprintf(output, "'PI' "); break;
1342*7c568831SAndroid Build Coastguard Worker 	    }
1343*7c568831SAndroid Build Coastguard Worker 	    if (prefix != NULL)
1344*7c568831SAndroid Build Coastguard Worker 		fprintf(output, "%s:", prefix);
1345*7c568831SAndroid Build Coastguard Worker 	    if (name != NULL)
1346*7c568831SAndroid Build Coastguard Worker 		fprintf(output, "%s", (const char *) name);
1347*7c568831SAndroid Build Coastguard Worker 	    break;
1348*7c568831SAndroid Build Coastguard Worker 
1349*7c568831SAndroid Build Coastguard Worker         }
1350*7c568831SAndroid Build Coastguard Worker 	case XPATH_OP_VALUE: {
1351*7c568831SAndroid Build Coastguard Worker 	    xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4;
1352*7c568831SAndroid Build Coastguard Worker 
1353*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "ELEM ");
1354*7c568831SAndroid Build Coastguard Worker 	    xmlXPathDebugDumpObject(output, object, 0);
1355*7c568831SAndroid Build Coastguard Worker 	    goto finish;
1356*7c568831SAndroid Build Coastguard Worker 	}
1357*7c568831SAndroid Build Coastguard Worker 	case XPATH_OP_VARIABLE: {
1358*7c568831SAndroid Build Coastguard Worker 	    const xmlChar *prefix = op->value5;
1359*7c568831SAndroid Build Coastguard Worker 	    const xmlChar *name = op->value4;
1360*7c568831SAndroid Build Coastguard Worker 
1361*7c568831SAndroid Build Coastguard Worker 	    if (prefix != NULL)
1362*7c568831SAndroid Build Coastguard Worker 		fprintf(output, "VARIABLE %s:%s", prefix, name);
1363*7c568831SAndroid Build Coastguard Worker 	    else
1364*7c568831SAndroid Build Coastguard Worker 		fprintf(output, "VARIABLE %s", name);
1365*7c568831SAndroid Build Coastguard Worker 	    break;
1366*7c568831SAndroid Build Coastguard Worker 	}
1367*7c568831SAndroid Build Coastguard Worker 	case XPATH_OP_FUNCTION: {
1368*7c568831SAndroid Build Coastguard Worker 	    int nbargs = op->value;
1369*7c568831SAndroid Build Coastguard Worker 	    const xmlChar *prefix = op->value5;
1370*7c568831SAndroid Build Coastguard Worker 	    const xmlChar *name = op->value4;
1371*7c568831SAndroid Build Coastguard Worker 
1372*7c568831SAndroid Build Coastguard Worker 	    if (prefix != NULL)
1373*7c568831SAndroid Build Coastguard Worker 		fprintf(output, "FUNCTION %s:%s(%d args)",
1374*7c568831SAndroid Build Coastguard Worker 			prefix, name, nbargs);
1375*7c568831SAndroid Build Coastguard Worker 	    else
1376*7c568831SAndroid Build Coastguard Worker 		fprintf(output, "FUNCTION %s(%d args)", name, nbargs);
1377*7c568831SAndroid Build Coastguard Worker 	    break;
1378*7c568831SAndroid Build Coastguard Worker 	}
1379*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_ARG: fprintf(output, "ARG"); break;
1380*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
1381*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
1382*7c568831SAndroid Build Coastguard Worker 	default:
1383*7c568831SAndroid Build Coastguard Worker         fprintf(output, "UNKNOWN %d\n", op->op); return;
1384*7c568831SAndroid Build Coastguard Worker     }
1385*7c568831SAndroid Build Coastguard Worker     fprintf(output, "\n");
1386*7c568831SAndroid Build Coastguard Worker finish:
1387*7c568831SAndroid Build Coastguard Worker     if (op->ch1 >= 0)
1388*7c568831SAndroid Build Coastguard Worker 	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1);
1389*7c568831SAndroid Build Coastguard Worker     if (op->ch2 >= 0)
1390*7c568831SAndroid Build Coastguard Worker 	xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1);
1391*7c568831SAndroid Build Coastguard Worker }
1392*7c568831SAndroid Build Coastguard Worker 
1393*7c568831SAndroid Build Coastguard Worker /**
1394*7c568831SAndroid Build Coastguard Worker  * xmlXPathDebugDumpCompExpr:
1395*7c568831SAndroid Build Coastguard Worker  * @output:  the FILE * for the output
1396*7c568831SAndroid Build Coastguard Worker  * @comp:  the precompiled XPath expression
1397*7c568831SAndroid Build Coastguard Worker  * @depth:  the indentation level.
1398*7c568831SAndroid Build Coastguard Worker  *
1399*7c568831SAndroid Build Coastguard Worker  * Dumps the tree of the compiled XPath expression.
1400*7c568831SAndroid Build Coastguard Worker  */
1401*7c568831SAndroid Build Coastguard Worker void
xmlXPathDebugDumpCompExpr(FILE * output,xmlXPathCompExprPtr comp,int depth)1402*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
1403*7c568831SAndroid Build Coastguard Worker 	                  int depth) {
1404*7c568831SAndroid Build Coastguard Worker     int i;
1405*7c568831SAndroid Build Coastguard Worker     char shift[100];
1406*7c568831SAndroid Build Coastguard Worker 
1407*7c568831SAndroid Build Coastguard Worker     if ((output == NULL) || (comp == NULL)) return;
1408*7c568831SAndroid Build Coastguard Worker 
1409*7c568831SAndroid Build Coastguard Worker     for (i = 0;((i < depth) && (i < 25));i++)
1410*7c568831SAndroid Build Coastguard Worker         shift[2 * i] = shift[2 * i + 1] = ' ';
1411*7c568831SAndroid Build Coastguard Worker     shift[2 * i] = shift[2 * i + 1] = 0;
1412*7c568831SAndroid Build Coastguard Worker 
1413*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%s", shift);
1414*7c568831SAndroid Build Coastguard Worker 
1415*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
1416*7c568831SAndroid Build Coastguard Worker     if (comp->stream) {
1417*7c568831SAndroid Build Coastguard Worker         fprintf(output, "Streaming Expression\n");
1418*7c568831SAndroid Build Coastguard Worker     } else
1419*7c568831SAndroid Build Coastguard Worker #endif
1420*7c568831SAndroid Build Coastguard Worker     {
1421*7c568831SAndroid Build Coastguard Worker         fprintf(output, "Compiled Expression : %d elements\n",
1422*7c568831SAndroid Build Coastguard Worker                 comp->nbStep);
1423*7c568831SAndroid Build Coastguard Worker         i = comp->last;
1424*7c568831SAndroid Build Coastguard Worker         xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
1425*7c568831SAndroid Build Coastguard Worker     }
1426*7c568831SAndroid Build Coastguard Worker }
1427*7c568831SAndroid Build Coastguard Worker 
1428*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_DEBUG_ENABLED */
1429*7c568831SAndroid Build Coastguard Worker 
1430*7c568831SAndroid Build Coastguard Worker /************************************************************************
1431*7c568831SAndroid Build Coastguard Worker  *									*
1432*7c568831SAndroid Build Coastguard Worker  *			XPath object caching				*
1433*7c568831SAndroid Build Coastguard Worker  *									*
1434*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
1435*7c568831SAndroid Build Coastguard Worker 
1436*7c568831SAndroid Build Coastguard Worker /**
1437*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewCache:
1438*7c568831SAndroid Build Coastguard Worker  *
1439*7c568831SAndroid Build Coastguard Worker  * Create a new object cache
1440*7c568831SAndroid Build Coastguard Worker  *
1441*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathCache just allocated.
1442*7c568831SAndroid Build Coastguard Worker  */
1443*7c568831SAndroid Build Coastguard Worker static xmlXPathContextCachePtr
xmlXPathNewCache(void)1444*7c568831SAndroid Build Coastguard Worker xmlXPathNewCache(void)
1445*7c568831SAndroid Build Coastguard Worker {
1446*7c568831SAndroid Build Coastguard Worker     xmlXPathContextCachePtr ret;
1447*7c568831SAndroid Build Coastguard Worker 
1448*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathContextCachePtr) xmlMalloc(sizeof(xmlXPathContextCache));
1449*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
1450*7c568831SAndroid Build Coastguard Worker 	return(NULL);
1451*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathContextCache));
1452*7c568831SAndroid Build Coastguard Worker     ret->maxNodeset = 100;
1453*7c568831SAndroid Build Coastguard Worker     ret->maxMisc = 100;
1454*7c568831SAndroid Build Coastguard Worker     return(ret);
1455*7c568831SAndroid Build Coastguard Worker }
1456*7c568831SAndroid Build Coastguard Worker 
1457*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCacheFreeObjectList(xmlXPathObjectPtr list)1458*7c568831SAndroid Build Coastguard Worker xmlXPathCacheFreeObjectList(xmlXPathObjectPtr list)
1459*7c568831SAndroid Build Coastguard Worker {
1460*7c568831SAndroid Build Coastguard Worker     while (list != NULL) {
1461*7c568831SAndroid Build Coastguard Worker         xmlXPathObjectPtr next;
1462*7c568831SAndroid Build Coastguard Worker 
1463*7c568831SAndroid Build Coastguard Worker         next = (void *) list->stringval;
1464*7c568831SAndroid Build Coastguard Worker 
1465*7c568831SAndroid Build Coastguard Worker 	if (list->nodesetval != NULL) {
1466*7c568831SAndroid Build Coastguard Worker 	    if (list->nodesetval->nodeTab != NULL)
1467*7c568831SAndroid Build Coastguard Worker 		xmlFree(list->nodesetval->nodeTab);
1468*7c568831SAndroid Build Coastguard Worker 	    xmlFree(list->nodesetval);
1469*7c568831SAndroid Build Coastguard Worker 	}
1470*7c568831SAndroid Build Coastguard Worker 	xmlFree(list);
1471*7c568831SAndroid Build Coastguard Worker 
1472*7c568831SAndroid Build Coastguard Worker         list = next;
1473*7c568831SAndroid Build Coastguard Worker     }
1474*7c568831SAndroid Build Coastguard Worker }
1475*7c568831SAndroid Build Coastguard Worker 
1476*7c568831SAndroid Build Coastguard Worker static void
xmlXPathFreeCache(xmlXPathContextCachePtr cache)1477*7c568831SAndroid Build Coastguard Worker xmlXPathFreeCache(xmlXPathContextCachePtr cache)
1478*7c568831SAndroid Build Coastguard Worker {
1479*7c568831SAndroid Build Coastguard Worker     if (cache == NULL)
1480*7c568831SAndroid Build Coastguard Worker 	return;
1481*7c568831SAndroid Build Coastguard Worker     if (cache->nodesetObjs)
1482*7c568831SAndroid Build Coastguard Worker 	xmlXPathCacheFreeObjectList(cache->nodesetObjs);
1483*7c568831SAndroid Build Coastguard Worker     if (cache->miscObjs)
1484*7c568831SAndroid Build Coastguard Worker 	xmlXPathCacheFreeObjectList(cache->miscObjs);
1485*7c568831SAndroid Build Coastguard Worker     xmlFree(cache);
1486*7c568831SAndroid Build Coastguard Worker }
1487*7c568831SAndroid Build Coastguard Worker 
1488*7c568831SAndroid Build Coastguard Worker /**
1489*7c568831SAndroid Build Coastguard Worker  * xmlXPathContextSetCache:
1490*7c568831SAndroid Build Coastguard Worker  *
1491*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
1492*7c568831SAndroid Build Coastguard Worker  * @active: enables/disables (creates/frees) the cache
1493*7c568831SAndroid Build Coastguard Worker  * @value: a value with semantics dependent on @options
1494*7c568831SAndroid Build Coastguard Worker  * @options: options (currently only the value 0 is used)
1495*7c568831SAndroid Build Coastguard Worker  *
1496*7c568831SAndroid Build Coastguard Worker  * Creates/frees an object cache on the XPath context.
1497*7c568831SAndroid Build Coastguard Worker  * If activates XPath objects (xmlXPathObject) will be cached internally
1498*7c568831SAndroid Build Coastguard Worker  * to be reused.
1499*7c568831SAndroid Build Coastguard Worker  * @options:
1500*7c568831SAndroid Build Coastguard Worker  *   0: This will set the XPath object caching:
1501*7c568831SAndroid Build Coastguard Worker  *      @value:
1502*7c568831SAndroid Build Coastguard Worker  *        This will set the maximum number of XPath objects
1503*7c568831SAndroid Build Coastguard Worker  *        to be cached per slot
1504*7c568831SAndroid Build Coastguard Worker  *        There are two slots for node-set and misc objects.
1505*7c568831SAndroid Build Coastguard Worker  *        Use <0 for the default number (100).
1506*7c568831SAndroid Build Coastguard Worker  *   Other values for @options have currently no effect.
1507*7c568831SAndroid Build Coastguard Worker  *
1508*7c568831SAndroid Build Coastguard Worker  * Returns 0 if the setting succeeded, and -1 on API or internal errors.
1509*7c568831SAndroid Build Coastguard Worker  */
1510*7c568831SAndroid Build Coastguard Worker int
xmlXPathContextSetCache(xmlXPathContextPtr ctxt,int active,int value,int options)1511*7c568831SAndroid Build Coastguard Worker xmlXPathContextSetCache(xmlXPathContextPtr ctxt,
1512*7c568831SAndroid Build Coastguard Worker 			int active,
1513*7c568831SAndroid Build Coastguard Worker 			int value,
1514*7c568831SAndroid Build Coastguard Worker 			int options)
1515*7c568831SAndroid Build Coastguard Worker {
1516*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
1517*7c568831SAndroid Build Coastguard Worker 	return(-1);
1518*7c568831SAndroid Build Coastguard Worker     if (active) {
1519*7c568831SAndroid Build Coastguard Worker 	xmlXPathContextCachePtr cache;
1520*7c568831SAndroid Build Coastguard Worker 
1521*7c568831SAndroid Build Coastguard Worker 	if (ctxt->cache == NULL) {
1522*7c568831SAndroid Build Coastguard Worker 	    ctxt->cache = xmlXPathNewCache();
1523*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->cache == NULL) {
1524*7c568831SAndroid Build Coastguard Worker                 xmlXPathErrMemory(ctxt);
1525*7c568831SAndroid Build Coastguard Worker 		return(-1);
1526*7c568831SAndroid Build Coastguard Worker             }
1527*7c568831SAndroid Build Coastguard Worker 	}
1528*7c568831SAndroid Build Coastguard Worker 	cache = (xmlXPathContextCachePtr) ctxt->cache;
1529*7c568831SAndroid Build Coastguard Worker 	if (options == 0) {
1530*7c568831SAndroid Build Coastguard Worker 	    if (value < 0)
1531*7c568831SAndroid Build Coastguard Worker 		value = 100;
1532*7c568831SAndroid Build Coastguard Worker 	    cache->maxNodeset = value;
1533*7c568831SAndroid Build Coastguard Worker 	    cache->maxMisc = value;
1534*7c568831SAndroid Build Coastguard Worker 	}
1535*7c568831SAndroid Build Coastguard Worker     } else if (ctxt->cache != NULL) {
1536*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
1537*7c568831SAndroid Build Coastguard Worker 	ctxt->cache = NULL;
1538*7c568831SAndroid Build Coastguard Worker     }
1539*7c568831SAndroid Build Coastguard Worker     return(0);
1540*7c568831SAndroid Build Coastguard Worker }
1541*7c568831SAndroid Build Coastguard Worker 
1542*7c568831SAndroid Build Coastguard Worker /**
1543*7c568831SAndroid Build Coastguard Worker  * xmlXPathCacheWrapNodeSet:
1544*7c568831SAndroid Build Coastguard Worker  * @pctxt: the XPath context
1545*7c568831SAndroid Build Coastguard Worker  * @val:  the NodePtr value
1546*7c568831SAndroid Build Coastguard Worker  *
1547*7c568831SAndroid Build Coastguard Worker  * This is the cached version of xmlXPathWrapNodeSet().
1548*7c568831SAndroid Build Coastguard Worker  * Wrap the Nodeset @val in a new xmlXPathObjectPtr
1549*7c568831SAndroid Build Coastguard Worker  *
1550*7c568831SAndroid Build Coastguard Worker  * Returns the created or reused object.
1551*7c568831SAndroid Build Coastguard Worker  *
1552*7c568831SAndroid Build Coastguard Worker  * In case of error the node set is destroyed and NULL is returned.
1553*7c568831SAndroid Build Coastguard Worker  */
1554*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheWrapNodeSet(xmlXPathParserContextPtr pctxt,xmlNodeSetPtr val)1555*7c568831SAndroid Build Coastguard Worker xmlXPathCacheWrapNodeSet(xmlXPathParserContextPtr pctxt, xmlNodeSetPtr val)
1556*7c568831SAndroid Build Coastguard Worker {
1557*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
1558*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt = pctxt->context;
1559*7c568831SAndroid Build Coastguard Worker 
1560*7c568831SAndroid Build Coastguard Worker     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1561*7c568831SAndroid Build Coastguard Worker 	xmlXPathContextCachePtr cache =
1562*7c568831SAndroid Build Coastguard Worker 	    (xmlXPathContextCachePtr) ctxt->cache;
1563*7c568831SAndroid Build Coastguard Worker 
1564*7c568831SAndroid Build Coastguard Worker 	if (cache->miscObjs != NULL) {
1565*7c568831SAndroid Build Coastguard Worker 	    ret = cache->miscObjs;
1566*7c568831SAndroid Build Coastguard Worker             cache->miscObjs = (void *) ret->stringval;
1567*7c568831SAndroid Build Coastguard Worker             cache->numMisc -= 1;
1568*7c568831SAndroid Build Coastguard Worker             ret->stringval = NULL;
1569*7c568831SAndroid Build Coastguard Worker 	    ret->type = XPATH_NODESET;
1570*7c568831SAndroid Build Coastguard Worker 	    ret->nodesetval = val;
1571*7c568831SAndroid Build Coastguard Worker 	    return(ret);
1572*7c568831SAndroid Build Coastguard Worker 	}
1573*7c568831SAndroid Build Coastguard Worker     }
1574*7c568831SAndroid Build Coastguard Worker 
1575*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathWrapNodeSet(val);
1576*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
1577*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(pctxt);
1578*7c568831SAndroid Build Coastguard Worker     return(ret);
1579*7c568831SAndroid Build Coastguard Worker }
1580*7c568831SAndroid Build Coastguard Worker 
1581*7c568831SAndroid Build Coastguard Worker /**
1582*7c568831SAndroid Build Coastguard Worker  * xmlXPathCacheWrapString:
1583*7c568831SAndroid Build Coastguard Worker  * @pctxt the XPath context
1584*7c568831SAndroid Build Coastguard Worker  * @val:  the xmlChar * value
1585*7c568831SAndroid Build Coastguard Worker  *
1586*7c568831SAndroid Build Coastguard Worker  * This is the cached version of xmlXPathWrapString().
1587*7c568831SAndroid Build Coastguard Worker  * Wraps the @val string into an XPath object.
1588*7c568831SAndroid Build Coastguard Worker  *
1589*7c568831SAndroid Build Coastguard Worker  * Returns the created or reused object.
1590*7c568831SAndroid Build Coastguard Worker  */
1591*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheWrapString(xmlXPathParserContextPtr pctxt,xmlChar * val)1592*7c568831SAndroid Build Coastguard Worker xmlXPathCacheWrapString(xmlXPathParserContextPtr pctxt, xmlChar *val)
1593*7c568831SAndroid Build Coastguard Worker {
1594*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
1595*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt = pctxt->context;
1596*7c568831SAndroid Build Coastguard Worker 
1597*7c568831SAndroid Build Coastguard Worker     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1598*7c568831SAndroid Build Coastguard Worker 	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1599*7c568831SAndroid Build Coastguard Worker 
1600*7c568831SAndroid Build Coastguard Worker 	if (cache->miscObjs != NULL) {
1601*7c568831SAndroid Build Coastguard Worker 	    ret = cache->miscObjs;
1602*7c568831SAndroid Build Coastguard Worker             cache->miscObjs = (void *) ret->stringval;
1603*7c568831SAndroid Build Coastguard Worker             cache->numMisc -= 1;
1604*7c568831SAndroid Build Coastguard Worker 	    ret->type = XPATH_STRING;
1605*7c568831SAndroid Build Coastguard Worker 	    ret->stringval = val;
1606*7c568831SAndroid Build Coastguard Worker 	    return(ret);
1607*7c568831SAndroid Build Coastguard Worker 	}
1608*7c568831SAndroid Build Coastguard Worker     }
1609*7c568831SAndroid Build Coastguard Worker 
1610*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathWrapString(val);
1611*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
1612*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(pctxt);
1613*7c568831SAndroid Build Coastguard Worker     return(ret);
1614*7c568831SAndroid Build Coastguard Worker }
1615*7c568831SAndroid Build Coastguard Worker 
1616*7c568831SAndroid Build Coastguard Worker /**
1617*7c568831SAndroid Build Coastguard Worker  * xmlXPathCacheNewNodeSet:
1618*7c568831SAndroid Build Coastguard Worker  * @pctxt the XPath context
1619*7c568831SAndroid Build Coastguard Worker  * @val:  the NodePtr value
1620*7c568831SAndroid Build Coastguard Worker  *
1621*7c568831SAndroid Build Coastguard Worker  * This is the cached version of xmlXPathNewNodeSet().
1622*7c568831SAndroid Build Coastguard Worker  * Acquire an xmlXPathObjectPtr of type NodeSet and initialize
1623*7c568831SAndroid Build Coastguard Worker  * it with the single Node @val
1624*7c568831SAndroid Build Coastguard Worker  *
1625*7c568831SAndroid Build Coastguard Worker  * Returns the created or reused object.
1626*7c568831SAndroid Build Coastguard Worker  */
1627*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewNodeSet(xmlXPathParserContextPtr pctxt,xmlNodePtr val)1628*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewNodeSet(xmlXPathParserContextPtr pctxt, xmlNodePtr val)
1629*7c568831SAndroid Build Coastguard Worker {
1630*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
1631*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt = pctxt->context;
1632*7c568831SAndroid Build Coastguard Worker 
1633*7c568831SAndroid Build Coastguard Worker     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1634*7c568831SAndroid Build Coastguard Worker 	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1635*7c568831SAndroid Build Coastguard Worker 
1636*7c568831SAndroid Build Coastguard Worker 	if (cache->nodesetObjs != NULL) {
1637*7c568831SAndroid Build Coastguard Worker 	    /*
1638*7c568831SAndroid Build Coastguard Worker 	    * Use the nodeset-cache.
1639*7c568831SAndroid Build Coastguard Worker 	    */
1640*7c568831SAndroid Build Coastguard Worker 	    ret = cache->nodesetObjs;
1641*7c568831SAndroid Build Coastguard Worker             cache->nodesetObjs = (void *) ret->stringval;
1642*7c568831SAndroid Build Coastguard Worker             cache->numNodeset -= 1;
1643*7c568831SAndroid Build Coastguard Worker             ret->stringval = NULL;
1644*7c568831SAndroid Build Coastguard Worker 	    ret->type = XPATH_NODESET;
1645*7c568831SAndroid Build Coastguard Worker 	    ret->boolval = 0;
1646*7c568831SAndroid Build Coastguard Worker 	    if (val) {
1647*7c568831SAndroid Build Coastguard Worker 		if ((ret->nodesetval->nodeMax == 0) ||
1648*7c568831SAndroid Build Coastguard Worker 		    (val->type == XML_NAMESPACE_DECL))
1649*7c568831SAndroid Build Coastguard Worker 		{
1650*7c568831SAndroid Build Coastguard Worker 		    if (xmlXPathNodeSetAddUnique(ret->nodesetval, val) < 0)
1651*7c568831SAndroid Build Coastguard Worker                         xmlXPathPErrMemory(pctxt);
1652*7c568831SAndroid Build Coastguard Worker 		} else {
1653*7c568831SAndroid Build Coastguard Worker 		    ret->nodesetval->nodeTab[0] = val;
1654*7c568831SAndroid Build Coastguard Worker 		    ret->nodesetval->nodeNr = 1;
1655*7c568831SAndroid Build Coastguard Worker 		}
1656*7c568831SAndroid Build Coastguard Worker 	    }
1657*7c568831SAndroid Build Coastguard Worker 	    return(ret);
1658*7c568831SAndroid Build Coastguard Worker 	} else if (cache->miscObjs != NULL) {
1659*7c568831SAndroid Build Coastguard Worker             xmlNodeSetPtr set;
1660*7c568831SAndroid Build Coastguard Worker 	    /*
1661*7c568831SAndroid Build Coastguard Worker 	    * Fallback to misc-cache.
1662*7c568831SAndroid Build Coastguard Worker 	    */
1663*7c568831SAndroid Build Coastguard Worker 
1664*7c568831SAndroid Build Coastguard Worker 	    set = xmlXPathNodeSetCreate(val);
1665*7c568831SAndroid Build Coastguard Worker 	    if (set == NULL) {
1666*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(pctxt);
1667*7c568831SAndroid Build Coastguard Worker 		return(NULL);
1668*7c568831SAndroid Build Coastguard Worker 	    }
1669*7c568831SAndroid Build Coastguard Worker 
1670*7c568831SAndroid Build Coastguard Worker 	    ret = cache->miscObjs;
1671*7c568831SAndroid Build Coastguard Worker             cache->miscObjs = (void *) ret->stringval;
1672*7c568831SAndroid Build Coastguard Worker             cache->numMisc -= 1;
1673*7c568831SAndroid Build Coastguard Worker             ret->stringval = NULL;
1674*7c568831SAndroid Build Coastguard Worker 	    ret->type = XPATH_NODESET;
1675*7c568831SAndroid Build Coastguard Worker 	    ret->boolval = 0;
1676*7c568831SAndroid Build Coastguard Worker 	    ret->nodesetval = set;
1677*7c568831SAndroid Build Coastguard Worker 	    return(ret);
1678*7c568831SAndroid Build Coastguard Worker 	}
1679*7c568831SAndroid Build Coastguard Worker     }
1680*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNewNodeSet(val);
1681*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
1682*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(pctxt);
1683*7c568831SAndroid Build Coastguard Worker     return(ret);
1684*7c568831SAndroid Build Coastguard Worker }
1685*7c568831SAndroid Build Coastguard Worker 
1686*7c568831SAndroid Build Coastguard Worker /**
1687*7c568831SAndroid Build Coastguard Worker  * xmlXPathCacheNewString:
1688*7c568831SAndroid Build Coastguard Worker  * @pctxt the XPath context
1689*7c568831SAndroid Build Coastguard Worker  * @val:  the xmlChar * value
1690*7c568831SAndroid Build Coastguard Worker  *
1691*7c568831SAndroid Build Coastguard Worker  * This is the cached version of xmlXPathNewString().
1692*7c568831SAndroid Build Coastguard Worker  * Acquire an xmlXPathObjectPtr of type string and of value @val
1693*7c568831SAndroid Build Coastguard Worker  *
1694*7c568831SAndroid Build Coastguard Worker  * Returns the created or reused object.
1695*7c568831SAndroid Build Coastguard Worker  */
1696*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewString(xmlXPathParserContextPtr pctxt,const xmlChar * val)1697*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewString(xmlXPathParserContextPtr pctxt, const xmlChar *val)
1698*7c568831SAndroid Build Coastguard Worker {
1699*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
1700*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt = pctxt->context;
1701*7c568831SAndroid Build Coastguard Worker 
1702*7c568831SAndroid Build Coastguard Worker     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1703*7c568831SAndroid Build Coastguard Worker 	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1704*7c568831SAndroid Build Coastguard Worker 
1705*7c568831SAndroid Build Coastguard Worker 	if (cache->miscObjs != NULL) {
1706*7c568831SAndroid Build Coastguard Worker             xmlChar *copy;
1707*7c568831SAndroid Build Coastguard Worker 
1708*7c568831SAndroid Build Coastguard Worker             if (val == NULL)
1709*7c568831SAndroid Build Coastguard Worker                 val = BAD_CAST "";
1710*7c568831SAndroid Build Coastguard Worker             copy = xmlStrdup(val);
1711*7c568831SAndroid Build Coastguard Worker             if (copy == NULL) {
1712*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(pctxt);
1713*7c568831SAndroid Build Coastguard Worker                 return(NULL);
1714*7c568831SAndroid Build Coastguard Worker             }
1715*7c568831SAndroid Build Coastguard Worker 
1716*7c568831SAndroid Build Coastguard Worker 	    ret = cache->miscObjs;
1717*7c568831SAndroid Build Coastguard Worker             cache->miscObjs = (void *) ret->stringval;
1718*7c568831SAndroid Build Coastguard Worker             cache->numMisc -= 1;
1719*7c568831SAndroid Build Coastguard Worker 	    ret->type = XPATH_STRING;
1720*7c568831SAndroid Build Coastguard Worker             ret->stringval = copy;
1721*7c568831SAndroid Build Coastguard Worker 	    return(ret);
1722*7c568831SAndroid Build Coastguard Worker 	}
1723*7c568831SAndroid Build Coastguard Worker     }
1724*7c568831SAndroid Build Coastguard Worker 
1725*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNewString(val);
1726*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
1727*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(pctxt);
1728*7c568831SAndroid Build Coastguard Worker     return(ret);
1729*7c568831SAndroid Build Coastguard Worker }
1730*7c568831SAndroid Build Coastguard Worker 
1731*7c568831SAndroid Build Coastguard Worker /**
1732*7c568831SAndroid Build Coastguard Worker  * xmlXPathCacheNewCString:
1733*7c568831SAndroid Build Coastguard Worker  * @pctxt the XPath context
1734*7c568831SAndroid Build Coastguard Worker  * @val:  the char * value
1735*7c568831SAndroid Build Coastguard Worker  *
1736*7c568831SAndroid Build Coastguard Worker  * This is the cached version of xmlXPathNewCString().
1737*7c568831SAndroid Build Coastguard Worker  * Acquire an xmlXPathObjectPtr of type string and of value @val
1738*7c568831SAndroid Build Coastguard Worker  *
1739*7c568831SAndroid Build Coastguard Worker  * Returns the created or reused object.
1740*7c568831SAndroid Build Coastguard Worker  */
1741*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewCString(xmlXPathParserContextPtr pctxt,const char * val)1742*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewCString(xmlXPathParserContextPtr pctxt, const char *val)
1743*7c568831SAndroid Build Coastguard Worker {
1744*7c568831SAndroid Build Coastguard Worker     return xmlXPathCacheNewString(pctxt, BAD_CAST val);
1745*7c568831SAndroid Build Coastguard Worker }
1746*7c568831SAndroid Build Coastguard Worker 
1747*7c568831SAndroid Build Coastguard Worker /**
1748*7c568831SAndroid Build Coastguard Worker  * xmlXPathCacheNewBoolean:
1749*7c568831SAndroid Build Coastguard Worker  * @pctxt the XPath context
1750*7c568831SAndroid Build Coastguard Worker  * @val:  the boolean value
1751*7c568831SAndroid Build Coastguard Worker  *
1752*7c568831SAndroid Build Coastguard Worker  * This is the cached version of xmlXPathNewBoolean().
1753*7c568831SAndroid Build Coastguard Worker  * Acquires an xmlXPathObjectPtr of type boolean and of value @val
1754*7c568831SAndroid Build Coastguard Worker  *
1755*7c568831SAndroid Build Coastguard Worker  * Returns the created or reused object.
1756*7c568831SAndroid Build Coastguard Worker  */
1757*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewBoolean(xmlXPathParserContextPtr pctxt,int val)1758*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewBoolean(xmlXPathParserContextPtr pctxt, int val)
1759*7c568831SAndroid Build Coastguard Worker {
1760*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
1761*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt = pctxt->context;
1762*7c568831SAndroid Build Coastguard Worker 
1763*7c568831SAndroid Build Coastguard Worker     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1764*7c568831SAndroid Build Coastguard Worker 	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1765*7c568831SAndroid Build Coastguard Worker 
1766*7c568831SAndroid Build Coastguard Worker 	if (cache->miscObjs != NULL) {
1767*7c568831SAndroid Build Coastguard Worker 	    ret = cache->miscObjs;
1768*7c568831SAndroid Build Coastguard Worker             cache->miscObjs = (void *) ret->stringval;
1769*7c568831SAndroid Build Coastguard Worker             cache->numMisc -= 1;
1770*7c568831SAndroid Build Coastguard Worker             ret->stringval = NULL;
1771*7c568831SAndroid Build Coastguard Worker 	    ret->type = XPATH_BOOLEAN;
1772*7c568831SAndroid Build Coastguard Worker 	    ret->boolval = (val != 0);
1773*7c568831SAndroid Build Coastguard Worker 	    return(ret);
1774*7c568831SAndroid Build Coastguard Worker 	}
1775*7c568831SAndroid Build Coastguard Worker     }
1776*7c568831SAndroid Build Coastguard Worker 
1777*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNewBoolean(val);
1778*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
1779*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(pctxt);
1780*7c568831SAndroid Build Coastguard Worker     return(ret);
1781*7c568831SAndroid Build Coastguard Worker }
1782*7c568831SAndroid Build Coastguard Worker 
1783*7c568831SAndroid Build Coastguard Worker /**
1784*7c568831SAndroid Build Coastguard Worker  * xmlXPathCacheNewFloat:
1785*7c568831SAndroid Build Coastguard Worker  * @pctxt the XPath context
1786*7c568831SAndroid Build Coastguard Worker  * @val:  the double value
1787*7c568831SAndroid Build Coastguard Worker  *
1788*7c568831SAndroid Build Coastguard Worker  * This is the cached version of xmlXPathNewFloat().
1789*7c568831SAndroid Build Coastguard Worker  * Acquires an xmlXPathObjectPtr of type double and of value @val
1790*7c568831SAndroid Build Coastguard Worker  *
1791*7c568831SAndroid Build Coastguard Worker  * Returns the created or reused object.
1792*7c568831SAndroid Build Coastguard Worker  */
1793*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewFloat(xmlXPathParserContextPtr pctxt,double val)1794*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewFloat(xmlXPathParserContextPtr pctxt, double val)
1795*7c568831SAndroid Build Coastguard Worker {
1796*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
1797*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt = pctxt->context;
1798*7c568831SAndroid Build Coastguard Worker 
1799*7c568831SAndroid Build Coastguard Worker     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1800*7c568831SAndroid Build Coastguard Worker 	xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1801*7c568831SAndroid Build Coastguard Worker 
1802*7c568831SAndroid Build Coastguard Worker 	if (cache->miscObjs != NULL) {
1803*7c568831SAndroid Build Coastguard Worker 	    ret = cache->miscObjs;
1804*7c568831SAndroid Build Coastguard Worker             cache->miscObjs = (void *) ret->stringval;
1805*7c568831SAndroid Build Coastguard Worker             cache->numMisc -= 1;
1806*7c568831SAndroid Build Coastguard Worker             ret->stringval = NULL;
1807*7c568831SAndroid Build Coastguard Worker 	    ret->type = XPATH_NUMBER;
1808*7c568831SAndroid Build Coastguard Worker 	    ret->floatval = val;
1809*7c568831SAndroid Build Coastguard Worker 	    return(ret);
1810*7c568831SAndroid Build Coastguard Worker 	}
1811*7c568831SAndroid Build Coastguard Worker     }
1812*7c568831SAndroid Build Coastguard Worker 
1813*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNewFloat(val);
1814*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
1815*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(pctxt);
1816*7c568831SAndroid Build Coastguard Worker     return(ret);
1817*7c568831SAndroid Build Coastguard Worker }
1818*7c568831SAndroid Build Coastguard Worker 
1819*7c568831SAndroid Build Coastguard Worker /**
1820*7c568831SAndroid Build Coastguard Worker  * xmlXPathCacheObjectCopy:
1821*7c568831SAndroid Build Coastguard Worker  * @pctxt the XPath context
1822*7c568831SAndroid Build Coastguard Worker  * @val:  the original object
1823*7c568831SAndroid Build Coastguard Worker  *
1824*7c568831SAndroid Build Coastguard Worker  * This is the cached version of xmlXPathObjectCopy().
1825*7c568831SAndroid Build Coastguard Worker  * Acquire a copy of a given object
1826*7c568831SAndroid Build Coastguard Worker  *
1827*7c568831SAndroid Build Coastguard Worker  * Returns a created or reused created object.
1828*7c568831SAndroid Build Coastguard Worker  */
1829*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheObjectCopy(xmlXPathParserContextPtr pctxt,xmlXPathObjectPtr val)1830*7c568831SAndroid Build Coastguard Worker xmlXPathCacheObjectCopy(xmlXPathParserContextPtr pctxt, xmlXPathObjectPtr val)
1831*7c568831SAndroid Build Coastguard Worker {
1832*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
1833*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt = pctxt->context;
1834*7c568831SAndroid Build Coastguard Worker 
1835*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
1836*7c568831SAndroid Build Coastguard Worker 	return(NULL);
1837*7c568831SAndroid Build Coastguard Worker 
1838*7c568831SAndroid Build Coastguard Worker     if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1839*7c568831SAndroid Build Coastguard Worker 	switch (val->type) {
1840*7c568831SAndroid Build Coastguard Worker             case XPATH_NODESET: {
1841*7c568831SAndroid Build Coastguard Worker                 xmlNodeSetPtr set;
1842*7c568831SAndroid Build Coastguard Worker 
1843*7c568831SAndroid Build Coastguard Worker                 set = xmlXPathNodeSetMerge(NULL, val->nodesetval);
1844*7c568831SAndroid Build Coastguard Worker                 if (set == NULL) {
1845*7c568831SAndroid Build Coastguard Worker                     xmlXPathPErrMemory(pctxt);
1846*7c568831SAndroid Build Coastguard Worker                     return(NULL);
1847*7c568831SAndroid Build Coastguard Worker                 }
1848*7c568831SAndroid Build Coastguard Worker                 return(xmlXPathCacheWrapNodeSet(pctxt, set));
1849*7c568831SAndroid Build Coastguard Worker             }
1850*7c568831SAndroid Build Coastguard Worker 	    case XPATH_STRING:
1851*7c568831SAndroid Build Coastguard Worker 		return(xmlXPathCacheNewString(pctxt, val->stringval));
1852*7c568831SAndroid Build Coastguard Worker 	    case XPATH_BOOLEAN:
1853*7c568831SAndroid Build Coastguard Worker 		return(xmlXPathCacheNewBoolean(pctxt, val->boolval));
1854*7c568831SAndroid Build Coastguard Worker 	    case XPATH_NUMBER:
1855*7c568831SAndroid Build Coastguard Worker 		return(xmlXPathCacheNewFloat(pctxt, val->floatval));
1856*7c568831SAndroid Build Coastguard Worker 	    default:
1857*7c568831SAndroid Build Coastguard Worker 		break;
1858*7c568831SAndroid Build Coastguard Worker 	}
1859*7c568831SAndroid Build Coastguard Worker     }
1860*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathObjectCopy(val);
1861*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
1862*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(pctxt);
1863*7c568831SAndroid Build Coastguard Worker     return(ret);
1864*7c568831SAndroid Build Coastguard Worker }
1865*7c568831SAndroid Build Coastguard Worker 
1866*7c568831SAndroid Build Coastguard Worker /************************************************************************
1867*7c568831SAndroid Build Coastguard Worker  *									*
1868*7c568831SAndroid Build Coastguard Worker  *		Parser stacks related functions and macros		*
1869*7c568831SAndroid Build Coastguard Worker  *									*
1870*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
1871*7c568831SAndroid Build Coastguard Worker 
1872*7c568831SAndroid Build Coastguard Worker /**
1873*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastToNumberInternal:
1874*7c568831SAndroid Build Coastguard Worker  * @ctxt:  parser context
1875*7c568831SAndroid Build Coastguard Worker  * @val:  an XPath object
1876*7c568831SAndroid Build Coastguard Worker  *
1877*7c568831SAndroid Build Coastguard Worker  * Converts an XPath object to its number value
1878*7c568831SAndroid Build Coastguard Worker  *
1879*7c568831SAndroid Build Coastguard Worker  * Returns the number value
1880*7c568831SAndroid Build Coastguard Worker  */
1881*7c568831SAndroid Build Coastguard Worker static double
xmlXPathCastToNumberInternal(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr val)1882*7c568831SAndroid Build Coastguard Worker xmlXPathCastToNumberInternal(xmlXPathParserContextPtr ctxt,
1883*7c568831SAndroid Build Coastguard Worker                              xmlXPathObjectPtr val) {
1884*7c568831SAndroid Build Coastguard Worker     double ret = 0.0;
1885*7c568831SAndroid Build Coastguard Worker 
1886*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
1887*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNAN);
1888*7c568831SAndroid Build Coastguard Worker     switch (val->type) {
1889*7c568831SAndroid Build Coastguard Worker     case XPATH_UNDEFINED:
1890*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathNAN;
1891*7c568831SAndroid Build Coastguard Worker 	break;
1892*7c568831SAndroid Build Coastguard Worker     case XPATH_NODESET:
1893*7c568831SAndroid Build Coastguard Worker     case XPATH_XSLT_TREE: {
1894*7c568831SAndroid Build Coastguard Worker         xmlChar *str;
1895*7c568831SAndroid Build Coastguard Worker 
1896*7c568831SAndroid Build Coastguard Worker 	str = xmlXPathCastNodeSetToString(val->nodesetval);
1897*7c568831SAndroid Build Coastguard Worker         if (str == NULL) {
1898*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
1899*7c568831SAndroid Build Coastguard Worker             ret = xmlXPathNAN;
1900*7c568831SAndroid Build Coastguard Worker         } else {
1901*7c568831SAndroid Build Coastguard Worker 	    ret = xmlXPathCastStringToNumber(str);
1902*7c568831SAndroid Build Coastguard Worker             xmlFree(str);
1903*7c568831SAndroid Build Coastguard Worker         }
1904*7c568831SAndroid Build Coastguard Worker 	break;
1905*7c568831SAndroid Build Coastguard Worker     }
1906*7c568831SAndroid Build Coastguard Worker     case XPATH_STRING:
1907*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathCastStringToNumber(val->stringval);
1908*7c568831SAndroid Build Coastguard Worker 	break;
1909*7c568831SAndroid Build Coastguard Worker     case XPATH_NUMBER:
1910*7c568831SAndroid Build Coastguard Worker 	ret = val->floatval;
1911*7c568831SAndroid Build Coastguard Worker 	break;
1912*7c568831SAndroid Build Coastguard Worker     case XPATH_BOOLEAN:
1913*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathCastBooleanToNumber(val->boolval);
1914*7c568831SAndroid Build Coastguard Worker 	break;
1915*7c568831SAndroid Build Coastguard Worker     case XPATH_USERS:
1916*7c568831SAndroid Build Coastguard Worker 	/* TODO */
1917*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathNAN;
1918*7c568831SAndroid Build Coastguard Worker 	break;
1919*7c568831SAndroid Build Coastguard Worker     }
1920*7c568831SAndroid Build Coastguard Worker     return(ret);
1921*7c568831SAndroid Build Coastguard Worker }
1922*7c568831SAndroid Build Coastguard Worker 
1923*7c568831SAndroid Build Coastguard Worker /**
1924*7c568831SAndroid Build Coastguard Worker  * valuePop:
1925*7c568831SAndroid Build Coastguard Worker  * @ctxt: an XPath evaluation context
1926*7c568831SAndroid Build Coastguard Worker  *
1927*7c568831SAndroid Build Coastguard Worker  * Pops the top XPath object from the value stack
1928*7c568831SAndroid Build Coastguard Worker  *
1929*7c568831SAndroid Build Coastguard Worker  * Returns the XPath object just removed
1930*7c568831SAndroid Build Coastguard Worker  */
1931*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
valuePop(xmlXPathParserContextPtr ctxt)1932*7c568831SAndroid Build Coastguard Worker valuePop(xmlXPathParserContextPtr ctxt)
1933*7c568831SAndroid Build Coastguard Worker {
1934*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
1935*7c568831SAndroid Build Coastguard Worker 
1936*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->valueNr <= 0))
1937*7c568831SAndroid Build Coastguard Worker         return (NULL);
1938*7c568831SAndroid Build Coastguard Worker 
1939*7c568831SAndroid Build Coastguard Worker     ctxt->valueNr--;
1940*7c568831SAndroid Build Coastguard Worker     if (ctxt->valueNr > 0)
1941*7c568831SAndroid Build Coastguard Worker         ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
1942*7c568831SAndroid Build Coastguard Worker     else
1943*7c568831SAndroid Build Coastguard Worker         ctxt->value = NULL;
1944*7c568831SAndroid Build Coastguard Worker     ret = ctxt->valueTab[ctxt->valueNr];
1945*7c568831SAndroid Build Coastguard Worker     ctxt->valueTab[ctxt->valueNr] = NULL;
1946*7c568831SAndroid Build Coastguard Worker     return (ret);
1947*7c568831SAndroid Build Coastguard Worker }
1948*7c568831SAndroid Build Coastguard Worker /**
1949*7c568831SAndroid Build Coastguard Worker  * valuePush:
1950*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an XPath evaluation context
1951*7c568831SAndroid Build Coastguard Worker  * @value:  the XPath object
1952*7c568831SAndroid Build Coastguard Worker  *
1953*7c568831SAndroid Build Coastguard Worker  * Pushes a new XPath object on top of the value stack. If value is NULL,
1954*7c568831SAndroid Build Coastguard Worker  * a memory error is recorded in the parser context.
1955*7c568831SAndroid Build Coastguard Worker  *
1956*7c568831SAndroid Build Coastguard Worker  * Returns the number of items on the value stack, or -1 in case of error.
1957*7c568831SAndroid Build Coastguard Worker  *
1958*7c568831SAndroid Build Coastguard Worker  * The object is destroyed in case of error.
1959*7c568831SAndroid Build Coastguard Worker  */
1960*7c568831SAndroid Build Coastguard Worker int
valuePush(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr value)1961*7c568831SAndroid Build Coastguard Worker valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
1962*7c568831SAndroid Build Coastguard Worker {
1963*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return(-1);
1964*7c568831SAndroid Build Coastguard Worker     if (value == NULL) {
1965*7c568831SAndroid Build Coastguard Worker         /*
1966*7c568831SAndroid Build Coastguard Worker          * A NULL value typically indicates that a memory allocation failed.
1967*7c568831SAndroid Build Coastguard Worker          */
1968*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
1969*7c568831SAndroid Build Coastguard Worker         return(-1);
1970*7c568831SAndroid Build Coastguard Worker     }
1971*7c568831SAndroid Build Coastguard Worker     if (ctxt->valueNr >= ctxt->valueMax) {
1972*7c568831SAndroid Build Coastguard Worker         xmlXPathObjectPtr *tmp;
1973*7c568831SAndroid Build Coastguard Worker 
1974*7c568831SAndroid Build Coastguard Worker         if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
1975*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
1976*7c568831SAndroid Build Coastguard Worker             xmlXPathFreeObject(value);
1977*7c568831SAndroid Build Coastguard Worker             return (-1);
1978*7c568831SAndroid Build Coastguard Worker         }
1979*7c568831SAndroid Build Coastguard Worker         tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
1980*7c568831SAndroid Build Coastguard Worker                                              2 * ctxt->valueMax *
1981*7c568831SAndroid Build Coastguard Worker                                              sizeof(ctxt->valueTab[0]));
1982*7c568831SAndroid Build Coastguard Worker         if (tmp == NULL) {
1983*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
1984*7c568831SAndroid Build Coastguard Worker             xmlXPathFreeObject(value);
1985*7c568831SAndroid Build Coastguard Worker             return (-1);
1986*7c568831SAndroid Build Coastguard Worker         }
1987*7c568831SAndroid Build Coastguard Worker         ctxt->valueMax *= 2;
1988*7c568831SAndroid Build Coastguard Worker 	ctxt->valueTab = tmp;
1989*7c568831SAndroid Build Coastguard Worker     }
1990*7c568831SAndroid Build Coastguard Worker     ctxt->valueTab[ctxt->valueNr] = value;
1991*7c568831SAndroid Build Coastguard Worker     ctxt->value = value;
1992*7c568831SAndroid Build Coastguard Worker     return (ctxt->valueNr++);
1993*7c568831SAndroid Build Coastguard Worker }
1994*7c568831SAndroid Build Coastguard Worker 
1995*7c568831SAndroid Build Coastguard Worker /**
1996*7c568831SAndroid Build Coastguard Worker  * xmlXPathPopBoolean:
1997*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an XPath parser context
1998*7c568831SAndroid Build Coastguard Worker  *
1999*7c568831SAndroid Build Coastguard Worker  * Pops a boolean from the stack, handling conversion if needed.
2000*7c568831SAndroid Build Coastguard Worker  * Check error with #xmlXPathCheckError.
2001*7c568831SAndroid Build Coastguard Worker  *
2002*7c568831SAndroid Build Coastguard Worker  * Returns the boolean
2003*7c568831SAndroid Build Coastguard Worker  */
2004*7c568831SAndroid Build Coastguard Worker int
xmlXPathPopBoolean(xmlXPathParserContextPtr ctxt)2005*7c568831SAndroid Build Coastguard Worker xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
2006*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr obj;
2007*7c568831SAndroid Build Coastguard Worker     int ret;
2008*7c568831SAndroid Build Coastguard Worker 
2009*7c568831SAndroid Build Coastguard Worker     obj = valuePop(ctxt);
2010*7c568831SAndroid Build Coastguard Worker     if (obj == NULL) {
2011*7c568831SAndroid Build Coastguard Worker 	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2012*7c568831SAndroid Build Coastguard Worker 	return(0);
2013*7c568831SAndroid Build Coastguard Worker     }
2014*7c568831SAndroid Build Coastguard Worker     if (obj->type != XPATH_BOOLEAN)
2015*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathCastToBoolean(obj);
2016*7c568831SAndroid Build Coastguard Worker     else
2017*7c568831SAndroid Build Coastguard Worker         ret = obj->boolval;
2018*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, obj);
2019*7c568831SAndroid Build Coastguard Worker     return(ret);
2020*7c568831SAndroid Build Coastguard Worker }
2021*7c568831SAndroid Build Coastguard Worker 
2022*7c568831SAndroid Build Coastguard Worker /**
2023*7c568831SAndroid Build Coastguard Worker  * xmlXPathPopNumber:
2024*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an XPath parser context
2025*7c568831SAndroid Build Coastguard Worker  *
2026*7c568831SAndroid Build Coastguard Worker  * Pops a number from the stack, handling conversion if needed.
2027*7c568831SAndroid Build Coastguard Worker  * Check error with #xmlXPathCheckError.
2028*7c568831SAndroid Build Coastguard Worker  *
2029*7c568831SAndroid Build Coastguard Worker  * Returns the number
2030*7c568831SAndroid Build Coastguard Worker  */
2031*7c568831SAndroid Build Coastguard Worker double
xmlXPathPopNumber(xmlXPathParserContextPtr ctxt)2032*7c568831SAndroid Build Coastguard Worker xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
2033*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr obj;
2034*7c568831SAndroid Build Coastguard Worker     double ret;
2035*7c568831SAndroid Build Coastguard Worker 
2036*7c568831SAndroid Build Coastguard Worker     obj = valuePop(ctxt);
2037*7c568831SAndroid Build Coastguard Worker     if (obj == NULL) {
2038*7c568831SAndroid Build Coastguard Worker 	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2039*7c568831SAndroid Build Coastguard Worker 	return(0);
2040*7c568831SAndroid Build Coastguard Worker     }
2041*7c568831SAndroid Build Coastguard Worker     if (obj->type != XPATH_NUMBER)
2042*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathCastToNumberInternal(ctxt, obj);
2043*7c568831SAndroid Build Coastguard Worker     else
2044*7c568831SAndroid Build Coastguard Worker         ret = obj->floatval;
2045*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, obj);
2046*7c568831SAndroid Build Coastguard Worker     return(ret);
2047*7c568831SAndroid Build Coastguard Worker }
2048*7c568831SAndroid Build Coastguard Worker 
2049*7c568831SAndroid Build Coastguard Worker /**
2050*7c568831SAndroid Build Coastguard Worker  * xmlXPathPopString:
2051*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an XPath parser context
2052*7c568831SAndroid Build Coastguard Worker  *
2053*7c568831SAndroid Build Coastguard Worker  * Pops a string from the stack, handling conversion if needed.
2054*7c568831SAndroid Build Coastguard Worker  * Check error with #xmlXPathCheckError.
2055*7c568831SAndroid Build Coastguard Worker  *
2056*7c568831SAndroid Build Coastguard Worker  * Returns the string
2057*7c568831SAndroid Build Coastguard Worker  */
2058*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathPopString(xmlXPathParserContextPtr ctxt)2059*7c568831SAndroid Build Coastguard Worker xmlXPathPopString (xmlXPathParserContextPtr ctxt) {
2060*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr obj;
2061*7c568831SAndroid Build Coastguard Worker     xmlChar * ret;
2062*7c568831SAndroid Build Coastguard Worker 
2063*7c568831SAndroid Build Coastguard Worker     obj = valuePop(ctxt);
2064*7c568831SAndroid Build Coastguard Worker     if (obj == NULL) {
2065*7c568831SAndroid Build Coastguard Worker 	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2066*7c568831SAndroid Build Coastguard Worker 	return(NULL);
2067*7c568831SAndroid Build Coastguard Worker     }
2068*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathCastToString(obj);
2069*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
2070*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
2071*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, obj);
2072*7c568831SAndroid Build Coastguard Worker     return(ret);
2073*7c568831SAndroid Build Coastguard Worker }
2074*7c568831SAndroid Build Coastguard Worker 
2075*7c568831SAndroid Build Coastguard Worker /**
2076*7c568831SAndroid Build Coastguard Worker  * xmlXPathPopNodeSet:
2077*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an XPath parser context
2078*7c568831SAndroid Build Coastguard Worker  *
2079*7c568831SAndroid Build Coastguard Worker  * Pops a node-set from the stack, handling conversion if needed.
2080*7c568831SAndroid Build Coastguard Worker  * Check error with #xmlXPathCheckError.
2081*7c568831SAndroid Build Coastguard Worker  *
2082*7c568831SAndroid Build Coastguard Worker  * Returns the node-set
2083*7c568831SAndroid Build Coastguard Worker  */
2084*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathPopNodeSet(xmlXPathParserContextPtr ctxt)2085*7c568831SAndroid Build Coastguard Worker xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
2086*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr obj;
2087*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret;
2088*7c568831SAndroid Build Coastguard Worker 
2089*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return(NULL);
2090*7c568831SAndroid Build Coastguard Worker     if (ctxt->value == NULL) {
2091*7c568831SAndroid Build Coastguard Worker 	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2092*7c568831SAndroid Build Coastguard Worker 	return(NULL);
2093*7c568831SAndroid Build Coastguard Worker     }
2094*7c568831SAndroid Build Coastguard Worker     if (!xmlXPathStackIsNodeSet(ctxt)) {
2095*7c568831SAndroid Build Coastguard Worker 	xmlXPathSetTypeError(ctxt);
2096*7c568831SAndroid Build Coastguard Worker 	return(NULL);
2097*7c568831SAndroid Build Coastguard Worker     }
2098*7c568831SAndroid Build Coastguard Worker     obj = valuePop(ctxt);
2099*7c568831SAndroid Build Coastguard Worker     ret = obj->nodesetval;
2100*7c568831SAndroid Build Coastguard Worker     obj->nodesetval = NULL;
2101*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, obj);
2102*7c568831SAndroid Build Coastguard Worker     return(ret);
2103*7c568831SAndroid Build Coastguard Worker }
2104*7c568831SAndroid Build Coastguard Worker 
2105*7c568831SAndroid Build Coastguard Worker /**
2106*7c568831SAndroid Build Coastguard Worker  * xmlXPathPopExternal:
2107*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an XPath parser context
2108*7c568831SAndroid Build Coastguard Worker  *
2109*7c568831SAndroid Build Coastguard Worker  * Pops an external object from the stack, handling conversion if needed.
2110*7c568831SAndroid Build Coastguard Worker  * Check error with #xmlXPathCheckError.
2111*7c568831SAndroid Build Coastguard Worker  *
2112*7c568831SAndroid Build Coastguard Worker  * Returns the object
2113*7c568831SAndroid Build Coastguard Worker  */
2114*7c568831SAndroid Build Coastguard Worker void *
xmlXPathPopExternal(xmlXPathParserContextPtr ctxt)2115*7c568831SAndroid Build Coastguard Worker xmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
2116*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr obj;
2117*7c568831SAndroid Build Coastguard Worker     void * ret;
2118*7c568831SAndroid Build Coastguard Worker 
2119*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->value == NULL)) {
2120*7c568831SAndroid Build Coastguard Worker 	xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2121*7c568831SAndroid Build Coastguard Worker 	return(NULL);
2122*7c568831SAndroid Build Coastguard Worker     }
2123*7c568831SAndroid Build Coastguard Worker     if (ctxt->value->type != XPATH_USERS) {
2124*7c568831SAndroid Build Coastguard Worker 	xmlXPathSetTypeError(ctxt);
2125*7c568831SAndroid Build Coastguard Worker 	return(NULL);
2126*7c568831SAndroid Build Coastguard Worker     }
2127*7c568831SAndroid Build Coastguard Worker     obj = valuePop(ctxt);
2128*7c568831SAndroid Build Coastguard Worker     ret = obj->user;
2129*7c568831SAndroid Build Coastguard Worker     obj->user = NULL;
2130*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, obj);
2131*7c568831SAndroid Build Coastguard Worker     return(ret);
2132*7c568831SAndroid Build Coastguard Worker }
2133*7c568831SAndroid Build Coastguard Worker 
2134*7c568831SAndroid Build Coastguard Worker /*
2135*7c568831SAndroid Build Coastguard Worker  * Macros for accessing the content. Those should be used only by the parser,
2136*7c568831SAndroid Build Coastguard Worker  * and not exported.
2137*7c568831SAndroid Build Coastguard Worker  *
2138*7c568831SAndroid Build Coastguard Worker  * Dirty macros, i.e. one need to make assumption on the context to use them
2139*7c568831SAndroid Build Coastguard Worker  *
2140*7c568831SAndroid Build Coastguard Worker  *   CUR_PTR return the current pointer to the xmlChar to be parsed.
2141*7c568831SAndroid Build Coastguard Worker  *   CUR     returns the current xmlChar value, i.e. a 8 bit value
2142*7c568831SAndroid Build Coastguard Worker  *           in ISO-Latin or UTF-8.
2143*7c568831SAndroid Build Coastguard Worker  *           This should be used internally by the parser
2144*7c568831SAndroid Build Coastguard Worker  *           only to compare to ASCII values otherwise it would break when
2145*7c568831SAndroid Build Coastguard Worker  *           running with UTF-8 encoding.
2146*7c568831SAndroid Build Coastguard Worker  *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
2147*7c568831SAndroid Build Coastguard Worker  *           to compare on ASCII based substring.
2148*7c568831SAndroid Build Coastguard Worker  *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
2149*7c568831SAndroid Build Coastguard Worker  *           strings within the parser.
2150*7c568831SAndroid Build Coastguard Worker  *   CURRENT Returns the current char value, with the full decoding of
2151*7c568831SAndroid Build Coastguard Worker  *           UTF-8 if we are using this mode. It returns an int.
2152*7c568831SAndroid Build Coastguard Worker  *   NEXT    Skip to the next character, this does the proper decoding
2153*7c568831SAndroid Build Coastguard Worker  *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
2154*7c568831SAndroid Build Coastguard Worker  *           It returns the pointer to the current xmlChar.
2155*7c568831SAndroid Build Coastguard Worker  */
2156*7c568831SAndroid Build Coastguard Worker 
2157*7c568831SAndroid Build Coastguard Worker #define CUR (*ctxt->cur)
2158*7c568831SAndroid Build Coastguard Worker #define SKIP(val) ctxt->cur += (val)
2159*7c568831SAndroid Build Coastguard Worker #define NXT(val) ctxt->cur[(val)]
2160*7c568831SAndroid Build Coastguard Worker #define CUR_PTR ctxt->cur
2161*7c568831SAndroid Build Coastguard Worker #define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
2162*7c568831SAndroid Build Coastguard Worker 
2163*7c568831SAndroid Build Coastguard Worker #define COPY_BUF(b, i, v)						\
2164*7c568831SAndroid Build Coastguard Worker     if (v < 0x80) b[i++] = v;						\
2165*7c568831SAndroid Build Coastguard Worker     else i += xmlCopyCharMultiByte(&b[i],v)
2166*7c568831SAndroid Build Coastguard Worker 
2167*7c568831SAndroid Build Coastguard Worker #define NEXTL(l)  ctxt->cur += l
2168*7c568831SAndroid Build Coastguard Worker 
2169*7c568831SAndroid Build Coastguard Worker #define SKIP_BLANKS							\
2170*7c568831SAndroid Build Coastguard Worker     while (IS_BLANK_CH(*(ctxt->cur))) NEXT
2171*7c568831SAndroid Build Coastguard Worker 
2172*7c568831SAndroid Build Coastguard Worker #define CURRENT (*ctxt->cur)
2173*7c568831SAndroid Build Coastguard Worker #define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)
2174*7c568831SAndroid Build Coastguard Worker 
2175*7c568831SAndroid Build Coastguard Worker 
2176*7c568831SAndroid Build Coastguard Worker #ifndef DBL_DIG
2177*7c568831SAndroid Build Coastguard Worker #define DBL_DIG 16
2178*7c568831SAndroid Build Coastguard Worker #endif
2179*7c568831SAndroid Build Coastguard Worker #ifndef DBL_EPSILON
2180*7c568831SAndroid Build Coastguard Worker #define DBL_EPSILON 1E-9
2181*7c568831SAndroid Build Coastguard Worker #endif
2182*7c568831SAndroid Build Coastguard Worker 
2183*7c568831SAndroid Build Coastguard Worker #define UPPER_DOUBLE 1E9
2184*7c568831SAndroid Build Coastguard Worker #define LOWER_DOUBLE 1E-5
2185*7c568831SAndroid Build Coastguard Worker #define	LOWER_DOUBLE_EXP 5
2186*7c568831SAndroid Build Coastguard Worker 
2187*7c568831SAndroid Build Coastguard Worker #define INTEGER_DIGITS DBL_DIG
2188*7c568831SAndroid Build Coastguard Worker #define FRACTION_DIGITS (DBL_DIG + 1 + (LOWER_DOUBLE_EXP))
2189*7c568831SAndroid Build Coastguard Worker #define EXPONENT_DIGITS (3 + 2)
2190*7c568831SAndroid Build Coastguard Worker 
2191*7c568831SAndroid Build Coastguard Worker /**
2192*7c568831SAndroid Build Coastguard Worker  * xmlXPathFormatNumber:
2193*7c568831SAndroid Build Coastguard Worker  * @number:     number to format
2194*7c568831SAndroid Build Coastguard Worker  * @buffer:     output buffer
2195*7c568831SAndroid Build Coastguard Worker  * @buffersize: size of output buffer
2196*7c568831SAndroid Build Coastguard Worker  *
2197*7c568831SAndroid Build Coastguard Worker  * Convert the number into a string representation.
2198*7c568831SAndroid Build Coastguard Worker  */
2199*7c568831SAndroid Build Coastguard Worker static void
xmlXPathFormatNumber(double number,char buffer[],int buffersize)2200*7c568831SAndroid Build Coastguard Worker xmlXPathFormatNumber(double number, char buffer[], int buffersize)
2201*7c568831SAndroid Build Coastguard Worker {
2202*7c568831SAndroid Build Coastguard Worker     switch (xmlXPathIsInf(number)) {
2203*7c568831SAndroid Build Coastguard Worker     case 1:
2204*7c568831SAndroid Build Coastguard Worker 	if (buffersize > (int)sizeof("Infinity"))
2205*7c568831SAndroid Build Coastguard Worker 	    snprintf(buffer, buffersize, "Infinity");
2206*7c568831SAndroid Build Coastguard Worker 	break;
2207*7c568831SAndroid Build Coastguard Worker     case -1:
2208*7c568831SAndroid Build Coastguard Worker 	if (buffersize > (int)sizeof("-Infinity"))
2209*7c568831SAndroid Build Coastguard Worker 	    snprintf(buffer, buffersize, "-Infinity");
2210*7c568831SAndroid Build Coastguard Worker 	break;
2211*7c568831SAndroid Build Coastguard Worker     default:
2212*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathIsNaN(number)) {
2213*7c568831SAndroid Build Coastguard Worker 	    if (buffersize > (int)sizeof("NaN"))
2214*7c568831SAndroid Build Coastguard Worker 		snprintf(buffer, buffersize, "NaN");
2215*7c568831SAndroid Build Coastguard Worker 	} else if (number == 0) {
2216*7c568831SAndroid Build Coastguard Worker             /* Omit sign for negative zero. */
2217*7c568831SAndroid Build Coastguard Worker 	    snprintf(buffer, buffersize, "0");
2218*7c568831SAndroid Build Coastguard Worker 	} else if ((number > INT_MIN) && (number < INT_MAX) &&
2219*7c568831SAndroid Build Coastguard Worker                    (number == (int) number)) {
2220*7c568831SAndroid Build Coastguard Worker 	    char work[30];
2221*7c568831SAndroid Build Coastguard Worker 	    char *ptr, *cur;
2222*7c568831SAndroid Build Coastguard Worker 	    int value = (int) number;
2223*7c568831SAndroid Build Coastguard Worker 
2224*7c568831SAndroid Build Coastguard Worker             ptr = &buffer[0];
2225*7c568831SAndroid Build Coastguard Worker 	    if (value == 0) {
2226*7c568831SAndroid Build Coastguard Worker 		*ptr++ = '0';
2227*7c568831SAndroid Build Coastguard Worker 	    } else {
2228*7c568831SAndroid Build Coastguard Worker 		snprintf(work, 29, "%d", value);
2229*7c568831SAndroid Build Coastguard Worker 		cur = &work[0];
2230*7c568831SAndroid Build Coastguard Worker 		while ((*cur) && (ptr - buffer < buffersize)) {
2231*7c568831SAndroid Build Coastguard Worker 		    *ptr++ = *cur++;
2232*7c568831SAndroid Build Coastguard Worker 		}
2233*7c568831SAndroid Build Coastguard Worker 	    }
2234*7c568831SAndroid Build Coastguard Worker 	    if (ptr - buffer < buffersize) {
2235*7c568831SAndroid Build Coastguard Worker 		*ptr = 0;
2236*7c568831SAndroid Build Coastguard Worker 	    } else if (buffersize > 0) {
2237*7c568831SAndroid Build Coastguard Worker 		ptr--;
2238*7c568831SAndroid Build Coastguard Worker 		*ptr = 0;
2239*7c568831SAndroid Build Coastguard Worker 	    }
2240*7c568831SAndroid Build Coastguard Worker 	} else {
2241*7c568831SAndroid Build Coastguard Worker 	    /*
2242*7c568831SAndroid Build Coastguard Worker 	      For the dimension of work,
2243*7c568831SAndroid Build Coastguard Worker 	          DBL_DIG is number of significant digits
2244*7c568831SAndroid Build Coastguard Worker 		  EXPONENT is only needed for "scientific notation"
2245*7c568831SAndroid Build Coastguard Worker 	          3 is sign, decimal point, and terminating zero
2246*7c568831SAndroid Build Coastguard Worker 		  LOWER_DOUBLE_EXP is max number of leading zeroes in fraction
2247*7c568831SAndroid Build Coastguard Worker 	      Note that this dimension is slightly (a few characters)
2248*7c568831SAndroid Build Coastguard Worker 	      larger than actually necessary.
2249*7c568831SAndroid Build Coastguard Worker 	    */
2250*7c568831SAndroid Build Coastguard Worker 	    char work[DBL_DIG + EXPONENT_DIGITS + 3 + LOWER_DOUBLE_EXP];
2251*7c568831SAndroid Build Coastguard Worker 	    int integer_place, fraction_place;
2252*7c568831SAndroid Build Coastguard Worker 	    char *ptr;
2253*7c568831SAndroid Build Coastguard Worker 	    char *after_fraction;
2254*7c568831SAndroid Build Coastguard Worker 	    double absolute_value;
2255*7c568831SAndroid Build Coastguard Worker 	    int size;
2256*7c568831SAndroid Build Coastguard Worker 
2257*7c568831SAndroid Build Coastguard Worker 	    absolute_value = fabs(number);
2258*7c568831SAndroid Build Coastguard Worker 
2259*7c568831SAndroid Build Coastguard Worker 	    /*
2260*7c568831SAndroid Build Coastguard Worker 	     * First choose format - scientific or regular floating point.
2261*7c568831SAndroid Build Coastguard Worker 	     * In either case, result is in work, and after_fraction points
2262*7c568831SAndroid Build Coastguard Worker 	     * just past the fractional part.
2263*7c568831SAndroid Build Coastguard Worker 	    */
2264*7c568831SAndroid Build Coastguard Worker 	    if ( ((absolute_value > UPPER_DOUBLE) ||
2265*7c568831SAndroid Build Coastguard Worker 		  (absolute_value < LOWER_DOUBLE)) &&
2266*7c568831SAndroid Build Coastguard Worker 		 (absolute_value != 0.0) ) {
2267*7c568831SAndroid Build Coastguard Worker 		/* Use scientific notation */
2268*7c568831SAndroid Build Coastguard Worker 		integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
2269*7c568831SAndroid Build Coastguard Worker 		fraction_place = DBL_DIG - 1;
2270*7c568831SAndroid Build Coastguard Worker 		size = snprintf(work, sizeof(work),"%*.*e",
2271*7c568831SAndroid Build Coastguard Worker 			 integer_place, fraction_place, number);
2272*7c568831SAndroid Build Coastguard Worker 		while ((size > 0) && (work[size] != 'e')) size--;
2273*7c568831SAndroid Build Coastguard Worker 
2274*7c568831SAndroid Build Coastguard Worker 	    }
2275*7c568831SAndroid Build Coastguard Worker 	    else {
2276*7c568831SAndroid Build Coastguard Worker 		/* Use regular notation */
2277*7c568831SAndroid Build Coastguard Worker 		if (absolute_value > 0.0) {
2278*7c568831SAndroid Build Coastguard Worker 		    integer_place = (int)log10(absolute_value);
2279*7c568831SAndroid Build Coastguard Worker 		    if (integer_place > 0)
2280*7c568831SAndroid Build Coastguard Worker 		        fraction_place = DBL_DIG - integer_place - 1;
2281*7c568831SAndroid Build Coastguard Worker 		    else
2282*7c568831SAndroid Build Coastguard Worker 		        fraction_place = DBL_DIG - integer_place;
2283*7c568831SAndroid Build Coastguard Worker 		} else {
2284*7c568831SAndroid Build Coastguard Worker 		    fraction_place = 1;
2285*7c568831SAndroid Build Coastguard Worker 		}
2286*7c568831SAndroid Build Coastguard Worker 		size = snprintf(work, sizeof(work), "%0.*f",
2287*7c568831SAndroid Build Coastguard Worker 				fraction_place, number);
2288*7c568831SAndroid Build Coastguard Worker 	    }
2289*7c568831SAndroid Build Coastguard Worker 
2290*7c568831SAndroid Build Coastguard Worker 	    /* Remove leading spaces sometimes inserted by snprintf */
2291*7c568831SAndroid Build Coastguard Worker 	    while (work[0] == ' ') {
2292*7c568831SAndroid Build Coastguard Worker 	        for (ptr = &work[0];(ptr[0] = ptr[1]);ptr++);
2293*7c568831SAndroid Build Coastguard Worker 		size--;
2294*7c568831SAndroid Build Coastguard Worker 	    }
2295*7c568831SAndroid Build Coastguard Worker 
2296*7c568831SAndroid Build Coastguard Worker 	    /* Remove fractional trailing zeroes */
2297*7c568831SAndroid Build Coastguard Worker 	    after_fraction = work + size;
2298*7c568831SAndroid Build Coastguard Worker 	    ptr = after_fraction;
2299*7c568831SAndroid Build Coastguard Worker 	    while (*(--ptr) == '0')
2300*7c568831SAndroid Build Coastguard Worker 		;
2301*7c568831SAndroid Build Coastguard Worker 	    if (*ptr != '.')
2302*7c568831SAndroid Build Coastguard Worker 	        ptr++;
2303*7c568831SAndroid Build Coastguard Worker 	    while ((*ptr++ = *after_fraction++) != 0);
2304*7c568831SAndroid Build Coastguard Worker 
2305*7c568831SAndroid Build Coastguard Worker 	    /* Finally copy result back to caller */
2306*7c568831SAndroid Build Coastguard Worker 	    size = strlen(work) + 1;
2307*7c568831SAndroid Build Coastguard Worker 	    if (size > buffersize) {
2308*7c568831SAndroid Build Coastguard Worker 		work[buffersize - 1] = 0;
2309*7c568831SAndroid Build Coastguard Worker 		size = buffersize;
2310*7c568831SAndroid Build Coastguard Worker 	    }
2311*7c568831SAndroid Build Coastguard Worker 	    memmove(buffer, work, size);
2312*7c568831SAndroid Build Coastguard Worker 	}
2313*7c568831SAndroid Build Coastguard Worker 	break;
2314*7c568831SAndroid Build Coastguard Worker     }
2315*7c568831SAndroid Build Coastguard Worker }
2316*7c568831SAndroid Build Coastguard Worker 
2317*7c568831SAndroid Build Coastguard Worker 
2318*7c568831SAndroid Build Coastguard Worker /************************************************************************
2319*7c568831SAndroid Build Coastguard Worker  *									*
2320*7c568831SAndroid Build Coastguard Worker  *			Routines to handle NodeSets			*
2321*7c568831SAndroid Build Coastguard Worker  *									*
2322*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
2323*7c568831SAndroid Build Coastguard Worker 
2324*7c568831SAndroid Build Coastguard Worker /**
2325*7c568831SAndroid Build Coastguard Worker  * xmlXPathOrderDocElems:
2326*7c568831SAndroid Build Coastguard Worker  * @doc:  an input document
2327*7c568831SAndroid Build Coastguard Worker  *
2328*7c568831SAndroid Build Coastguard Worker  * Call this routine to speed up XPath computation on static documents.
2329*7c568831SAndroid Build Coastguard Worker  * This stamps all the element nodes with the document order
2330*7c568831SAndroid Build Coastguard Worker  * Like for line information, the order is kept in the element->content
2331*7c568831SAndroid Build Coastguard Worker  * field, the value stored is actually - the node number (starting at -1)
2332*7c568831SAndroid Build Coastguard Worker  * to be able to differentiate from line numbers.
2333*7c568831SAndroid Build Coastguard Worker  *
2334*7c568831SAndroid Build Coastguard Worker  * Returns the number of elements found in the document or -1 in case
2335*7c568831SAndroid Build Coastguard Worker  *    of error.
2336*7c568831SAndroid Build Coastguard Worker  */
2337*7c568831SAndroid Build Coastguard Worker long
xmlXPathOrderDocElems(xmlDocPtr doc)2338*7c568831SAndroid Build Coastguard Worker xmlXPathOrderDocElems(xmlDocPtr doc) {
2339*7c568831SAndroid Build Coastguard Worker     ptrdiff_t count = 0;
2340*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
2341*7c568831SAndroid Build Coastguard Worker 
2342*7c568831SAndroid Build Coastguard Worker     if (doc == NULL)
2343*7c568831SAndroid Build Coastguard Worker 	return(-1);
2344*7c568831SAndroid Build Coastguard Worker     cur = doc->children;
2345*7c568831SAndroid Build Coastguard Worker     while (cur != NULL) {
2346*7c568831SAndroid Build Coastguard Worker 	if (cur->type == XML_ELEMENT_NODE) {
2347*7c568831SAndroid Build Coastguard Worker 	    cur->content = (void *) (-(++count));
2348*7c568831SAndroid Build Coastguard Worker 	    if (cur->children != NULL) {
2349*7c568831SAndroid Build Coastguard Worker 		cur = cur->children;
2350*7c568831SAndroid Build Coastguard Worker 		continue;
2351*7c568831SAndroid Build Coastguard Worker 	    }
2352*7c568831SAndroid Build Coastguard Worker 	}
2353*7c568831SAndroid Build Coastguard Worker 	if (cur->next != NULL) {
2354*7c568831SAndroid Build Coastguard Worker 	    cur = cur->next;
2355*7c568831SAndroid Build Coastguard Worker 	    continue;
2356*7c568831SAndroid Build Coastguard Worker 	}
2357*7c568831SAndroid Build Coastguard Worker 	do {
2358*7c568831SAndroid Build Coastguard Worker 	    cur = cur->parent;
2359*7c568831SAndroid Build Coastguard Worker 	    if (cur == NULL)
2360*7c568831SAndroid Build Coastguard Worker 		break;
2361*7c568831SAndroid Build Coastguard Worker 	    if (cur == (xmlNodePtr) doc) {
2362*7c568831SAndroid Build Coastguard Worker 		cur = NULL;
2363*7c568831SAndroid Build Coastguard Worker 		break;
2364*7c568831SAndroid Build Coastguard Worker 	    }
2365*7c568831SAndroid Build Coastguard Worker 	    if (cur->next != NULL) {
2366*7c568831SAndroid Build Coastguard Worker 		cur = cur->next;
2367*7c568831SAndroid Build Coastguard Worker 		break;
2368*7c568831SAndroid Build Coastguard Worker 	    }
2369*7c568831SAndroid Build Coastguard Worker 	} while (cur != NULL);
2370*7c568831SAndroid Build Coastguard Worker     }
2371*7c568831SAndroid Build Coastguard Worker     return(count);
2372*7c568831SAndroid Build Coastguard Worker }
2373*7c568831SAndroid Build Coastguard Worker 
2374*7c568831SAndroid Build Coastguard Worker /**
2375*7c568831SAndroid Build Coastguard Worker  * xmlXPathCmpNodes:
2376*7c568831SAndroid Build Coastguard Worker  * @node1:  the first node
2377*7c568831SAndroid Build Coastguard Worker  * @node2:  the second node
2378*7c568831SAndroid Build Coastguard Worker  *
2379*7c568831SAndroid Build Coastguard Worker  * Compare two nodes w.r.t document order
2380*7c568831SAndroid Build Coastguard Worker  *
2381*7c568831SAndroid Build Coastguard Worker  * Returns -2 in case of error 1 if first point < second point, 0 if
2382*7c568831SAndroid Build Coastguard Worker  *         it's the same node, -1 otherwise
2383*7c568831SAndroid Build Coastguard Worker  */
2384*7c568831SAndroid Build Coastguard Worker int
xmlXPathCmpNodes(xmlNodePtr node1,xmlNodePtr node2)2385*7c568831SAndroid Build Coastguard Worker xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
2386*7c568831SAndroid Build Coastguard Worker     int depth1, depth2;
2387*7c568831SAndroid Build Coastguard Worker     int attr1 = 0, attr2 = 0;
2388*7c568831SAndroid Build Coastguard Worker     xmlNodePtr attrNode1 = NULL, attrNode2 = NULL;
2389*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur, root;
2390*7c568831SAndroid Build Coastguard Worker 
2391*7c568831SAndroid Build Coastguard Worker     if ((node1 == NULL) || (node2 == NULL))
2392*7c568831SAndroid Build Coastguard Worker 	return(-2);
2393*7c568831SAndroid Build Coastguard Worker     /*
2394*7c568831SAndroid Build Coastguard Worker      * a couple of optimizations which will avoid computations in most cases
2395*7c568831SAndroid Build Coastguard Worker      */
2396*7c568831SAndroid Build Coastguard Worker     if (node1 == node2)		/* trivial case */
2397*7c568831SAndroid Build Coastguard Worker 	return(0);
2398*7c568831SAndroid Build Coastguard Worker     if (node1->type == XML_ATTRIBUTE_NODE) {
2399*7c568831SAndroid Build Coastguard Worker 	attr1 = 1;
2400*7c568831SAndroid Build Coastguard Worker 	attrNode1 = node1;
2401*7c568831SAndroid Build Coastguard Worker 	node1 = node1->parent;
2402*7c568831SAndroid Build Coastguard Worker     }
2403*7c568831SAndroid Build Coastguard Worker     if (node2->type == XML_ATTRIBUTE_NODE) {
2404*7c568831SAndroid Build Coastguard Worker 	attr2 = 1;
2405*7c568831SAndroid Build Coastguard Worker 	attrNode2 = node2;
2406*7c568831SAndroid Build Coastguard Worker 	node2 = node2->parent;
2407*7c568831SAndroid Build Coastguard Worker     }
2408*7c568831SAndroid Build Coastguard Worker     if (node1 == node2) {
2409*7c568831SAndroid Build Coastguard Worker 	if (attr1 == attr2) {
2410*7c568831SAndroid Build Coastguard Worker 	    /* not required, but we keep attributes in order */
2411*7c568831SAndroid Build Coastguard Worker 	    if (attr1 != 0) {
2412*7c568831SAndroid Build Coastguard Worker 	        cur = attrNode2->prev;
2413*7c568831SAndroid Build Coastguard Worker 		while (cur != NULL) {
2414*7c568831SAndroid Build Coastguard Worker 		    if (cur == attrNode1)
2415*7c568831SAndroid Build Coastguard Worker 		        return (1);
2416*7c568831SAndroid Build Coastguard Worker 		    cur = cur->prev;
2417*7c568831SAndroid Build Coastguard Worker 		}
2418*7c568831SAndroid Build Coastguard Worker 		return (-1);
2419*7c568831SAndroid Build Coastguard Worker 	    }
2420*7c568831SAndroid Build Coastguard Worker 	    return(0);
2421*7c568831SAndroid Build Coastguard Worker 	}
2422*7c568831SAndroid Build Coastguard Worker 	if (attr2 == 1)
2423*7c568831SAndroid Build Coastguard Worker 	    return(1);
2424*7c568831SAndroid Build Coastguard Worker 	return(-1);
2425*7c568831SAndroid Build Coastguard Worker     }
2426*7c568831SAndroid Build Coastguard Worker     if ((node1->type == XML_NAMESPACE_DECL) ||
2427*7c568831SAndroid Build Coastguard Worker         (node2->type == XML_NAMESPACE_DECL))
2428*7c568831SAndroid Build Coastguard Worker 	return(1);
2429*7c568831SAndroid Build Coastguard Worker     if (node1 == node2->prev)
2430*7c568831SAndroid Build Coastguard Worker 	return(1);
2431*7c568831SAndroid Build Coastguard Worker     if (node1 == node2->next)
2432*7c568831SAndroid Build Coastguard Worker 	return(-1);
2433*7c568831SAndroid Build Coastguard Worker 
2434*7c568831SAndroid Build Coastguard Worker     /*
2435*7c568831SAndroid Build Coastguard Worker      * Speedup using document order if available.
2436*7c568831SAndroid Build Coastguard Worker      */
2437*7c568831SAndroid Build Coastguard Worker     if ((node1->type == XML_ELEMENT_NODE) &&
2438*7c568831SAndroid Build Coastguard Worker 	(node2->type == XML_ELEMENT_NODE) &&
2439*7c568831SAndroid Build Coastguard Worker 	(0 > (ptrdiff_t) node1->content) &&
2440*7c568831SAndroid Build Coastguard Worker 	(0 > (ptrdiff_t) node2->content) &&
2441*7c568831SAndroid Build Coastguard Worker 	(node1->doc == node2->doc)) {
2442*7c568831SAndroid Build Coastguard Worker 	ptrdiff_t l1, l2;
2443*7c568831SAndroid Build Coastguard Worker 
2444*7c568831SAndroid Build Coastguard Worker 	l1 = -((ptrdiff_t) node1->content);
2445*7c568831SAndroid Build Coastguard Worker 	l2 = -((ptrdiff_t) node2->content);
2446*7c568831SAndroid Build Coastguard Worker 	if (l1 < l2)
2447*7c568831SAndroid Build Coastguard Worker 	    return(1);
2448*7c568831SAndroid Build Coastguard Worker 	if (l1 > l2)
2449*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2450*7c568831SAndroid Build Coastguard Worker     }
2451*7c568831SAndroid Build Coastguard Worker 
2452*7c568831SAndroid Build Coastguard Worker     /*
2453*7c568831SAndroid Build Coastguard Worker      * compute depth to root
2454*7c568831SAndroid Build Coastguard Worker      */
2455*7c568831SAndroid Build Coastguard Worker     for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
2456*7c568831SAndroid Build Coastguard Worker 	if (cur->parent == node1)
2457*7c568831SAndroid Build Coastguard Worker 	    return(1);
2458*7c568831SAndroid Build Coastguard Worker 	depth2++;
2459*7c568831SAndroid Build Coastguard Worker     }
2460*7c568831SAndroid Build Coastguard Worker     root = cur;
2461*7c568831SAndroid Build Coastguard Worker     for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
2462*7c568831SAndroid Build Coastguard Worker 	if (cur->parent == node2)
2463*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2464*7c568831SAndroid Build Coastguard Worker 	depth1++;
2465*7c568831SAndroid Build Coastguard Worker     }
2466*7c568831SAndroid Build Coastguard Worker     /*
2467*7c568831SAndroid Build Coastguard Worker      * Distinct document (or distinct entities :-( ) case.
2468*7c568831SAndroid Build Coastguard Worker      */
2469*7c568831SAndroid Build Coastguard Worker     if (root != cur) {
2470*7c568831SAndroid Build Coastguard Worker 	return(-2);
2471*7c568831SAndroid Build Coastguard Worker     }
2472*7c568831SAndroid Build Coastguard Worker     /*
2473*7c568831SAndroid Build Coastguard Worker      * get the nearest common ancestor.
2474*7c568831SAndroid Build Coastguard Worker      */
2475*7c568831SAndroid Build Coastguard Worker     while (depth1 > depth2) {
2476*7c568831SAndroid Build Coastguard Worker 	depth1--;
2477*7c568831SAndroid Build Coastguard Worker 	node1 = node1->parent;
2478*7c568831SAndroid Build Coastguard Worker     }
2479*7c568831SAndroid Build Coastguard Worker     while (depth2 > depth1) {
2480*7c568831SAndroid Build Coastguard Worker 	depth2--;
2481*7c568831SAndroid Build Coastguard Worker 	node2 = node2->parent;
2482*7c568831SAndroid Build Coastguard Worker     }
2483*7c568831SAndroid Build Coastguard Worker     while (node1->parent != node2->parent) {
2484*7c568831SAndroid Build Coastguard Worker 	node1 = node1->parent;
2485*7c568831SAndroid Build Coastguard Worker 	node2 = node2->parent;
2486*7c568831SAndroid Build Coastguard Worker 	/* should not happen but just in case ... */
2487*7c568831SAndroid Build Coastguard Worker 	if ((node1 == NULL) || (node2 == NULL))
2488*7c568831SAndroid Build Coastguard Worker 	    return(-2);
2489*7c568831SAndroid Build Coastguard Worker     }
2490*7c568831SAndroid Build Coastguard Worker     /*
2491*7c568831SAndroid Build Coastguard Worker      * Find who's first.
2492*7c568831SAndroid Build Coastguard Worker      */
2493*7c568831SAndroid Build Coastguard Worker     if (node1 == node2->prev)
2494*7c568831SAndroid Build Coastguard Worker 	return(1);
2495*7c568831SAndroid Build Coastguard Worker     if (node1 == node2->next)
2496*7c568831SAndroid Build Coastguard Worker 	return(-1);
2497*7c568831SAndroid Build Coastguard Worker     /*
2498*7c568831SAndroid Build Coastguard Worker      * Speedup using document order if available.
2499*7c568831SAndroid Build Coastguard Worker      */
2500*7c568831SAndroid Build Coastguard Worker     if ((node1->type == XML_ELEMENT_NODE) &&
2501*7c568831SAndroid Build Coastguard Worker 	(node2->type == XML_ELEMENT_NODE) &&
2502*7c568831SAndroid Build Coastguard Worker 	(0 > (ptrdiff_t) node1->content) &&
2503*7c568831SAndroid Build Coastguard Worker 	(0 > (ptrdiff_t) node2->content) &&
2504*7c568831SAndroid Build Coastguard Worker 	(node1->doc == node2->doc)) {
2505*7c568831SAndroid Build Coastguard Worker 	ptrdiff_t l1, l2;
2506*7c568831SAndroid Build Coastguard Worker 
2507*7c568831SAndroid Build Coastguard Worker 	l1 = -((ptrdiff_t) node1->content);
2508*7c568831SAndroid Build Coastguard Worker 	l2 = -((ptrdiff_t) node2->content);
2509*7c568831SAndroid Build Coastguard Worker 	if (l1 < l2)
2510*7c568831SAndroid Build Coastguard Worker 	    return(1);
2511*7c568831SAndroid Build Coastguard Worker 	if (l1 > l2)
2512*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2513*7c568831SAndroid Build Coastguard Worker     }
2514*7c568831SAndroid Build Coastguard Worker 
2515*7c568831SAndroid Build Coastguard Worker     for (cur = node1->next;cur != NULL;cur = cur->next)
2516*7c568831SAndroid Build Coastguard Worker 	if (cur == node2)
2517*7c568831SAndroid Build Coastguard Worker 	    return(1);
2518*7c568831SAndroid Build Coastguard Worker     return(-1); /* assume there is no sibling list corruption */
2519*7c568831SAndroid Build Coastguard Worker }
2520*7c568831SAndroid Build Coastguard Worker 
2521*7c568831SAndroid Build Coastguard Worker /**
2522*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetSort:
2523*7c568831SAndroid Build Coastguard Worker  * @set:  the node set
2524*7c568831SAndroid Build Coastguard Worker  *
2525*7c568831SAndroid Build Coastguard Worker  * Sort the node set in document order
2526*7c568831SAndroid Build Coastguard Worker  */
2527*7c568831SAndroid Build Coastguard Worker void
xmlXPathNodeSetSort(xmlNodeSetPtr set)2528*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(xmlNodeSetPtr set) {
2529*7c568831SAndroid Build Coastguard Worker #ifndef WITH_TIM_SORT
2530*7c568831SAndroid Build Coastguard Worker     int i, j, incr, len;
2531*7c568831SAndroid Build Coastguard Worker     xmlNodePtr tmp;
2532*7c568831SAndroid Build Coastguard Worker #endif
2533*7c568831SAndroid Build Coastguard Worker 
2534*7c568831SAndroid Build Coastguard Worker     if (set == NULL)
2535*7c568831SAndroid Build Coastguard Worker 	return;
2536*7c568831SAndroid Build Coastguard Worker 
2537*7c568831SAndroid Build Coastguard Worker #ifndef WITH_TIM_SORT
2538*7c568831SAndroid Build Coastguard Worker     /*
2539*7c568831SAndroid Build Coastguard Worker      * Use the old Shell's sort implementation to sort the node-set
2540*7c568831SAndroid Build Coastguard Worker      * Timsort ought to be quite faster
2541*7c568831SAndroid Build Coastguard Worker      */
2542*7c568831SAndroid Build Coastguard Worker     len = set->nodeNr;
2543*7c568831SAndroid Build Coastguard Worker     for (incr = len / 2; incr > 0; incr /= 2) {
2544*7c568831SAndroid Build Coastguard Worker 	for (i = incr; i < len; i++) {
2545*7c568831SAndroid Build Coastguard Worker 	    j = i - incr;
2546*7c568831SAndroid Build Coastguard Worker 	    while (j >= 0) {
2547*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
2548*7c568831SAndroid Build Coastguard Worker 		if (xmlXPathCmpNodesExt(set->nodeTab[j],
2549*7c568831SAndroid Build Coastguard Worker 			set->nodeTab[j + incr]) == -1)
2550*7c568831SAndroid Build Coastguard Worker #else
2551*7c568831SAndroid Build Coastguard Worker 		if (xmlXPathCmpNodes(set->nodeTab[j],
2552*7c568831SAndroid Build Coastguard Worker 			set->nodeTab[j + incr]) == -1)
2553*7c568831SAndroid Build Coastguard Worker #endif
2554*7c568831SAndroid Build Coastguard Worker 		{
2555*7c568831SAndroid Build Coastguard Worker 		    tmp = set->nodeTab[j];
2556*7c568831SAndroid Build Coastguard Worker 		    set->nodeTab[j] = set->nodeTab[j + incr];
2557*7c568831SAndroid Build Coastguard Worker 		    set->nodeTab[j + incr] = tmp;
2558*7c568831SAndroid Build Coastguard Worker 		    j -= incr;
2559*7c568831SAndroid Build Coastguard Worker 		} else
2560*7c568831SAndroid Build Coastguard Worker 		    break;
2561*7c568831SAndroid Build Coastguard Worker 	    }
2562*7c568831SAndroid Build Coastguard Worker 	}
2563*7c568831SAndroid Build Coastguard Worker     }
2564*7c568831SAndroid Build Coastguard Worker #else /* WITH_TIM_SORT */
2565*7c568831SAndroid Build Coastguard Worker     libxml_domnode_tim_sort(set->nodeTab, set->nodeNr);
2566*7c568831SAndroid Build Coastguard Worker #endif /* WITH_TIM_SORT */
2567*7c568831SAndroid Build Coastguard Worker }
2568*7c568831SAndroid Build Coastguard Worker 
2569*7c568831SAndroid Build Coastguard Worker #define XML_NODESET_DEFAULT	10
2570*7c568831SAndroid Build Coastguard Worker /**
2571*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetDupNs:
2572*7c568831SAndroid Build Coastguard Worker  * @node:  the parent node of the namespace XPath node
2573*7c568831SAndroid Build Coastguard Worker  * @ns:  the libxml namespace declaration node.
2574*7c568831SAndroid Build Coastguard Worker  *
2575*7c568831SAndroid Build Coastguard Worker  * Namespace node in libxml don't match the XPath semantic. In a node set
2576*7c568831SAndroid Build Coastguard Worker  * the namespace nodes are duplicated and the next pointer is set to the
2577*7c568831SAndroid Build Coastguard Worker  * parent node in the XPath semantic.
2578*7c568831SAndroid Build Coastguard Worker  *
2579*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
2580*7c568831SAndroid Build Coastguard Worker  */
2581*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNodeSetDupNs(xmlNodePtr node,xmlNsPtr ns)2582*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
2583*7c568831SAndroid Build Coastguard Worker     xmlNsPtr cur;
2584*7c568831SAndroid Build Coastguard Worker 
2585*7c568831SAndroid Build Coastguard Worker     if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
2586*7c568831SAndroid Build Coastguard Worker 	return(NULL);
2587*7c568831SAndroid Build Coastguard Worker     if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
2588*7c568831SAndroid Build Coastguard Worker 	return((xmlNodePtr) ns);
2589*7c568831SAndroid Build Coastguard Worker 
2590*7c568831SAndroid Build Coastguard Worker     /*
2591*7c568831SAndroid Build Coastguard Worker      * Allocate a new Namespace and fill the fields.
2592*7c568831SAndroid Build Coastguard Worker      */
2593*7c568831SAndroid Build Coastguard Worker     cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
2594*7c568831SAndroid Build Coastguard Worker     if (cur == NULL)
2595*7c568831SAndroid Build Coastguard Worker 	return(NULL);
2596*7c568831SAndroid Build Coastguard Worker     memset(cur, 0, sizeof(xmlNs));
2597*7c568831SAndroid Build Coastguard Worker     cur->type = XML_NAMESPACE_DECL;
2598*7c568831SAndroid Build Coastguard Worker     if (ns->href != NULL) {
2599*7c568831SAndroid Build Coastguard Worker 	cur->href = xmlStrdup(ns->href);
2600*7c568831SAndroid Build Coastguard Worker         if (cur->href == NULL) {
2601*7c568831SAndroid Build Coastguard Worker             xmlFree(cur);
2602*7c568831SAndroid Build Coastguard Worker             return(NULL);
2603*7c568831SAndroid Build Coastguard Worker         }
2604*7c568831SAndroid Build Coastguard Worker     }
2605*7c568831SAndroid Build Coastguard Worker     if (ns->prefix != NULL) {
2606*7c568831SAndroid Build Coastguard Worker 	cur->prefix = xmlStrdup(ns->prefix);
2607*7c568831SAndroid Build Coastguard Worker         if (cur->prefix == NULL) {
2608*7c568831SAndroid Build Coastguard Worker             xmlFree((xmlChar *) cur->href);
2609*7c568831SAndroid Build Coastguard Worker             xmlFree(cur);
2610*7c568831SAndroid Build Coastguard Worker             return(NULL);
2611*7c568831SAndroid Build Coastguard Worker         }
2612*7c568831SAndroid Build Coastguard Worker     }
2613*7c568831SAndroid Build Coastguard Worker     cur->next = (xmlNsPtr) node;
2614*7c568831SAndroid Build Coastguard Worker     return((xmlNodePtr) cur);
2615*7c568831SAndroid Build Coastguard Worker }
2616*7c568831SAndroid Build Coastguard Worker 
2617*7c568831SAndroid Build Coastguard Worker /**
2618*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetFreeNs:
2619*7c568831SAndroid Build Coastguard Worker  * @ns:  the XPath namespace node found in a nodeset.
2620*7c568831SAndroid Build Coastguard Worker  *
2621*7c568831SAndroid Build Coastguard Worker  * Namespace nodes in libxml don't match the XPath semantic. In a node set
2622*7c568831SAndroid Build Coastguard Worker  * the namespace nodes are duplicated and the next pointer is set to the
2623*7c568831SAndroid Build Coastguard Worker  * parent node in the XPath semantic. Check if such a node needs to be freed
2624*7c568831SAndroid Build Coastguard Worker  */
2625*7c568831SAndroid Build Coastguard Worker void
xmlXPathNodeSetFreeNs(xmlNsPtr ns)2626*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs(xmlNsPtr ns) {
2627*7c568831SAndroid Build Coastguard Worker     if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
2628*7c568831SAndroid Build Coastguard Worker 	return;
2629*7c568831SAndroid Build Coastguard Worker 
2630*7c568831SAndroid Build Coastguard Worker     if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) {
2631*7c568831SAndroid Build Coastguard Worker 	if (ns->href != NULL)
2632*7c568831SAndroid Build Coastguard Worker 	    xmlFree((xmlChar *)ns->href);
2633*7c568831SAndroid Build Coastguard Worker 	if (ns->prefix != NULL)
2634*7c568831SAndroid Build Coastguard Worker 	    xmlFree((xmlChar *)ns->prefix);
2635*7c568831SAndroid Build Coastguard Worker 	xmlFree(ns);
2636*7c568831SAndroid Build Coastguard Worker     }
2637*7c568831SAndroid Build Coastguard Worker }
2638*7c568831SAndroid Build Coastguard Worker 
2639*7c568831SAndroid Build Coastguard Worker /**
2640*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetCreate:
2641*7c568831SAndroid Build Coastguard Worker  * @val:  an initial xmlNodePtr, or NULL
2642*7c568831SAndroid Build Coastguard Worker  *
2643*7c568831SAndroid Build Coastguard Worker  * Create a new xmlNodeSetPtr of type double and of value @val
2644*7c568831SAndroid Build Coastguard Worker  *
2645*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
2646*7c568831SAndroid Build Coastguard Worker  */
2647*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeSetCreate(xmlNodePtr val)2648*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetCreate(xmlNodePtr val) {
2649*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret;
2650*7c568831SAndroid Build Coastguard Worker 
2651*7c568831SAndroid Build Coastguard Worker     ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
2652*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
2653*7c568831SAndroid Build Coastguard Worker 	return(NULL);
2654*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlNodeSet));
2655*7c568831SAndroid Build Coastguard Worker     if (val != NULL) {
2656*7c568831SAndroid Build Coastguard Worker         ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2657*7c568831SAndroid Build Coastguard Worker 					     sizeof(xmlNodePtr));
2658*7c568831SAndroid Build Coastguard Worker 	if (ret->nodeTab == NULL) {
2659*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret);
2660*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
2661*7c568831SAndroid Build Coastguard Worker 	}
2662*7c568831SAndroid Build Coastguard Worker 	memset(ret->nodeTab, 0 ,
2663*7c568831SAndroid Build Coastguard Worker 	       XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2664*7c568831SAndroid Build Coastguard Worker         ret->nodeMax = XML_NODESET_DEFAULT;
2665*7c568831SAndroid Build Coastguard Worker 	if (val->type == XML_NAMESPACE_DECL) {
2666*7c568831SAndroid Build Coastguard Worker 	    xmlNsPtr ns = (xmlNsPtr) val;
2667*7c568831SAndroid Build Coastguard Worker             xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2668*7c568831SAndroid Build Coastguard Worker 
2669*7c568831SAndroid Build Coastguard Worker             if (nsNode == NULL) {
2670*7c568831SAndroid Build Coastguard Worker                 xmlXPathFreeNodeSet(ret);
2671*7c568831SAndroid Build Coastguard Worker                 return(NULL);
2672*7c568831SAndroid Build Coastguard Worker             }
2673*7c568831SAndroid Build Coastguard Worker 	    ret->nodeTab[ret->nodeNr++] = nsNode;
2674*7c568831SAndroid Build Coastguard Worker 	} else
2675*7c568831SAndroid Build Coastguard Worker 	    ret->nodeTab[ret->nodeNr++] = val;
2676*7c568831SAndroid Build Coastguard Worker     }
2677*7c568831SAndroid Build Coastguard Worker     return(ret);
2678*7c568831SAndroid Build Coastguard Worker }
2679*7c568831SAndroid Build Coastguard Worker 
2680*7c568831SAndroid Build Coastguard Worker /**
2681*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetContains:
2682*7c568831SAndroid Build Coastguard Worker  * @cur:  the node-set
2683*7c568831SAndroid Build Coastguard Worker  * @val:  the node
2684*7c568831SAndroid Build Coastguard Worker  *
2685*7c568831SAndroid Build Coastguard Worker  * checks whether @cur contains @val
2686*7c568831SAndroid Build Coastguard Worker  *
2687*7c568831SAndroid Build Coastguard Worker  * Returns true (1) if @cur contains @val, false (0) otherwise
2688*7c568831SAndroid Build Coastguard Worker  */
2689*7c568831SAndroid Build Coastguard Worker int
xmlXPathNodeSetContains(xmlNodeSetPtr cur,xmlNodePtr val)2690*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
2691*7c568831SAndroid Build Coastguard Worker     int i;
2692*7c568831SAndroid Build Coastguard Worker 
2693*7c568831SAndroid Build Coastguard Worker     if ((cur == NULL) || (val == NULL)) return(0);
2694*7c568831SAndroid Build Coastguard Worker     if (val->type == XML_NAMESPACE_DECL) {
2695*7c568831SAndroid Build Coastguard Worker 	for (i = 0; i < cur->nodeNr; i++) {
2696*7c568831SAndroid Build Coastguard Worker 	    if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2697*7c568831SAndroid Build Coastguard Worker 		xmlNsPtr ns1, ns2;
2698*7c568831SAndroid Build Coastguard Worker 
2699*7c568831SAndroid Build Coastguard Worker 		ns1 = (xmlNsPtr) val;
2700*7c568831SAndroid Build Coastguard Worker 		ns2 = (xmlNsPtr) cur->nodeTab[i];
2701*7c568831SAndroid Build Coastguard Worker 		if (ns1 == ns2)
2702*7c568831SAndroid Build Coastguard Worker 		    return(1);
2703*7c568831SAndroid Build Coastguard Worker 		if ((ns1->next != NULL) && (ns2->next == ns1->next) &&
2704*7c568831SAndroid Build Coastguard Worker 	            (xmlStrEqual(ns1->prefix, ns2->prefix)))
2705*7c568831SAndroid Build Coastguard Worker 		    return(1);
2706*7c568831SAndroid Build Coastguard Worker 	    }
2707*7c568831SAndroid Build Coastguard Worker 	}
2708*7c568831SAndroid Build Coastguard Worker     } else {
2709*7c568831SAndroid Build Coastguard Worker 	for (i = 0; i < cur->nodeNr; i++) {
2710*7c568831SAndroid Build Coastguard Worker 	    if (cur->nodeTab[i] == val)
2711*7c568831SAndroid Build Coastguard Worker 		return(1);
2712*7c568831SAndroid Build Coastguard Worker 	}
2713*7c568831SAndroid Build Coastguard Worker     }
2714*7c568831SAndroid Build Coastguard Worker     return(0);
2715*7c568831SAndroid Build Coastguard Worker }
2716*7c568831SAndroid Build Coastguard Worker 
2717*7c568831SAndroid Build Coastguard Worker /**
2718*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetAddNs:
2719*7c568831SAndroid Build Coastguard Worker  * @cur:  the initial node set
2720*7c568831SAndroid Build Coastguard Worker  * @node:  the hosting node
2721*7c568831SAndroid Build Coastguard Worker  * @ns:  a the namespace node
2722*7c568831SAndroid Build Coastguard Worker  *
2723*7c568831SAndroid Build Coastguard Worker  * add a new namespace node to an existing NodeSet
2724*7c568831SAndroid Build Coastguard Worker  *
2725*7c568831SAndroid Build Coastguard Worker  * Returns 0 in case of success and -1 in case of error
2726*7c568831SAndroid Build Coastguard Worker  */
2727*7c568831SAndroid Build Coastguard Worker int
xmlXPathNodeSetAddNs(xmlNodeSetPtr cur,xmlNodePtr node,xmlNsPtr ns)2728*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
2729*7c568831SAndroid Build Coastguard Worker     int i;
2730*7c568831SAndroid Build Coastguard Worker     xmlNodePtr nsNode;
2731*7c568831SAndroid Build Coastguard Worker 
2732*7c568831SAndroid Build Coastguard Worker     if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
2733*7c568831SAndroid Build Coastguard Worker         (ns->type != XML_NAMESPACE_DECL) ||
2734*7c568831SAndroid Build Coastguard Worker 	(node->type != XML_ELEMENT_NODE))
2735*7c568831SAndroid Build Coastguard Worker 	return(-1);
2736*7c568831SAndroid Build Coastguard Worker 
2737*7c568831SAndroid Build Coastguard Worker     /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2738*7c568831SAndroid Build Coastguard Worker     /*
2739*7c568831SAndroid Build Coastguard Worker      * prevent duplicates
2740*7c568831SAndroid Build Coastguard Worker      */
2741*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < cur->nodeNr;i++) {
2742*7c568831SAndroid Build Coastguard Worker         if ((cur->nodeTab[i] != NULL) &&
2743*7c568831SAndroid Build Coastguard Worker 	    (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
2744*7c568831SAndroid Build Coastguard Worker 	    (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
2745*7c568831SAndroid Build Coastguard Worker 	    (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
2746*7c568831SAndroid Build Coastguard Worker 	    return(0);
2747*7c568831SAndroid Build Coastguard Worker     }
2748*7c568831SAndroid Build Coastguard Worker 
2749*7c568831SAndroid Build Coastguard Worker     /*
2750*7c568831SAndroid Build Coastguard Worker      * grow the nodeTab if needed
2751*7c568831SAndroid Build Coastguard Worker      */
2752*7c568831SAndroid Build Coastguard Worker     if (cur->nodeMax == 0) {
2753*7c568831SAndroid Build Coastguard Worker         cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2754*7c568831SAndroid Build Coastguard Worker 					     sizeof(xmlNodePtr));
2755*7c568831SAndroid Build Coastguard Worker 	if (cur->nodeTab == NULL)
2756*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2757*7c568831SAndroid Build Coastguard Worker 	memset(cur->nodeTab, 0 ,
2758*7c568831SAndroid Build Coastguard Worker 	       XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2759*7c568831SAndroid Build Coastguard Worker         cur->nodeMax = XML_NODESET_DEFAULT;
2760*7c568831SAndroid Build Coastguard Worker     } else if (cur->nodeNr == cur->nodeMax) {
2761*7c568831SAndroid Build Coastguard Worker         xmlNodePtr *temp;
2762*7c568831SAndroid Build Coastguard Worker 
2763*7c568831SAndroid Build Coastguard Worker         if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2764*7c568831SAndroid Build Coastguard Worker             return(-1);
2765*7c568831SAndroid Build Coastguard Worker 	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2766*7c568831SAndroid Build Coastguard Worker 				      sizeof(xmlNodePtr));
2767*7c568831SAndroid Build Coastguard Worker 	if (temp == NULL)
2768*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2769*7c568831SAndroid Build Coastguard Worker         cur->nodeMax *= 2;
2770*7c568831SAndroid Build Coastguard Worker 	cur->nodeTab = temp;
2771*7c568831SAndroid Build Coastguard Worker     }
2772*7c568831SAndroid Build Coastguard Worker     nsNode = xmlXPathNodeSetDupNs(node, ns);
2773*7c568831SAndroid Build Coastguard Worker     if(nsNode == NULL)
2774*7c568831SAndroid Build Coastguard Worker         return(-1);
2775*7c568831SAndroid Build Coastguard Worker     cur->nodeTab[cur->nodeNr++] = nsNode;
2776*7c568831SAndroid Build Coastguard Worker     return(0);
2777*7c568831SAndroid Build Coastguard Worker }
2778*7c568831SAndroid Build Coastguard Worker 
2779*7c568831SAndroid Build Coastguard Worker /**
2780*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetAdd:
2781*7c568831SAndroid Build Coastguard Worker  * @cur:  the initial node set
2782*7c568831SAndroid Build Coastguard Worker  * @val:  a new xmlNodePtr
2783*7c568831SAndroid Build Coastguard Worker  *
2784*7c568831SAndroid Build Coastguard Worker  * add a new xmlNodePtr to an existing NodeSet
2785*7c568831SAndroid Build Coastguard Worker  *
2786*7c568831SAndroid Build Coastguard Worker  * Returns 0 in case of success, and -1 in case of error
2787*7c568831SAndroid Build Coastguard Worker  */
2788*7c568831SAndroid Build Coastguard Worker int
xmlXPathNodeSetAdd(xmlNodeSetPtr cur,xmlNodePtr val)2789*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
2790*7c568831SAndroid Build Coastguard Worker     int i;
2791*7c568831SAndroid Build Coastguard Worker 
2792*7c568831SAndroid Build Coastguard Worker     if ((cur == NULL) || (val == NULL)) return(-1);
2793*7c568831SAndroid Build Coastguard Worker 
2794*7c568831SAndroid Build Coastguard Worker     /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2795*7c568831SAndroid Build Coastguard Worker     /*
2796*7c568831SAndroid Build Coastguard Worker      * prevent duplicates
2797*7c568831SAndroid Build Coastguard Worker      */
2798*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < cur->nodeNr;i++)
2799*7c568831SAndroid Build Coastguard Worker         if (cur->nodeTab[i] == val) return(0);
2800*7c568831SAndroid Build Coastguard Worker 
2801*7c568831SAndroid Build Coastguard Worker     /*
2802*7c568831SAndroid Build Coastguard Worker      * grow the nodeTab if needed
2803*7c568831SAndroid Build Coastguard Worker      */
2804*7c568831SAndroid Build Coastguard Worker     if (cur->nodeMax == 0) {
2805*7c568831SAndroid Build Coastguard Worker         cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2806*7c568831SAndroid Build Coastguard Worker 					     sizeof(xmlNodePtr));
2807*7c568831SAndroid Build Coastguard Worker 	if (cur->nodeTab == NULL)
2808*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2809*7c568831SAndroid Build Coastguard Worker 	memset(cur->nodeTab, 0 ,
2810*7c568831SAndroid Build Coastguard Worker 	       XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2811*7c568831SAndroid Build Coastguard Worker         cur->nodeMax = XML_NODESET_DEFAULT;
2812*7c568831SAndroid Build Coastguard Worker     } else if (cur->nodeNr == cur->nodeMax) {
2813*7c568831SAndroid Build Coastguard Worker         xmlNodePtr *temp;
2814*7c568831SAndroid Build Coastguard Worker 
2815*7c568831SAndroid Build Coastguard Worker         if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2816*7c568831SAndroid Build Coastguard Worker             return(-1);
2817*7c568831SAndroid Build Coastguard Worker 	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2818*7c568831SAndroid Build Coastguard Worker 				      sizeof(xmlNodePtr));
2819*7c568831SAndroid Build Coastguard Worker 	if (temp == NULL)
2820*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2821*7c568831SAndroid Build Coastguard Worker         cur->nodeMax *= 2;
2822*7c568831SAndroid Build Coastguard Worker 	cur->nodeTab = temp;
2823*7c568831SAndroid Build Coastguard Worker     }
2824*7c568831SAndroid Build Coastguard Worker     if (val->type == XML_NAMESPACE_DECL) {
2825*7c568831SAndroid Build Coastguard Worker 	xmlNsPtr ns = (xmlNsPtr) val;
2826*7c568831SAndroid Build Coastguard Worker         xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2827*7c568831SAndroid Build Coastguard Worker 
2828*7c568831SAndroid Build Coastguard Worker         if (nsNode == NULL)
2829*7c568831SAndroid Build Coastguard Worker             return(-1);
2830*7c568831SAndroid Build Coastguard Worker 	cur->nodeTab[cur->nodeNr++] = nsNode;
2831*7c568831SAndroid Build Coastguard Worker     } else
2832*7c568831SAndroid Build Coastguard Worker 	cur->nodeTab[cur->nodeNr++] = val;
2833*7c568831SAndroid Build Coastguard Worker     return(0);
2834*7c568831SAndroid Build Coastguard Worker }
2835*7c568831SAndroid Build Coastguard Worker 
2836*7c568831SAndroid Build Coastguard Worker /**
2837*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetAddUnique:
2838*7c568831SAndroid Build Coastguard Worker  * @cur:  the initial node set
2839*7c568831SAndroid Build Coastguard Worker  * @val:  a new xmlNodePtr
2840*7c568831SAndroid Build Coastguard Worker  *
2841*7c568831SAndroid Build Coastguard Worker  * add a new xmlNodePtr to an existing NodeSet, optimized version
2842*7c568831SAndroid Build Coastguard Worker  * when we are sure the node is not already in the set.
2843*7c568831SAndroid Build Coastguard Worker  *
2844*7c568831SAndroid Build Coastguard Worker  * Returns 0 in case of success and -1 in case of failure
2845*7c568831SAndroid Build Coastguard Worker  */
2846*7c568831SAndroid Build Coastguard Worker int
xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur,xmlNodePtr val)2847*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
2848*7c568831SAndroid Build Coastguard Worker     if ((cur == NULL) || (val == NULL)) return(-1);
2849*7c568831SAndroid Build Coastguard Worker 
2850*7c568831SAndroid Build Coastguard Worker     /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2851*7c568831SAndroid Build Coastguard Worker     /*
2852*7c568831SAndroid Build Coastguard Worker      * grow the nodeTab if needed
2853*7c568831SAndroid Build Coastguard Worker      */
2854*7c568831SAndroid Build Coastguard Worker     if (cur->nodeMax == 0) {
2855*7c568831SAndroid Build Coastguard Worker         cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2856*7c568831SAndroid Build Coastguard Worker 					     sizeof(xmlNodePtr));
2857*7c568831SAndroid Build Coastguard Worker 	if (cur->nodeTab == NULL)
2858*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2859*7c568831SAndroid Build Coastguard Worker 	memset(cur->nodeTab, 0 ,
2860*7c568831SAndroid Build Coastguard Worker 	       XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2861*7c568831SAndroid Build Coastguard Worker         cur->nodeMax = XML_NODESET_DEFAULT;
2862*7c568831SAndroid Build Coastguard Worker     } else if (cur->nodeNr == cur->nodeMax) {
2863*7c568831SAndroid Build Coastguard Worker         xmlNodePtr *temp;
2864*7c568831SAndroid Build Coastguard Worker 
2865*7c568831SAndroid Build Coastguard Worker         if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2866*7c568831SAndroid Build Coastguard Worker             return(-1);
2867*7c568831SAndroid Build Coastguard Worker 	temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2868*7c568831SAndroid Build Coastguard Worker 				      sizeof(xmlNodePtr));
2869*7c568831SAndroid Build Coastguard Worker 	if (temp == NULL)
2870*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2871*7c568831SAndroid Build Coastguard Worker 	cur->nodeTab = temp;
2872*7c568831SAndroid Build Coastguard Worker         cur->nodeMax *= 2;
2873*7c568831SAndroid Build Coastguard Worker     }
2874*7c568831SAndroid Build Coastguard Worker     if (val->type == XML_NAMESPACE_DECL) {
2875*7c568831SAndroid Build Coastguard Worker 	xmlNsPtr ns = (xmlNsPtr) val;
2876*7c568831SAndroid Build Coastguard Worker         xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2877*7c568831SAndroid Build Coastguard Worker 
2878*7c568831SAndroid Build Coastguard Worker         if (nsNode == NULL)
2879*7c568831SAndroid Build Coastguard Worker             return(-1);
2880*7c568831SAndroid Build Coastguard Worker 	cur->nodeTab[cur->nodeNr++] = nsNode;
2881*7c568831SAndroid Build Coastguard Worker     } else
2882*7c568831SAndroid Build Coastguard Worker 	cur->nodeTab[cur->nodeNr++] = val;
2883*7c568831SAndroid Build Coastguard Worker     return(0);
2884*7c568831SAndroid Build Coastguard Worker }
2885*7c568831SAndroid Build Coastguard Worker 
2886*7c568831SAndroid Build Coastguard Worker /**
2887*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetMerge:
2888*7c568831SAndroid Build Coastguard Worker  * @val1:  the first NodeSet or NULL
2889*7c568831SAndroid Build Coastguard Worker  * @val2:  the second NodeSet
2890*7c568831SAndroid Build Coastguard Worker  *
2891*7c568831SAndroid Build Coastguard Worker  * Merges two nodesets, all nodes from @val2 are added to @val1
2892*7c568831SAndroid Build Coastguard Worker  * if @val1 is NULL, a new set is created and copied from @val2
2893*7c568831SAndroid Build Coastguard Worker  *
2894*7c568831SAndroid Build Coastguard Worker  * Returns @val1 once extended or NULL in case of error.
2895*7c568831SAndroid Build Coastguard Worker  *
2896*7c568831SAndroid Build Coastguard Worker  * Frees @val1 in case of error.
2897*7c568831SAndroid Build Coastguard Worker  */
2898*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeSetMerge(xmlNodeSetPtr val1,xmlNodeSetPtr val2)2899*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
2900*7c568831SAndroid Build Coastguard Worker     int i, j, initNr, skip;
2901*7c568831SAndroid Build Coastguard Worker     xmlNodePtr n1, n2;
2902*7c568831SAndroid Build Coastguard Worker 
2903*7c568831SAndroid Build Coastguard Worker     if (val1 == NULL) {
2904*7c568831SAndroid Build Coastguard Worker 	val1 = xmlXPathNodeSetCreate(NULL);
2905*7c568831SAndroid Build Coastguard Worker         if (val1 == NULL)
2906*7c568831SAndroid Build Coastguard Worker             return (NULL);
2907*7c568831SAndroid Build Coastguard Worker     }
2908*7c568831SAndroid Build Coastguard Worker     if (val2 == NULL)
2909*7c568831SAndroid Build Coastguard Worker         return(val1);
2910*7c568831SAndroid Build Coastguard Worker 
2911*7c568831SAndroid Build Coastguard Worker     /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2912*7c568831SAndroid Build Coastguard Worker     initNr = val1->nodeNr;
2913*7c568831SAndroid Build Coastguard Worker 
2914*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < val2->nodeNr;i++) {
2915*7c568831SAndroid Build Coastguard Worker 	n2 = val2->nodeTab[i];
2916*7c568831SAndroid Build Coastguard Worker 	/*
2917*7c568831SAndroid Build Coastguard Worker 	 * check against duplicates
2918*7c568831SAndroid Build Coastguard Worker 	 */
2919*7c568831SAndroid Build Coastguard Worker 	skip = 0;
2920*7c568831SAndroid Build Coastguard Worker 	for (j = 0; j < initNr; j++) {
2921*7c568831SAndroid Build Coastguard Worker 	    n1 = val1->nodeTab[j];
2922*7c568831SAndroid Build Coastguard Worker 	    if (n1 == n2) {
2923*7c568831SAndroid Build Coastguard Worker 		skip = 1;
2924*7c568831SAndroid Build Coastguard Worker 		break;
2925*7c568831SAndroid Build Coastguard Worker 	    } else if ((n1->type == XML_NAMESPACE_DECL) &&
2926*7c568831SAndroid Build Coastguard Worker 		       (n2->type == XML_NAMESPACE_DECL)) {
2927*7c568831SAndroid Build Coastguard Worker 		if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) &&
2928*7c568831SAndroid Build Coastguard Worker 		    (xmlStrEqual(((xmlNsPtr) n1)->prefix,
2929*7c568831SAndroid Build Coastguard Worker 			((xmlNsPtr) n2)->prefix)))
2930*7c568831SAndroid Build Coastguard Worker 		{
2931*7c568831SAndroid Build Coastguard Worker 		    skip = 1;
2932*7c568831SAndroid Build Coastguard Worker 		    break;
2933*7c568831SAndroid Build Coastguard Worker 		}
2934*7c568831SAndroid Build Coastguard Worker 	    }
2935*7c568831SAndroid Build Coastguard Worker 	}
2936*7c568831SAndroid Build Coastguard Worker 	if (skip)
2937*7c568831SAndroid Build Coastguard Worker 	    continue;
2938*7c568831SAndroid Build Coastguard Worker 
2939*7c568831SAndroid Build Coastguard Worker 	/*
2940*7c568831SAndroid Build Coastguard Worker 	 * grow the nodeTab if needed
2941*7c568831SAndroid Build Coastguard Worker 	 */
2942*7c568831SAndroid Build Coastguard Worker 	if (val1->nodeMax == 0) {
2943*7c568831SAndroid Build Coastguard Worker 	    val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2944*7c568831SAndroid Build Coastguard Worker 						    sizeof(xmlNodePtr));
2945*7c568831SAndroid Build Coastguard Worker 	    if (val1->nodeTab == NULL)
2946*7c568831SAndroid Build Coastguard Worker 		goto error;
2947*7c568831SAndroid Build Coastguard Worker 	    memset(val1->nodeTab, 0 ,
2948*7c568831SAndroid Build Coastguard Worker 		   XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2949*7c568831SAndroid Build Coastguard Worker 	    val1->nodeMax = XML_NODESET_DEFAULT;
2950*7c568831SAndroid Build Coastguard Worker 	} else if (val1->nodeNr == val1->nodeMax) {
2951*7c568831SAndroid Build Coastguard Worker 	    xmlNodePtr *temp;
2952*7c568831SAndroid Build Coastguard Worker 
2953*7c568831SAndroid Build Coastguard Worker             if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2954*7c568831SAndroid Build Coastguard Worker                 goto error;
2955*7c568831SAndroid Build Coastguard Worker 	    temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
2956*7c568831SAndroid Build Coastguard Worker 					     sizeof(xmlNodePtr));
2957*7c568831SAndroid Build Coastguard Worker 	    if (temp == NULL)
2958*7c568831SAndroid Build Coastguard Worker 		goto error;
2959*7c568831SAndroid Build Coastguard Worker 	    val1->nodeTab = temp;
2960*7c568831SAndroid Build Coastguard Worker 	    val1->nodeMax *= 2;
2961*7c568831SAndroid Build Coastguard Worker 	}
2962*7c568831SAndroid Build Coastguard Worker 	if (n2->type == XML_NAMESPACE_DECL) {
2963*7c568831SAndroid Build Coastguard Worker 	    xmlNsPtr ns = (xmlNsPtr) n2;
2964*7c568831SAndroid Build Coastguard Worker             xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2965*7c568831SAndroid Build Coastguard Worker 
2966*7c568831SAndroid Build Coastguard Worker             if (nsNode == NULL)
2967*7c568831SAndroid Build Coastguard Worker                 goto error;
2968*7c568831SAndroid Build Coastguard Worker 	    val1->nodeTab[val1->nodeNr++] = nsNode;
2969*7c568831SAndroid Build Coastguard Worker 	} else
2970*7c568831SAndroid Build Coastguard Worker 	    val1->nodeTab[val1->nodeNr++] = n2;
2971*7c568831SAndroid Build Coastguard Worker     }
2972*7c568831SAndroid Build Coastguard Worker 
2973*7c568831SAndroid Build Coastguard Worker     return(val1);
2974*7c568831SAndroid Build Coastguard Worker 
2975*7c568831SAndroid Build Coastguard Worker error:
2976*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeNodeSet(val1);
2977*7c568831SAndroid Build Coastguard Worker     return(NULL);
2978*7c568831SAndroid Build Coastguard Worker }
2979*7c568831SAndroid Build Coastguard Worker 
2980*7c568831SAndroid Build Coastguard Worker 
2981*7c568831SAndroid Build Coastguard Worker /**
2982*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetMergeAndClear:
2983*7c568831SAndroid Build Coastguard Worker  * @set1:  the first NodeSet or NULL
2984*7c568831SAndroid Build Coastguard Worker  * @set2:  the second NodeSet
2985*7c568831SAndroid Build Coastguard Worker  *
2986*7c568831SAndroid Build Coastguard Worker  * Merges two nodesets, all nodes from @set2 are added to @set1.
2987*7c568831SAndroid Build Coastguard Worker  * Checks for duplicate nodes. Clears set2.
2988*7c568831SAndroid Build Coastguard Worker  *
2989*7c568831SAndroid Build Coastguard Worker  * Returns @set1 once extended or NULL in case of error.
2990*7c568831SAndroid Build Coastguard Worker  *
2991*7c568831SAndroid Build Coastguard Worker  * Frees @set1 in case of error.
2992*7c568831SAndroid Build Coastguard Worker  */
2993*7c568831SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1,xmlNodeSetPtr set2)2994*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
2995*7c568831SAndroid Build Coastguard Worker {
2996*7c568831SAndroid Build Coastguard Worker     {
2997*7c568831SAndroid Build Coastguard Worker 	int i, j, initNbSet1;
2998*7c568831SAndroid Build Coastguard Worker 	xmlNodePtr n1, n2;
2999*7c568831SAndroid Build Coastguard Worker 
3000*7c568831SAndroid Build Coastguard Worker 	initNbSet1 = set1->nodeNr;
3001*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < set2->nodeNr;i++) {
3002*7c568831SAndroid Build Coastguard Worker 	    n2 = set2->nodeTab[i];
3003*7c568831SAndroid Build Coastguard Worker 	    /*
3004*7c568831SAndroid Build Coastguard Worker 	    * Skip duplicates.
3005*7c568831SAndroid Build Coastguard Worker 	    */
3006*7c568831SAndroid Build Coastguard Worker 	    for (j = 0; j < initNbSet1; j++) {
3007*7c568831SAndroid Build Coastguard Worker 		n1 = set1->nodeTab[j];
3008*7c568831SAndroid Build Coastguard Worker 		if (n1 == n2) {
3009*7c568831SAndroid Build Coastguard Worker 		    goto skip_node;
3010*7c568831SAndroid Build Coastguard Worker 		} else if ((n1->type == XML_NAMESPACE_DECL) &&
3011*7c568831SAndroid Build Coastguard Worker 		    (n2->type == XML_NAMESPACE_DECL))
3012*7c568831SAndroid Build Coastguard Worker 		{
3013*7c568831SAndroid Build Coastguard Worker 		    if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) &&
3014*7c568831SAndroid Build Coastguard Worker 			(xmlStrEqual(((xmlNsPtr) n1)->prefix,
3015*7c568831SAndroid Build Coastguard Worker 			((xmlNsPtr) n2)->prefix)))
3016*7c568831SAndroid Build Coastguard Worker 		    {
3017*7c568831SAndroid Build Coastguard Worker 			/*
3018*7c568831SAndroid Build Coastguard Worker 			* Free the namespace node.
3019*7c568831SAndroid Build Coastguard Worker 			*/
3020*7c568831SAndroid Build Coastguard Worker 			xmlXPathNodeSetFreeNs((xmlNsPtr) n2);
3021*7c568831SAndroid Build Coastguard Worker 			goto skip_node;
3022*7c568831SAndroid Build Coastguard Worker 		    }
3023*7c568831SAndroid Build Coastguard Worker 		}
3024*7c568831SAndroid Build Coastguard Worker 	    }
3025*7c568831SAndroid Build Coastguard Worker 	    /*
3026*7c568831SAndroid Build Coastguard Worker 	    * grow the nodeTab if needed
3027*7c568831SAndroid Build Coastguard Worker 	    */
3028*7c568831SAndroid Build Coastguard Worker 	    if (set1->nodeMax == 0) {
3029*7c568831SAndroid Build Coastguard Worker 		set1->nodeTab = (xmlNodePtr *) xmlMalloc(
3030*7c568831SAndroid Build Coastguard Worker 		    XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3031*7c568831SAndroid Build Coastguard Worker 		if (set1->nodeTab == NULL)
3032*7c568831SAndroid Build Coastguard Worker 		    goto error;
3033*7c568831SAndroid Build Coastguard Worker 		memset(set1->nodeTab, 0,
3034*7c568831SAndroid Build Coastguard Worker 		    XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3035*7c568831SAndroid Build Coastguard Worker 		set1->nodeMax = XML_NODESET_DEFAULT;
3036*7c568831SAndroid Build Coastguard Worker 	    } else if (set1->nodeNr >= set1->nodeMax) {
3037*7c568831SAndroid Build Coastguard Worker 		xmlNodePtr *temp;
3038*7c568831SAndroid Build Coastguard Worker 
3039*7c568831SAndroid Build Coastguard Worker                 if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
3040*7c568831SAndroid Build Coastguard Worker                     goto error;
3041*7c568831SAndroid Build Coastguard Worker 		temp = (xmlNodePtr *) xmlRealloc(
3042*7c568831SAndroid Build Coastguard Worker 		    set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
3043*7c568831SAndroid Build Coastguard Worker 		if (temp == NULL)
3044*7c568831SAndroid Build Coastguard Worker 		    goto error;
3045*7c568831SAndroid Build Coastguard Worker 		set1->nodeTab = temp;
3046*7c568831SAndroid Build Coastguard Worker 		set1->nodeMax *= 2;
3047*7c568831SAndroid Build Coastguard Worker 	    }
3048*7c568831SAndroid Build Coastguard Worker 	    set1->nodeTab[set1->nodeNr++] = n2;
3049*7c568831SAndroid Build Coastguard Worker skip_node:
3050*7c568831SAndroid Build Coastguard Worker             set2->nodeTab[i] = NULL;
3051*7c568831SAndroid Build Coastguard Worker 	}
3052*7c568831SAndroid Build Coastguard Worker     }
3053*7c568831SAndroid Build Coastguard Worker     set2->nodeNr = 0;
3054*7c568831SAndroid Build Coastguard Worker     return(set1);
3055*7c568831SAndroid Build Coastguard Worker 
3056*7c568831SAndroid Build Coastguard Worker error:
3057*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeNodeSet(set1);
3058*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetClear(set2, 1);
3059*7c568831SAndroid Build Coastguard Worker     return(NULL);
3060*7c568831SAndroid Build Coastguard Worker }
3061*7c568831SAndroid Build Coastguard Worker 
3062*7c568831SAndroid Build Coastguard Worker /**
3063*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetMergeAndClearNoDupls:
3064*7c568831SAndroid Build Coastguard Worker  * @set1:  the first NodeSet or NULL
3065*7c568831SAndroid Build Coastguard Worker  * @set2:  the second NodeSet
3066*7c568831SAndroid Build Coastguard Worker  *
3067*7c568831SAndroid Build Coastguard Worker  * Merges two nodesets, all nodes from @set2 are added to @set1.
3068*7c568831SAndroid Build Coastguard Worker  * Doesn't check for duplicate nodes. Clears set2.
3069*7c568831SAndroid Build Coastguard Worker  *
3070*7c568831SAndroid Build Coastguard Worker  * Returns @set1 once extended or NULL in case of error.
3071*7c568831SAndroid Build Coastguard Worker  *
3072*7c568831SAndroid Build Coastguard Worker  * Frees @set1 in case of error.
3073*7c568831SAndroid Build Coastguard Worker  */
3074*7c568831SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1,xmlNodeSetPtr set2)3075*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
3076*7c568831SAndroid Build Coastguard Worker {
3077*7c568831SAndroid Build Coastguard Worker     {
3078*7c568831SAndroid Build Coastguard Worker 	int i;
3079*7c568831SAndroid Build Coastguard Worker 	xmlNodePtr n2;
3080*7c568831SAndroid Build Coastguard Worker 
3081*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < set2->nodeNr;i++) {
3082*7c568831SAndroid Build Coastguard Worker 	    n2 = set2->nodeTab[i];
3083*7c568831SAndroid Build Coastguard Worker 	    if (set1->nodeMax == 0) {
3084*7c568831SAndroid Build Coastguard Worker 		set1->nodeTab = (xmlNodePtr *) xmlMalloc(
3085*7c568831SAndroid Build Coastguard Worker 		    XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3086*7c568831SAndroid Build Coastguard Worker 		if (set1->nodeTab == NULL)
3087*7c568831SAndroid Build Coastguard Worker 		    goto error;
3088*7c568831SAndroid Build Coastguard Worker 		memset(set1->nodeTab, 0,
3089*7c568831SAndroid Build Coastguard Worker 		    XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3090*7c568831SAndroid Build Coastguard Worker 		set1->nodeMax = XML_NODESET_DEFAULT;
3091*7c568831SAndroid Build Coastguard Worker 	    } else if (set1->nodeNr >= set1->nodeMax) {
3092*7c568831SAndroid Build Coastguard Worker 		xmlNodePtr *temp;
3093*7c568831SAndroid Build Coastguard Worker 
3094*7c568831SAndroid Build Coastguard Worker                 if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
3095*7c568831SAndroid Build Coastguard Worker                     goto error;
3096*7c568831SAndroid Build Coastguard Worker 		temp = (xmlNodePtr *) xmlRealloc(
3097*7c568831SAndroid Build Coastguard Worker 		    set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
3098*7c568831SAndroid Build Coastguard Worker 		if (temp == NULL)
3099*7c568831SAndroid Build Coastguard Worker 		    goto error;
3100*7c568831SAndroid Build Coastguard Worker 		set1->nodeTab = temp;
3101*7c568831SAndroid Build Coastguard Worker 		set1->nodeMax *= 2;
3102*7c568831SAndroid Build Coastguard Worker 	    }
3103*7c568831SAndroid Build Coastguard Worker 	    set1->nodeTab[set1->nodeNr++] = n2;
3104*7c568831SAndroid Build Coastguard Worker             set2->nodeTab[i] = NULL;
3105*7c568831SAndroid Build Coastguard Worker 	}
3106*7c568831SAndroid Build Coastguard Worker     }
3107*7c568831SAndroid Build Coastguard Worker     set2->nodeNr = 0;
3108*7c568831SAndroid Build Coastguard Worker     return(set1);
3109*7c568831SAndroid Build Coastguard Worker 
3110*7c568831SAndroid Build Coastguard Worker error:
3111*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeNodeSet(set1);
3112*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetClear(set2, 1);
3113*7c568831SAndroid Build Coastguard Worker     return(NULL);
3114*7c568831SAndroid Build Coastguard Worker }
3115*7c568831SAndroid Build Coastguard Worker 
3116*7c568831SAndroid Build Coastguard Worker /**
3117*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetDel:
3118*7c568831SAndroid Build Coastguard Worker  * @cur:  the initial node set
3119*7c568831SAndroid Build Coastguard Worker  * @val:  an xmlNodePtr
3120*7c568831SAndroid Build Coastguard Worker  *
3121*7c568831SAndroid Build Coastguard Worker  * Removes an xmlNodePtr from an existing NodeSet
3122*7c568831SAndroid Build Coastguard Worker  */
3123*7c568831SAndroid Build Coastguard Worker void
xmlXPathNodeSetDel(xmlNodeSetPtr cur,xmlNodePtr val)3124*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
3125*7c568831SAndroid Build Coastguard Worker     int i;
3126*7c568831SAndroid Build Coastguard Worker 
3127*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) return;
3128*7c568831SAndroid Build Coastguard Worker     if (val == NULL) return;
3129*7c568831SAndroid Build Coastguard Worker 
3130*7c568831SAndroid Build Coastguard Worker     /*
3131*7c568831SAndroid Build Coastguard Worker      * find node in nodeTab
3132*7c568831SAndroid Build Coastguard Worker      */
3133*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < cur->nodeNr;i++)
3134*7c568831SAndroid Build Coastguard Worker         if (cur->nodeTab[i] == val) break;
3135*7c568831SAndroid Build Coastguard Worker 
3136*7c568831SAndroid Build Coastguard Worker     if (i >= cur->nodeNr) {	/* not found */
3137*7c568831SAndroid Build Coastguard Worker         return;
3138*7c568831SAndroid Build Coastguard Worker     }
3139*7c568831SAndroid Build Coastguard Worker     if ((cur->nodeTab[i] != NULL) &&
3140*7c568831SAndroid Build Coastguard Worker 	(cur->nodeTab[i]->type == XML_NAMESPACE_DECL))
3141*7c568831SAndroid Build Coastguard Worker 	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]);
3142*7c568831SAndroid Build Coastguard Worker     cur->nodeNr--;
3143*7c568831SAndroid Build Coastguard Worker     for (;i < cur->nodeNr;i++)
3144*7c568831SAndroid Build Coastguard Worker         cur->nodeTab[i] = cur->nodeTab[i + 1];
3145*7c568831SAndroid Build Coastguard Worker     cur->nodeTab[cur->nodeNr] = NULL;
3146*7c568831SAndroid Build Coastguard Worker }
3147*7c568831SAndroid Build Coastguard Worker 
3148*7c568831SAndroid Build Coastguard Worker /**
3149*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetRemove:
3150*7c568831SAndroid Build Coastguard Worker  * @cur:  the initial node set
3151*7c568831SAndroid Build Coastguard Worker  * @val:  the index to remove
3152*7c568831SAndroid Build Coastguard Worker  *
3153*7c568831SAndroid Build Coastguard Worker  * Removes an entry from an existing NodeSet list.
3154*7c568831SAndroid Build Coastguard Worker  */
3155*7c568831SAndroid Build Coastguard Worker void
xmlXPathNodeSetRemove(xmlNodeSetPtr cur,int val)3156*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) {
3157*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) return;
3158*7c568831SAndroid Build Coastguard Worker     if (val >= cur->nodeNr) return;
3159*7c568831SAndroid Build Coastguard Worker     if ((cur->nodeTab[val] != NULL) &&
3160*7c568831SAndroid Build Coastguard Worker 	(cur->nodeTab[val]->type == XML_NAMESPACE_DECL))
3161*7c568831SAndroid Build Coastguard Worker 	xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]);
3162*7c568831SAndroid Build Coastguard Worker     cur->nodeNr--;
3163*7c568831SAndroid Build Coastguard Worker     for (;val < cur->nodeNr;val++)
3164*7c568831SAndroid Build Coastguard Worker         cur->nodeTab[val] = cur->nodeTab[val + 1];
3165*7c568831SAndroid Build Coastguard Worker     cur->nodeTab[cur->nodeNr] = NULL;
3166*7c568831SAndroid Build Coastguard Worker }
3167*7c568831SAndroid Build Coastguard Worker 
3168*7c568831SAndroid Build Coastguard Worker /**
3169*7c568831SAndroid Build Coastguard Worker  * xmlXPathFreeNodeSet:
3170*7c568831SAndroid Build Coastguard Worker  * @obj:  the xmlNodeSetPtr to free
3171*7c568831SAndroid Build Coastguard Worker  *
3172*7c568831SAndroid Build Coastguard Worker  * Free the NodeSet compound (not the actual nodes !).
3173*7c568831SAndroid Build Coastguard Worker  */
3174*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeNodeSet(xmlNodeSetPtr obj)3175*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
3176*7c568831SAndroid Build Coastguard Worker     if (obj == NULL) return;
3177*7c568831SAndroid Build Coastguard Worker     if (obj->nodeTab != NULL) {
3178*7c568831SAndroid Build Coastguard Worker 	int i;
3179*7c568831SAndroid Build Coastguard Worker 
3180*7c568831SAndroid Build Coastguard Worker 	/* @@ with_ns to check whether namespace nodes should be looked at @@ */
3181*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < obj->nodeNr;i++)
3182*7c568831SAndroid Build Coastguard Worker 	    if ((obj->nodeTab[i] != NULL) &&
3183*7c568831SAndroid Build Coastguard Worker 		(obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
3184*7c568831SAndroid Build Coastguard Worker 		xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
3185*7c568831SAndroid Build Coastguard Worker 	xmlFree(obj->nodeTab);
3186*7c568831SAndroid Build Coastguard Worker     }
3187*7c568831SAndroid Build Coastguard Worker     xmlFree(obj);
3188*7c568831SAndroid Build Coastguard Worker }
3189*7c568831SAndroid Build Coastguard Worker 
3190*7c568831SAndroid Build Coastguard Worker /**
3191*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetClearFromPos:
3192*7c568831SAndroid Build Coastguard Worker  * @set: the node set to be cleared
3193*7c568831SAndroid Build Coastguard Worker  * @pos: the start position to clear from
3194*7c568831SAndroid Build Coastguard Worker  *
3195*7c568831SAndroid Build Coastguard Worker  * Clears the list from temporary XPath objects (e.g. namespace nodes
3196*7c568831SAndroid Build Coastguard Worker  * are feed) starting with the entry at @pos, but does *not* free the list
3197*7c568831SAndroid Build Coastguard Worker  * itself. Sets the length of the list to @pos.
3198*7c568831SAndroid Build Coastguard Worker  */
3199*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set,int pos,int hasNsNodes)3200*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set, int pos, int hasNsNodes)
3201*7c568831SAndroid Build Coastguard Worker {
3202*7c568831SAndroid Build Coastguard Worker     if ((set == NULL) || (pos >= set->nodeNr))
3203*7c568831SAndroid Build Coastguard Worker 	return;
3204*7c568831SAndroid Build Coastguard Worker     else if ((hasNsNodes)) {
3205*7c568831SAndroid Build Coastguard Worker 	int i;
3206*7c568831SAndroid Build Coastguard Worker 	xmlNodePtr node;
3207*7c568831SAndroid Build Coastguard Worker 
3208*7c568831SAndroid Build Coastguard Worker 	for (i = pos; i < set->nodeNr; i++) {
3209*7c568831SAndroid Build Coastguard Worker 	    node = set->nodeTab[i];
3210*7c568831SAndroid Build Coastguard Worker 	    if ((node != NULL) &&
3211*7c568831SAndroid Build Coastguard Worker 		(node->type == XML_NAMESPACE_DECL))
3212*7c568831SAndroid Build Coastguard Worker 		xmlXPathNodeSetFreeNs((xmlNsPtr) node);
3213*7c568831SAndroid Build Coastguard Worker 	}
3214*7c568831SAndroid Build Coastguard Worker     }
3215*7c568831SAndroid Build Coastguard Worker     set->nodeNr = pos;
3216*7c568831SAndroid Build Coastguard Worker }
3217*7c568831SAndroid Build Coastguard Worker 
3218*7c568831SAndroid Build Coastguard Worker /**
3219*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetClear:
3220*7c568831SAndroid Build Coastguard Worker  * @set:  the node set to clear
3221*7c568831SAndroid Build Coastguard Worker  *
3222*7c568831SAndroid Build Coastguard Worker  * Clears the list from all temporary XPath objects (e.g. namespace nodes
3223*7c568831SAndroid Build Coastguard Worker  * are feed), but does *not* free the list itself. Sets the length of the
3224*7c568831SAndroid Build Coastguard Worker  * list to 0.
3225*7c568831SAndroid Build Coastguard Worker  */
3226*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNodeSetClear(xmlNodeSetPtr set,int hasNsNodes)3227*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes)
3228*7c568831SAndroid Build Coastguard Worker {
3229*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetClearFromPos(set, 0, hasNsNodes);
3230*7c568831SAndroid Build Coastguard Worker }
3231*7c568831SAndroid Build Coastguard Worker 
3232*7c568831SAndroid Build Coastguard Worker /**
3233*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetKeepLast:
3234*7c568831SAndroid Build Coastguard Worker  * @set: the node set to be cleared
3235*7c568831SAndroid Build Coastguard Worker  *
3236*7c568831SAndroid Build Coastguard Worker  * Move the last node to the first position and clear temporary XPath objects
3237*7c568831SAndroid Build Coastguard Worker  * (e.g. namespace nodes) from all other nodes. Sets the length of the list
3238*7c568831SAndroid Build Coastguard Worker  * to 1.
3239*7c568831SAndroid Build Coastguard Worker  */
3240*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNodeSetKeepLast(xmlNodeSetPtr set)3241*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetKeepLast(xmlNodeSetPtr set)
3242*7c568831SAndroid Build Coastguard Worker {
3243*7c568831SAndroid Build Coastguard Worker     int i;
3244*7c568831SAndroid Build Coastguard Worker     xmlNodePtr node;
3245*7c568831SAndroid Build Coastguard Worker 
3246*7c568831SAndroid Build Coastguard Worker     if ((set == NULL) || (set->nodeNr <= 1))
3247*7c568831SAndroid Build Coastguard Worker 	return;
3248*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < set->nodeNr - 1; i++) {
3249*7c568831SAndroid Build Coastguard Worker         node = set->nodeTab[i];
3250*7c568831SAndroid Build Coastguard Worker         if ((node != NULL) &&
3251*7c568831SAndroid Build Coastguard Worker             (node->type == XML_NAMESPACE_DECL))
3252*7c568831SAndroid Build Coastguard Worker             xmlXPathNodeSetFreeNs((xmlNsPtr) node);
3253*7c568831SAndroid Build Coastguard Worker     }
3254*7c568831SAndroid Build Coastguard Worker     set->nodeTab[0] = set->nodeTab[set->nodeNr-1];
3255*7c568831SAndroid Build Coastguard Worker     set->nodeNr = 1;
3256*7c568831SAndroid Build Coastguard Worker }
3257*7c568831SAndroid Build Coastguard Worker 
3258*7c568831SAndroid Build Coastguard Worker /**
3259*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewNodeSet:
3260*7c568831SAndroid Build Coastguard Worker  * @val:  the NodePtr value
3261*7c568831SAndroid Build Coastguard Worker  *
3262*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathObjectPtr of type NodeSet and initialize
3263*7c568831SAndroid Build Coastguard Worker  * it with the single Node @val
3264*7c568831SAndroid Build Coastguard Worker  *
3265*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
3266*7c568831SAndroid Build Coastguard Worker  */
3267*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewNodeSet(xmlNodePtr val)3268*7c568831SAndroid Build Coastguard Worker xmlXPathNewNodeSet(xmlNodePtr val) {
3269*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
3270*7c568831SAndroid Build Coastguard Worker 
3271*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3272*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
3273*7c568831SAndroid Build Coastguard Worker 	return(NULL);
3274*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathObject));
3275*7c568831SAndroid Build Coastguard Worker     ret->type = XPATH_NODESET;
3276*7c568831SAndroid Build Coastguard Worker     ret->boolval = 0;
3277*7c568831SAndroid Build Coastguard Worker     ret->nodesetval = xmlXPathNodeSetCreate(val);
3278*7c568831SAndroid Build Coastguard Worker     if (ret->nodesetval == NULL) {
3279*7c568831SAndroid Build Coastguard Worker         xmlFree(ret);
3280*7c568831SAndroid Build Coastguard Worker         return(NULL);
3281*7c568831SAndroid Build Coastguard Worker     }
3282*7c568831SAndroid Build Coastguard Worker     /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3283*7c568831SAndroid Build Coastguard Worker     return(ret);
3284*7c568831SAndroid Build Coastguard Worker }
3285*7c568831SAndroid Build Coastguard Worker 
3286*7c568831SAndroid Build Coastguard Worker /**
3287*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewValueTree:
3288*7c568831SAndroid Build Coastguard Worker  * @val:  the NodePtr value
3289*7c568831SAndroid Build Coastguard Worker  *
3290*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize
3291*7c568831SAndroid Build Coastguard Worker  * it with the tree root @val
3292*7c568831SAndroid Build Coastguard Worker  *
3293*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
3294*7c568831SAndroid Build Coastguard Worker  */
3295*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewValueTree(xmlNodePtr val)3296*7c568831SAndroid Build Coastguard Worker xmlXPathNewValueTree(xmlNodePtr val) {
3297*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
3298*7c568831SAndroid Build Coastguard Worker 
3299*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNewNodeSet(val);
3300*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
3301*7c568831SAndroid Build Coastguard Worker 	return(NULL);
3302*7c568831SAndroid Build Coastguard Worker     ret->type = XPATH_XSLT_TREE;
3303*7c568831SAndroid Build Coastguard Worker 
3304*7c568831SAndroid Build Coastguard Worker     return(ret);
3305*7c568831SAndroid Build Coastguard Worker }
3306*7c568831SAndroid Build Coastguard Worker 
3307*7c568831SAndroid Build Coastguard Worker /**
3308*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewNodeSetList:
3309*7c568831SAndroid Build Coastguard Worker  * @val:  an existing NodeSet
3310*7c568831SAndroid Build Coastguard Worker  *
3311*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathObjectPtr of type NodeSet and initialize
3312*7c568831SAndroid Build Coastguard Worker  * it with the Nodeset @val
3313*7c568831SAndroid Build Coastguard Worker  *
3314*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
3315*7c568831SAndroid Build Coastguard Worker  */
3316*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewNodeSetList(xmlNodeSetPtr val)3317*7c568831SAndroid Build Coastguard Worker xmlXPathNewNodeSetList(xmlNodeSetPtr val)
3318*7c568831SAndroid Build Coastguard Worker {
3319*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
3320*7c568831SAndroid Build Coastguard Worker 
3321*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
3322*7c568831SAndroid Build Coastguard Worker         ret = NULL;
3323*7c568831SAndroid Build Coastguard Worker     else if (val->nodeTab == NULL)
3324*7c568831SAndroid Build Coastguard Worker         ret = xmlXPathNewNodeSet(NULL);
3325*7c568831SAndroid Build Coastguard Worker     else {
3326*7c568831SAndroid Build Coastguard Worker         ret = xmlXPathNewNodeSet(val->nodeTab[0]);
3327*7c568831SAndroid Build Coastguard Worker         if (ret) {
3328*7c568831SAndroid Build Coastguard Worker             ret->nodesetval = xmlXPathNodeSetMerge(NULL, val);
3329*7c568831SAndroid Build Coastguard Worker             if (ret->nodesetval == NULL) {
3330*7c568831SAndroid Build Coastguard Worker                 xmlFree(ret);
3331*7c568831SAndroid Build Coastguard Worker                 return(NULL);
3332*7c568831SAndroid Build Coastguard Worker             }
3333*7c568831SAndroid Build Coastguard Worker         }
3334*7c568831SAndroid Build Coastguard Worker     }
3335*7c568831SAndroid Build Coastguard Worker 
3336*7c568831SAndroid Build Coastguard Worker     return (ret);
3337*7c568831SAndroid Build Coastguard Worker }
3338*7c568831SAndroid Build Coastguard Worker 
3339*7c568831SAndroid Build Coastguard Worker /**
3340*7c568831SAndroid Build Coastguard Worker  * xmlXPathWrapNodeSet:
3341*7c568831SAndroid Build Coastguard Worker  * @val:  the NodePtr value
3342*7c568831SAndroid Build Coastguard Worker  *
3343*7c568831SAndroid Build Coastguard Worker  * Wrap the Nodeset @val in a new xmlXPathObjectPtr
3344*7c568831SAndroid Build Coastguard Worker  *
3345*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
3346*7c568831SAndroid Build Coastguard Worker  *
3347*7c568831SAndroid Build Coastguard Worker  * In case of error the node set is destroyed and NULL is returned.
3348*7c568831SAndroid Build Coastguard Worker  */
3349*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapNodeSet(xmlNodeSetPtr val)3350*7c568831SAndroid Build Coastguard Worker xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
3351*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
3352*7c568831SAndroid Build Coastguard Worker 
3353*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3354*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
3355*7c568831SAndroid Build Coastguard Worker         xmlXPathFreeNodeSet(val);
3356*7c568831SAndroid Build Coastguard Worker 	return(NULL);
3357*7c568831SAndroid Build Coastguard Worker     }
3358*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathObject));
3359*7c568831SAndroid Build Coastguard Worker     ret->type = XPATH_NODESET;
3360*7c568831SAndroid Build Coastguard Worker     ret->nodesetval = val;
3361*7c568831SAndroid Build Coastguard Worker     return(ret);
3362*7c568831SAndroid Build Coastguard Worker }
3363*7c568831SAndroid Build Coastguard Worker 
3364*7c568831SAndroid Build Coastguard Worker /**
3365*7c568831SAndroid Build Coastguard Worker  * xmlXPathFreeNodeSetList:
3366*7c568831SAndroid Build Coastguard Worker  * @obj:  an existing NodeSetList object
3367*7c568831SAndroid Build Coastguard Worker  *
3368*7c568831SAndroid Build Coastguard Worker  * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
3369*7c568831SAndroid Build Coastguard Worker  * the list contrary to xmlXPathFreeObject().
3370*7c568831SAndroid Build Coastguard Worker  */
3371*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj)3372*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
3373*7c568831SAndroid Build Coastguard Worker     if (obj == NULL) return;
3374*7c568831SAndroid Build Coastguard Worker     xmlFree(obj);
3375*7c568831SAndroid Build Coastguard Worker }
3376*7c568831SAndroid Build Coastguard Worker 
3377*7c568831SAndroid Build Coastguard Worker /**
3378*7c568831SAndroid Build Coastguard Worker  * xmlXPathDifference:
3379*7c568831SAndroid Build Coastguard Worker  * @nodes1:  a node-set
3380*7c568831SAndroid Build Coastguard Worker  * @nodes2:  a node-set
3381*7c568831SAndroid Build Coastguard Worker  *
3382*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets difference() function:
3383*7c568831SAndroid Build Coastguard Worker  *    node-set set:difference (node-set, node-set)
3384*7c568831SAndroid Build Coastguard Worker  *
3385*7c568831SAndroid Build Coastguard Worker  * Returns the difference between the two node sets, or nodes1 if
3386*7c568831SAndroid Build Coastguard Worker  *         nodes2 is empty
3387*7c568831SAndroid Build Coastguard Worker  */
3388*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDifference(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3389*7c568831SAndroid Build Coastguard Worker xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3390*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret;
3391*7c568831SAndroid Build Coastguard Worker     int i, l1;
3392*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
3393*7c568831SAndroid Build Coastguard Worker 
3394*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes2))
3395*7c568831SAndroid Build Coastguard Worker 	return(nodes1);
3396*7c568831SAndroid Build Coastguard Worker 
3397*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNodeSetCreate(NULL);
3398*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
3399*7c568831SAndroid Build Coastguard Worker         return(NULL);
3400*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes1))
3401*7c568831SAndroid Build Coastguard Worker 	return(ret);
3402*7c568831SAndroid Build Coastguard Worker 
3403*7c568831SAndroid Build Coastguard Worker     l1 = xmlXPathNodeSetGetLength(nodes1);
3404*7c568831SAndroid Build Coastguard Worker 
3405*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < l1; i++) {
3406*7c568831SAndroid Build Coastguard Worker 	cur = xmlXPathNodeSetItem(nodes1, i);
3407*7c568831SAndroid Build Coastguard Worker 	if (!xmlXPathNodeSetContains(nodes2, cur)) {
3408*7c568831SAndroid Build Coastguard Worker 	    if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3409*7c568831SAndroid Build Coastguard Worker                 xmlXPathFreeNodeSet(ret);
3410*7c568831SAndroid Build Coastguard Worker 	        return(NULL);
3411*7c568831SAndroid Build Coastguard Worker             }
3412*7c568831SAndroid Build Coastguard Worker 	}
3413*7c568831SAndroid Build Coastguard Worker     }
3414*7c568831SAndroid Build Coastguard Worker     return(ret);
3415*7c568831SAndroid Build Coastguard Worker }
3416*7c568831SAndroid Build Coastguard Worker 
3417*7c568831SAndroid Build Coastguard Worker /**
3418*7c568831SAndroid Build Coastguard Worker  * xmlXPathIntersection:
3419*7c568831SAndroid Build Coastguard Worker  * @nodes1:  a node-set
3420*7c568831SAndroid Build Coastguard Worker  * @nodes2:  a node-set
3421*7c568831SAndroid Build Coastguard Worker  *
3422*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets intersection() function:
3423*7c568831SAndroid Build Coastguard Worker  *    node-set set:intersection (node-set, node-set)
3424*7c568831SAndroid Build Coastguard Worker  *
3425*7c568831SAndroid Build Coastguard Worker  * Returns a node set comprising the nodes that are within both the
3426*7c568831SAndroid Build Coastguard Worker  *         node sets passed as arguments
3427*7c568831SAndroid Build Coastguard Worker  */
3428*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathIntersection(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3429*7c568831SAndroid Build Coastguard Worker xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3430*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
3431*7c568831SAndroid Build Coastguard Worker     int i, l1;
3432*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
3433*7c568831SAndroid Build Coastguard Worker 
3434*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
3435*7c568831SAndroid Build Coastguard Worker         return(ret);
3436*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes1))
3437*7c568831SAndroid Build Coastguard Worker 	return(ret);
3438*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes2))
3439*7c568831SAndroid Build Coastguard Worker 	return(ret);
3440*7c568831SAndroid Build Coastguard Worker 
3441*7c568831SAndroid Build Coastguard Worker     l1 = xmlXPathNodeSetGetLength(nodes1);
3442*7c568831SAndroid Build Coastguard Worker 
3443*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < l1; i++) {
3444*7c568831SAndroid Build Coastguard Worker 	cur = xmlXPathNodeSetItem(nodes1, i);
3445*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathNodeSetContains(nodes2, cur)) {
3446*7c568831SAndroid Build Coastguard Worker 	    if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3447*7c568831SAndroid Build Coastguard Worker                 xmlXPathFreeNodeSet(ret);
3448*7c568831SAndroid Build Coastguard Worker 	        return(NULL);
3449*7c568831SAndroid Build Coastguard Worker             }
3450*7c568831SAndroid Build Coastguard Worker 	}
3451*7c568831SAndroid Build Coastguard Worker     }
3452*7c568831SAndroid Build Coastguard Worker     return(ret);
3453*7c568831SAndroid Build Coastguard Worker }
3454*7c568831SAndroid Build Coastguard Worker 
3455*7c568831SAndroid Build Coastguard Worker /**
3456*7c568831SAndroid Build Coastguard Worker  * xmlXPathDistinctSorted:
3457*7c568831SAndroid Build Coastguard Worker  * @nodes:  a node-set, sorted by document order
3458*7c568831SAndroid Build Coastguard Worker  *
3459*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets distinct() function:
3460*7c568831SAndroid Build Coastguard Worker  *    node-set set:distinct (node-set)
3461*7c568831SAndroid Build Coastguard Worker  *
3462*7c568831SAndroid Build Coastguard Worker  * Returns a subset of the nodes contained in @nodes, or @nodes if
3463*7c568831SAndroid Build Coastguard Worker  *         it is empty
3464*7c568831SAndroid Build Coastguard Worker  */
3465*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDistinctSorted(xmlNodeSetPtr nodes)3466*7c568831SAndroid Build Coastguard Worker xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
3467*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret;
3468*7c568831SAndroid Build Coastguard Worker     xmlHashTablePtr hash;
3469*7c568831SAndroid Build Coastguard Worker     int i, l;
3470*7c568831SAndroid Build Coastguard Worker     xmlChar * strval;
3471*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
3472*7c568831SAndroid Build Coastguard Worker 
3473*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes))
3474*7c568831SAndroid Build Coastguard Worker 	return(nodes);
3475*7c568831SAndroid Build Coastguard Worker 
3476*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNodeSetCreate(NULL);
3477*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
3478*7c568831SAndroid Build Coastguard Worker         return(ret);
3479*7c568831SAndroid Build Coastguard Worker     l = xmlXPathNodeSetGetLength(nodes);
3480*7c568831SAndroid Build Coastguard Worker     hash = xmlHashCreate (l);
3481*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < l; i++) {
3482*7c568831SAndroid Build Coastguard Worker 	cur = xmlXPathNodeSetItem(nodes, i);
3483*7c568831SAndroid Build Coastguard Worker 	strval = xmlXPathCastNodeToString(cur);
3484*7c568831SAndroid Build Coastguard Worker 	if (xmlHashLookup(hash, strval) == NULL) {
3485*7c568831SAndroid Build Coastguard Worker 	    if (xmlHashAddEntry(hash, strval, strval) < 0) {
3486*7c568831SAndroid Build Coastguard Worker                 xmlFree(strval);
3487*7c568831SAndroid Build Coastguard Worker                 goto error;
3488*7c568831SAndroid Build Coastguard Worker             }
3489*7c568831SAndroid Build Coastguard Worker 	    if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
3490*7c568831SAndroid Build Coastguard Worker 	        goto error;
3491*7c568831SAndroid Build Coastguard Worker 	} else {
3492*7c568831SAndroid Build Coastguard Worker 	    xmlFree(strval);
3493*7c568831SAndroid Build Coastguard Worker 	}
3494*7c568831SAndroid Build Coastguard Worker     }
3495*7c568831SAndroid Build Coastguard Worker     xmlHashFree(hash, xmlHashDefaultDeallocator);
3496*7c568831SAndroid Build Coastguard Worker     return(ret);
3497*7c568831SAndroid Build Coastguard Worker 
3498*7c568831SAndroid Build Coastguard Worker error:
3499*7c568831SAndroid Build Coastguard Worker     xmlHashFree(hash, xmlHashDefaultDeallocator);
3500*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeNodeSet(ret);
3501*7c568831SAndroid Build Coastguard Worker     return(NULL);
3502*7c568831SAndroid Build Coastguard Worker }
3503*7c568831SAndroid Build Coastguard Worker 
3504*7c568831SAndroid Build Coastguard Worker /**
3505*7c568831SAndroid Build Coastguard Worker  * xmlXPathDistinct:
3506*7c568831SAndroid Build Coastguard Worker  * @nodes:  a node-set
3507*7c568831SAndroid Build Coastguard Worker  *
3508*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets distinct() function:
3509*7c568831SAndroid Build Coastguard Worker  *    node-set set:distinct (node-set)
3510*7c568831SAndroid Build Coastguard Worker  * @nodes is sorted by document order, then #exslSetsDistinctSorted
3511*7c568831SAndroid Build Coastguard Worker  * is called with the sorted node-set
3512*7c568831SAndroid Build Coastguard Worker  *
3513*7c568831SAndroid Build Coastguard Worker  * Returns a subset of the nodes contained in @nodes, or @nodes if
3514*7c568831SAndroid Build Coastguard Worker  *         it is empty
3515*7c568831SAndroid Build Coastguard Worker  */
3516*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDistinct(xmlNodeSetPtr nodes)3517*7c568831SAndroid Build Coastguard Worker xmlXPathDistinct (xmlNodeSetPtr nodes) {
3518*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes))
3519*7c568831SAndroid Build Coastguard Worker 	return(nodes);
3520*7c568831SAndroid Build Coastguard Worker 
3521*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetSort(nodes);
3522*7c568831SAndroid Build Coastguard Worker     return(xmlXPathDistinctSorted(nodes));
3523*7c568831SAndroid Build Coastguard Worker }
3524*7c568831SAndroid Build Coastguard Worker 
3525*7c568831SAndroid Build Coastguard Worker /**
3526*7c568831SAndroid Build Coastguard Worker  * xmlXPathHasSameNodes:
3527*7c568831SAndroid Build Coastguard Worker  * @nodes1:  a node-set
3528*7c568831SAndroid Build Coastguard Worker  * @nodes2:  a node-set
3529*7c568831SAndroid Build Coastguard Worker  *
3530*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets has-same-nodes function:
3531*7c568831SAndroid Build Coastguard Worker  *    boolean set:has-same-node(node-set, node-set)
3532*7c568831SAndroid Build Coastguard Worker  *
3533*7c568831SAndroid Build Coastguard Worker  * Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
3534*7c568831SAndroid Build Coastguard Worker  *         otherwise
3535*7c568831SAndroid Build Coastguard Worker  */
3536*7c568831SAndroid Build Coastguard Worker int
xmlXPathHasSameNodes(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3537*7c568831SAndroid Build Coastguard Worker xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3538*7c568831SAndroid Build Coastguard Worker     int i, l;
3539*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
3540*7c568831SAndroid Build Coastguard Worker 
3541*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes1) ||
3542*7c568831SAndroid Build Coastguard Worker 	xmlXPathNodeSetIsEmpty(nodes2))
3543*7c568831SAndroid Build Coastguard Worker 	return(0);
3544*7c568831SAndroid Build Coastguard Worker 
3545*7c568831SAndroid Build Coastguard Worker     l = xmlXPathNodeSetGetLength(nodes1);
3546*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < l; i++) {
3547*7c568831SAndroid Build Coastguard Worker 	cur = xmlXPathNodeSetItem(nodes1, i);
3548*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathNodeSetContains(nodes2, cur))
3549*7c568831SAndroid Build Coastguard Worker 	    return(1);
3550*7c568831SAndroid Build Coastguard Worker     }
3551*7c568831SAndroid Build Coastguard Worker     return(0);
3552*7c568831SAndroid Build Coastguard Worker }
3553*7c568831SAndroid Build Coastguard Worker 
3554*7c568831SAndroid Build Coastguard Worker /**
3555*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeLeadingSorted:
3556*7c568831SAndroid Build Coastguard Worker  * @nodes: a node-set, sorted by document order
3557*7c568831SAndroid Build Coastguard Worker  * @node: a node
3558*7c568831SAndroid Build Coastguard Worker  *
3559*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets leading() function:
3560*7c568831SAndroid Build Coastguard Worker  *    node-set set:leading (node-set, node-set)
3561*7c568831SAndroid Build Coastguard Worker  *
3562*7c568831SAndroid Build Coastguard Worker  * Returns the nodes in @nodes that precede @node in document order,
3563*7c568831SAndroid Build Coastguard Worker  *         @nodes if @node is NULL or an empty node-set if @nodes
3564*7c568831SAndroid Build Coastguard Worker  *         doesn't contain @node
3565*7c568831SAndroid Build Coastguard Worker  */
3566*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeLeadingSorted(xmlNodeSetPtr nodes,xmlNodePtr node)3567*7c568831SAndroid Build Coastguard Worker xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
3568*7c568831SAndroid Build Coastguard Worker     int i, l;
3569*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
3570*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret;
3571*7c568831SAndroid Build Coastguard Worker 
3572*7c568831SAndroid Build Coastguard Worker     if (node == NULL)
3573*7c568831SAndroid Build Coastguard Worker 	return(nodes);
3574*7c568831SAndroid Build Coastguard Worker 
3575*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNodeSetCreate(NULL);
3576*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
3577*7c568831SAndroid Build Coastguard Worker         return(ret);
3578*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes) ||
3579*7c568831SAndroid Build Coastguard Worker 	(!xmlXPathNodeSetContains(nodes, node)))
3580*7c568831SAndroid Build Coastguard Worker 	return(ret);
3581*7c568831SAndroid Build Coastguard Worker 
3582*7c568831SAndroid Build Coastguard Worker     l = xmlXPathNodeSetGetLength(nodes);
3583*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < l; i++) {
3584*7c568831SAndroid Build Coastguard Worker 	cur = xmlXPathNodeSetItem(nodes, i);
3585*7c568831SAndroid Build Coastguard Worker 	if (cur == node)
3586*7c568831SAndroid Build Coastguard Worker 	    break;
3587*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3588*7c568831SAndroid Build Coastguard Worker             xmlXPathFreeNodeSet(ret);
3589*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
3590*7c568831SAndroid Build Coastguard Worker         }
3591*7c568831SAndroid Build Coastguard Worker     }
3592*7c568831SAndroid Build Coastguard Worker     return(ret);
3593*7c568831SAndroid Build Coastguard Worker }
3594*7c568831SAndroid Build Coastguard Worker 
3595*7c568831SAndroid Build Coastguard Worker /**
3596*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeLeading:
3597*7c568831SAndroid Build Coastguard Worker  * @nodes:  a node-set
3598*7c568831SAndroid Build Coastguard Worker  * @node:  a node
3599*7c568831SAndroid Build Coastguard Worker  *
3600*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets leading() function:
3601*7c568831SAndroid Build Coastguard Worker  *    node-set set:leading (node-set, node-set)
3602*7c568831SAndroid Build Coastguard Worker  * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
3603*7c568831SAndroid Build Coastguard Worker  * is called.
3604*7c568831SAndroid Build Coastguard Worker  *
3605*7c568831SAndroid Build Coastguard Worker  * Returns the nodes in @nodes that precede @node in document order,
3606*7c568831SAndroid Build Coastguard Worker  *         @nodes if @node is NULL or an empty node-set if @nodes
3607*7c568831SAndroid Build Coastguard Worker  *         doesn't contain @node
3608*7c568831SAndroid Build Coastguard Worker  */
3609*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeLeading(xmlNodeSetPtr nodes,xmlNodePtr node)3610*7c568831SAndroid Build Coastguard Worker xmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
3611*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetSort(nodes);
3612*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNodeLeadingSorted(nodes, node));
3613*7c568831SAndroid Build Coastguard Worker }
3614*7c568831SAndroid Build Coastguard Worker 
3615*7c568831SAndroid Build Coastguard Worker /**
3616*7c568831SAndroid Build Coastguard Worker  * xmlXPathLeadingSorted:
3617*7c568831SAndroid Build Coastguard Worker  * @nodes1:  a node-set, sorted by document order
3618*7c568831SAndroid Build Coastguard Worker  * @nodes2:  a node-set, sorted by document order
3619*7c568831SAndroid Build Coastguard Worker  *
3620*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets leading() function:
3621*7c568831SAndroid Build Coastguard Worker  *    node-set set:leading (node-set, node-set)
3622*7c568831SAndroid Build Coastguard Worker  *
3623*7c568831SAndroid Build Coastguard Worker  * Returns the nodes in @nodes1 that precede the first node in @nodes2
3624*7c568831SAndroid Build Coastguard Worker  *         in document order, @nodes1 if @nodes2 is NULL or empty or
3625*7c568831SAndroid Build Coastguard Worker  *         an empty node-set if @nodes1 doesn't contain @nodes2
3626*7c568831SAndroid Build Coastguard Worker  */
3627*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathLeadingSorted(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3628*7c568831SAndroid Build Coastguard Worker xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3629*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes2))
3630*7c568831SAndroid Build Coastguard Worker 	return(nodes1);
3631*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNodeLeadingSorted(nodes1,
3632*7c568831SAndroid Build Coastguard Worker 				     xmlXPathNodeSetItem(nodes2, 1)));
3633*7c568831SAndroid Build Coastguard Worker }
3634*7c568831SAndroid Build Coastguard Worker 
3635*7c568831SAndroid Build Coastguard Worker /**
3636*7c568831SAndroid Build Coastguard Worker  * xmlXPathLeading:
3637*7c568831SAndroid Build Coastguard Worker  * @nodes1:  a node-set
3638*7c568831SAndroid Build Coastguard Worker  * @nodes2:  a node-set
3639*7c568831SAndroid Build Coastguard Worker  *
3640*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets leading() function:
3641*7c568831SAndroid Build Coastguard Worker  *    node-set set:leading (node-set, node-set)
3642*7c568831SAndroid Build Coastguard Worker  * @nodes1 and @nodes2 are sorted by document order, then
3643*7c568831SAndroid Build Coastguard Worker  * #exslSetsLeadingSorted is called.
3644*7c568831SAndroid Build Coastguard Worker  *
3645*7c568831SAndroid Build Coastguard Worker  * Returns the nodes in @nodes1 that precede the first node in @nodes2
3646*7c568831SAndroid Build Coastguard Worker  *         in document order, @nodes1 if @nodes2 is NULL or empty or
3647*7c568831SAndroid Build Coastguard Worker  *         an empty node-set if @nodes1 doesn't contain @nodes2
3648*7c568831SAndroid Build Coastguard Worker  */
3649*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathLeading(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3650*7c568831SAndroid Build Coastguard Worker xmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3651*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes2))
3652*7c568831SAndroid Build Coastguard Worker 	return(nodes1);
3653*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes1))
3654*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNodeSetCreate(NULL));
3655*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetSort(nodes1);
3656*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetSort(nodes2);
3657*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNodeLeadingSorted(nodes1,
3658*7c568831SAndroid Build Coastguard Worker 				     xmlXPathNodeSetItem(nodes2, 1)));
3659*7c568831SAndroid Build Coastguard Worker }
3660*7c568831SAndroid Build Coastguard Worker 
3661*7c568831SAndroid Build Coastguard Worker /**
3662*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeTrailingSorted:
3663*7c568831SAndroid Build Coastguard Worker  * @nodes: a node-set, sorted by document order
3664*7c568831SAndroid Build Coastguard Worker  * @node: a node
3665*7c568831SAndroid Build Coastguard Worker  *
3666*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets trailing() function:
3667*7c568831SAndroid Build Coastguard Worker  *    node-set set:trailing (node-set, node-set)
3668*7c568831SAndroid Build Coastguard Worker  *
3669*7c568831SAndroid Build Coastguard Worker  * Returns the nodes in @nodes that follow @node in document order,
3670*7c568831SAndroid Build Coastguard Worker  *         @nodes if @node is NULL or an empty node-set if @nodes
3671*7c568831SAndroid Build Coastguard Worker  *         doesn't contain @node
3672*7c568831SAndroid Build Coastguard Worker  */
3673*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeTrailingSorted(xmlNodeSetPtr nodes,xmlNodePtr node)3674*7c568831SAndroid Build Coastguard Worker xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
3675*7c568831SAndroid Build Coastguard Worker     int i, l;
3676*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
3677*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret;
3678*7c568831SAndroid Build Coastguard Worker 
3679*7c568831SAndroid Build Coastguard Worker     if (node == NULL)
3680*7c568831SAndroid Build Coastguard Worker 	return(nodes);
3681*7c568831SAndroid Build Coastguard Worker 
3682*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNodeSetCreate(NULL);
3683*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
3684*7c568831SAndroid Build Coastguard Worker         return(ret);
3685*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes) ||
3686*7c568831SAndroid Build Coastguard Worker 	(!xmlXPathNodeSetContains(nodes, node)))
3687*7c568831SAndroid Build Coastguard Worker 	return(ret);
3688*7c568831SAndroid Build Coastguard Worker 
3689*7c568831SAndroid Build Coastguard Worker     l = xmlXPathNodeSetGetLength(nodes);
3690*7c568831SAndroid Build Coastguard Worker     for (i = l - 1; i >= 0; i--) {
3691*7c568831SAndroid Build Coastguard Worker 	cur = xmlXPathNodeSetItem(nodes, i);
3692*7c568831SAndroid Build Coastguard Worker 	if (cur == node)
3693*7c568831SAndroid Build Coastguard Worker 	    break;
3694*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3695*7c568831SAndroid Build Coastguard Worker             xmlXPathFreeNodeSet(ret);
3696*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
3697*7c568831SAndroid Build Coastguard Worker         }
3698*7c568831SAndroid Build Coastguard Worker     }
3699*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetSort(ret);	/* bug 413451 */
3700*7c568831SAndroid Build Coastguard Worker     return(ret);
3701*7c568831SAndroid Build Coastguard Worker }
3702*7c568831SAndroid Build Coastguard Worker 
3703*7c568831SAndroid Build Coastguard Worker /**
3704*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeTrailing:
3705*7c568831SAndroid Build Coastguard Worker  * @nodes:  a node-set
3706*7c568831SAndroid Build Coastguard Worker  * @node:  a node
3707*7c568831SAndroid Build Coastguard Worker  *
3708*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets trailing() function:
3709*7c568831SAndroid Build Coastguard Worker  *    node-set set:trailing (node-set, node-set)
3710*7c568831SAndroid Build Coastguard Worker  * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
3711*7c568831SAndroid Build Coastguard Worker  * is called.
3712*7c568831SAndroid Build Coastguard Worker  *
3713*7c568831SAndroid Build Coastguard Worker  * Returns the nodes in @nodes that follow @node in document order,
3714*7c568831SAndroid Build Coastguard Worker  *         @nodes if @node is NULL or an empty node-set if @nodes
3715*7c568831SAndroid Build Coastguard Worker  *         doesn't contain @node
3716*7c568831SAndroid Build Coastguard Worker  */
3717*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeTrailing(xmlNodeSetPtr nodes,xmlNodePtr node)3718*7c568831SAndroid Build Coastguard Worker xmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
3719*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetSort(nodes);
3720*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNodeTrailingSorted(nodes, node));
3721*7c568831SAndroid Build Coastguard Worker }
3722*7c568831SAndroid Build Coastguard Worker 
3723*7c568831SAndroid Build Coastguard Worker /**
3724*7c568831SAndroid Build Coastguard Worker  * xmlXPathTrailingSorted:
3725*7c568831SAndroid Build Coastguard Worker  * @nodes1:  a node-set, sorted by document order
3726*7c568831SAndroid Build Coastguard Worker  * @nodes2:  a node-set, sorted by document order
3727*7c568831SAndroid Build Coastguard Worker  *
3728*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets trailing() function:
3729*7c568831SAndroid Build Coastguard Worker  *    node-set set:trailing (node-set, node-set)
3730*7c568831SAndroid Build Coastguard Worker  *
3731*7c568831SAndroid Build Coastguard Worker  * Returns the nodes in @nodes1 that follow the first node in @nodes2
3732*7c568831SAndroid Build Coastguard Worker  *         in document order, @nodes1 if @nodes2 is NULL or empty or
3733*7c568831SAndroid Build Coastguard Worker  *         an empty node-set if @nodes1 doesn't contain @nodes2
3734*7c568831SAndroid Build Coastguard Worker  */
3735*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathTrailingSorted(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3736*7c568831SAndroid Build Coastguard Worker xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3737*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes2))
3738*7c568831SAndroid Build Coastguard Worker 	return(nodes1);
3739*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNodeTrailingSorted(nodes1,
3740*7c568831SAndroid Build Coastguard Worker 				      xmlXPathNodeSetItem(nodes2, 0)));
3741*7c568831SAndroid Build Coastguard Worker }
3742*7c568831SAndroid Build Coastguard Worker 
3743*7c568831SAndroid Build Coastguard Worker /**
3744*7c568831SAndroid Build Coastguard Worker  * xmlXPathTrailing:
3745*7c568831SAndroid Build Coastguard Worker  * @nodes1:  a node-set
3746*7c568831SAndroid Build Coastguard Worker  * @nodes2:  a node-set
3747*7c568831SAndroid Build Coastguard Worker  *
3748*7c568831SAndroid Build Coastguard Worker  * Implements the EXSLT - Sets trailing() function:
3749*7c568831SAndroid Build Coastguard Worker  *    node-set set:trailing (node-set, node-set)
3750*7c568831SAndroid Build Coastguard Worker  * @nodes1 and @nodes2 are sorted by document order, then
3751*7c568831SAndroid Build Coastguard Worker  * #xmlXPathTrailingSorted is called.
3752*7c568831SAndroid Build Coastguard Worker  *
3753*7c568831SAndroid Build Coastguard Worker  * Returns the nodes in @nodes1 that follow the first node in @nodes2
3754*7c568831SAndroid Build Coastguard Worker  *         in document order, @nodes1 if @nodes2 is NULL or empty or
3755*7c568831SAndroid Build Coastguard Worker  *         an empty node-set if @nodes1 doesn't contain @nodes2
3756*7c568831SAndroid Build Coastguard Worker  */
3757*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathTrailing(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3758*7c568831SAndroid Build Coastguard Worker xmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3759*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes2))
3760*7c568831SAndroid Build Coastguard Worker 	return(nodes1);
3761*7c568831SAndroid Build Coastguard Worker     if (xmlXPathNodeSetIsEmpty(nodes1))
3762*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNodeSetCreate(NULL));
3763*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetSort(nodes1);
3764*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetSort(nodes2);
3765*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNodeTrailingSorted(nodes1,
3766*7c568831SAndroid Build Coastguard Worker 				      xmlXPathNodeSetItem(nodes2, 0)));
3767*7c568831SAndroid Build Coastguard Worker }
3768*7c568831SAndroid Build Coastguard Worker 
3769*7c568831SAndroid Build Coastguard Worker /************************************************************************
3770*7c568831SAndroid Build Coastguard Worker  *									*
3771*7c568831SAndroid Build Coastguard Worker  *		Routines to handle extra functions			*
3772*7c568831SAndroid Build Coastguard Worker  *									*
3773*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
3774*7c568831SAndroid Build Coastguard Worker 
3775*7c568831SAndroid Build Coastguard Worker /**
3776*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisterFunc:
3777*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3778*7c568831SAndroid Build Coastguard Worker  * @name:  the function name
3779*7c568831SAndroid Build Coastguard Worker  * @f:  the function implementation or NULL
3780*7c568831SAndroid Build Coastguard Worker  *
3781*7c568831SAndroid Build Coastguard Worker  * Register a new function. If @f is NULL it unregisters the function
3782*7c568831SAndroid Build Coastguard Worker  *
3783*7c568831SAndroid Build Coastguard Worker  * Returns 0 in case of success, -1 in case of error
3784*7c568831SAndroid Build Coastguard Worker  */
3785*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterFunc(xmlXPathContextPtr ctxt,const xmlChar * name,xmlXPathFunction f)3786*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
3787*7c568831SAndroid Build Coastguard Worker 		     xmlXPathFunction f) {
3788*7c568831SAndroid Build Coastguard Worker     return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f));
3789*7c568831SAndroid Build Coastguard Worker }
3790*7c568831SAndroid Build Coastguard Worker 
3791*7c568831SAndroid Build Coastguard Worker /**
3792*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisterFuncNS:
3793*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3794*7c568831SAndroid Build Coastguard Worker  * @name:  the function name
3795*7c568831SAndroid Build Coastguard Worker  * @ns_uri:  the function namespace URI
3796*7c568831SAndroid Build Coastguard Worker  * @f:  the function implementation or NULL
3797*7c568831SAndroid Build Coastguard Worker  *
3798*7c568831SAndroid Build Coastguard Worker  * Register a new function. If @f is NULL it unregisters the function
3799*7c568831SAndroid Build Coastguard Worker  *
3800*7c568831SAndroid Build Coastguard Worker  * Returns 0 in case of success, -1 in case of error
3801*7c568831SAndroid Build Coastguard Worker  */
3802*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri,xmlXPathFunction f)3803*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
3804*7c568831SAndroid Build Coastguard Worker 		       const xmlChar *ns_uri, xmlXPathFunction f) {
3805*7c568831SAndroid Build Coastguard Worker     int ret;
3806*7c568831SAndroid Build Coastguard Worker 
3807*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
3808*7c568831SAndroid Build Coastguard Worker 	return(-1);
3809*7c568831SAndroid Build Coastguard Worker     if (name == NULL)
3810*7c568831SAndroid Build Coastguard Worker 	return(-1);
3811*7c568831SAndroid Build Coastguard Worker 
3812*7c568831SAndroid Build Coastguard Worker     if (ctxt->funcHash == NULL)
3813*7c568831SAndroid Build Coastguard Worker 	ctxt->funcHash = xmlHashCreate(0);
3814*7c568831SAndroid Build Coastguard Worker     if (ctxt->funcHash == NULL) {
3815*7c568831SAndroid Build Coastguard Worker         xmlXPathErrMemory(ctxt);
3816*7c568831SAndroid Build Coastguard Worker 	return(-1);
3817*7c568831SAndroid Build Coastguard Worker     }
3818*7c568831SAndroid Build Coastguard Worker     if (f == NULL)
3819*7c568831SAndroid Build Coastguard Worker         return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL));
3820*7c568831SAndroid Build Coastguard Worker XML_IGNORE_FPTR_CAST_WARNINGS
3821*7c568831SAndroid Build Coastguard Worker     ret = xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f);
3822*7c568831SAndroid Build Coastguard Worker XML_POP_WARNINGS
3823*7c568831SAndroid Build Coastguard Worker     if (ret < 0) {
3824*7c568831SAndroid Build Coastguard Worker         xmlXPathErrMemory(ctxt);
3825*7c568831SAndroid Build Coastguard Worker         return(-1);
3826*7c568831SAndroid Build Coastguard Worker     }
3827*7c568831SAndroid Build Coastguard Worker 
3828*7c568831SAndroid Build Coastguard Worker     return(0);
3829*7c568831SAndroid Build Coastguard Worker }
3830*7c568831SAndroid Build Coastguard Worker 
3831*7c568831SAndroid Build Coastguard Worker /**
3832*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisterFuncLookup:
3833*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3834*7c568831SAndroid Build Coastguard Worker  * @f:  the lookup function
3835*7c568831SAndroid Build Coastguard Worker  * @funcCtxt:  the lookup data
3836*7c568831SAndroid Build Coastguard Worker  *
3837*7c568831SAndroid Build Coastguard Worker  * Registers an external mechanism to do function lookup.
3838*7c568831SAndroid Build Coastguard Worker  */
3839*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisterFuncLookup(xmlXPathContextPtr ctxt,xmlXPathFuncLookupFunc f,void * funcCtxt)3840*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
3841*7c568831SAndroid Build Coastguard Worker 			    xmlXPathFuncLookupFunc f,
3842*7c568831SAndroid Build Coastguard Worker 			    void *funcCtxt) {
3843*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
3844*7c568831SAndroid Build Coastguard Worker 	return;
3845*7c568831SAndroid Build Coastguard Worker     ctxt->funcLookupFunc = f;
3846*7c568831SAndroid Build Coastguard Worker     ctxt->funcLookupData = funcCtxt;
3847*7c568831SAndroid Build Coastguard Worker }
3848*7c568831SAndroid Build Coastguard Worker 
3849*7c568831SAndroid Build Coastguard Worker /**
3850*7c568831SAndroid Build Coastguard Worker  * xmlXPathFunctionLookup:
3851*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3852*7c568831SAndroid Build Coastguard Worker  * @name:  the function name
3853*7c568831SAndroid Build Coastguard Worker  *
3854*7c568831SAndroid Build Coastguard Worker  * Search in the Function array of the context for the given
3855*7c568831SAndroid Build Coastguard Worker  * function.
3856*7c568831SAndroid Build Coastguard Worker  *
3857*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathFunction or NULL if not found
3858*7c568831SAndroid Build Coastguard Worker  */
3859*7c568831SAndroid Build Coastguard Worker xmlXPathFunction
xmlXPathFunctionLookup(xmlXPathContextPtr ctxt,const xmlChar * name)3860*7c568831SAndroid Build Coastguard Worker xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
3861*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
3862*7c568831SAndroid Build Coastguard Worker 	return (NULL);
3863*7c568831SAndroid Build Coastguard Worker 
3864*7c568831SAndroid Build Coastguard Worker     if (ctxt->funcLookupFunc != NULL) {
3865*7c568831SAndroid Build Coastguard Worker 	xmlXPathFunction ret;
3866*7c568831SAndroid Build Coastguard Worker 	xmlXPathFuncLookupFunc f;
3867*7c568831SAndroid Build Coastguard Worker 
3868*7c568831SAndroid Build Coastguard Worker 	f = ctxt->funcLookupFunc;
3869*7c568831SAndroid Build Coastguard Worker 	ret = f(ctxt->funcLookupData, name, NULL);
3870*7c568831SAndroid Build Coastguard Worker 	if (ret != NULL)
3871*7c568831SAndroid Build Coastguard Worker 	    return(ret);
3872*7c568831SAndroid Build Coastguard Worker     }
3873*7c568831SAndroid Build Coastguard Worker     return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
3874*7c568831SAndroid Build Coastguard Worker }
3875*7c568831SAndroid Build Coastguard Worker 
3876*7c568831SAndroid Build Coastguard Worker /**
3877*7c568831SAndroid Build Coastguard Worker  * xmlXPathFunctionLookupNS:
3878*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3879*7c568831SAndroid Build Coastguard Worker  * @name:  the function name
3880*7c568831SAndroid Build Coastguard Worker  * @ns_uri:  the function namespace URI
3881*7c568831SAndroid Build Coastguard Worker  *
3882*7c568831SAndroid Build Coastguard Worker  * Search in the Function array of the context for the given
3883*7c568831SAndroid Build Coastguard Worker  * function.
3884*7c568831SAndroid Build Coastguard Worker  *
3885*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathFunction or NULL if not found
3886*7c568831SAndroid Build Coastguard Worker  */
3887*7c568831SAndroid Build Coastguard Worker xmlXPathFunction
xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri)3888*7c568831SAndroid Build Coastguard Worker xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
3889*7c568831SAndroid Build Coastguard Worker 			 const xmlChar *ns_uri) {
3890*7c568831SAndroid Build Coastguard Worker     xmlXPathFunction ret;
3891*7c568831SAndroid Build Coastguard Worker 
3892*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
3893*7c568831SAndroid Build Coastguard Worker 	return(NULL);
3894*7c568831SAndroid Build Coastguard Worker     if (name == NULL)
3895*7c568831SAndroid Build Coastguard Worker 	return(NULL);
3896*7c568831SAndroid Build Coastguard Worker 
3897*7c568831SAndroid Build Coastguard Worker     if (ctxt->funcLookupFunc != NULL) {
3898*7c568831SAndroid Build Coastguard Worker 	xmlXPathFuncLookupFunc f;
3899*7c568831SAndroid Build Coastguard Worker 
3900*7c568831SAndroid Build Coastguard Worker 	f = ctxt->funcLookupFunc;
3901*7c568831SAndroid Build Coastguard Worker 	ret = f(ctxt->funcLookupData, name, ns_uri);
3902*7c568831SAndroid Build Coastguard Worker 	if (ret != NULL)
3903*7c568831SAndroid Build Coastguard Worker 	    return(ret);
3904*7c568831SAndroid Build Coastguard Worker     }
3905*7c568831SAndroid Build Coastguard Worker 
3906*7c568831SAndroid Build Coastguard Worker     if (ctxt->funcHash == NULL)
3907*7c568831SAndroid Build Coastguard Worker 	return(NULL);
3908*7c568831SAndroid Build Coastguard Worker 
3909*7c568831SAndroid Build Coastguard Worker XML_IGNORE_FPTR_CAST_WARNINGS
3910*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
3911*7c568831SAndroid Build Coastguard Worker XML_POP_WARNINGS
3912*7c568831SAndroid Build Coastguard Worker     return(ret);
3913*7c568831SAndroid Build Coastguard Worker }
3914*7c568831SAndroid Build Coastguard Worker 
3915*7c568831SAndroid Build Coastguard Worker /**
3916*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisteredFuncsCleanup:
3917*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3918*7c568831SAndroid Build Coastguard Worker  *
3919*7c568831SAndroid Build Coastguard Worker  * Cleanup the XPath context data associated to registered functions
3920*7c568831SAndroid Build Coastguard Worker  */
3921*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt)3922*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
3923*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
3924*7c568831SAndroid Build Coastguard Worker 	return;
3925*7c568831SAndroid Build Coastguard Worker 
3926*7c568831SAndroid Build Coastguard Worker     xmlHashFree(ctxt->funcHash, NULL);
3927*7c568831SAndroid Build Coastguard Worker     ctxt->funcHash = NULL;
3928*7c568831SAndroid Build Coastguard Worker }
3929*7c568831SAndroid Build Coastguard Worker 
3930*7c568831SAndroid Build Coastguard Worker /************************************************************************
3931*7c568831SAndroid Build Coastguard Worker  *									*
3932*7c568831SAndroid Build Coastguard Worker  *			Routines to handle Variables			*
3933*7c568831SAndroid Build Coastguard Worker  *									*
3934*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
3935*7c568831SAndroid Build Coastguard Worker 
3936*7c568831SAndroid Build Coastguard Worker /**
3937*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisterVariable:
3938*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3939*7c568831SAndroid Build Coastguard Worker  * @name:  the variable name
3940*7c568831SAndroid Build Coastguard Worker  * @value:  the variable value or NULL
3941*7c568831SAndroid Build Coastguard Worker  *
3942*7c568831SAndroid Build Coastguard Worker  * Register a new variable value. If @value is NULL it unregisters
3943*7c568831SAndroid Build Coastguard Worker  * the variable
3944*7c568831SAndroid Build Coastguard Worker  *
3945*7c568831SAndroid Build Coastguard Worker  * Returns 0 in case of success, -1 in case of error
3946*7c568831SAndroid Build Coastguard Worker  */
3947*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterVariable(xmlXPathContextPtr ctxt,const xmlChar * name,xmlXPathObjectPtr value)3948*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
3949*7c568831SAndroid Build Coastguard Worker 			 xmlXPathObjectPtr value) {
3950*7c568831SAndroid Build Coastguard Worker     return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value));
3951*7c568831SAndroid Build Coastguard Worker }
3952*7c568831SAndroid Build Coastguard Worker 
3953*7c568831SAndroid Build Coastguard Worker /**
3954*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisterVariableNS:
3955*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3956*7c568831SAndroid Build Coastguard Worker  * @name:  the variable name
3957*7c568831SAndroid Build Coastguard Worker  * @ns_uri:  the variable namespace URI
3958*7c568831SAndroid Build Coastguard Worker  * @value:  the variable value or NULL
3959*7c568831SAndroid Build Coastguard Worker  *
3960*7c568831SAndroid Build Coastguard Worker  * Register a new variable value. If @value is NULL it unregisters
3961*7c568831SAndroid Build Coastguard Worker  * the variable
3962*7c568831SAndroid Build Coastguard Worker  *
3963*7c568831SAndroid Build Coastguard Worker  * Returns 0 in case of success, -1 in case of error
3964*7c568831SAndroid Build Coastguard Worker  */
3965*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri,xmlXPathObjectPtr value)3966*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name,
3967*7c568831SAndroid Build Coastguard Worker 			   const xmlChar *ns_uri,
3968*7c568831SAndroid Build Coastguard Worker 			   xmlXPathObjectPtr value) {
3969*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
3970*7c568831SAndroid Build Coastguard Worker 	return(-1);
3971*7c568831SAndroid Build Coastguard Worker     if (name == NULL)
3972*7c568831SAndroid Build Coastguard Worker 	return(-1);
3973*7c568831SAndroid Build Coastguard Worker 
3974*7c568831SAndroid Build Coastguard Worker     if (ctxt->varHash == NULL)
3975*7c568831SAndroid Build Coastguard Worker 	ctxt->varHash = xmlHashCreate(0);
3976*7c568831SAndroid Build Coastguard Worker     if (ctxt->varHash == NULL)
3977*7c568831SAndroid Build Coastguard Worker 	return(-1);
3978*7c568831SAndroid Build Coastguard Worker     if (value == NULL)
3979*7c568831SAndroid Build Coastguard Worker         return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri,
3980*7c568831SAndroid Build Coastguard Worker 	                           xmlXPathFreeObjectEntry));
3981*7c568831SAndroid Build Coastguard Worker     return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
3982*7c568831SAndroid Build Coastguard Worker 			       (void *) value, xmlXPathFreeObjectEntry));
3983*7c568831SAndroid Build Coastguard Worker }
3984*7c568831SAndroid Build Coastguard Worker 
3985*7c568831SAndroid Build Coastguard Worker /**
3986*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisterVariableLookup:
3987*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
3988*7c568831SAndroid Build Coastguard Worker  * @f:  the lookup function
3989*7c568831SAndroid Build Coastguard Worker  * @data:  the lookup data
3990*7c568831SAndroid Build Coastguard Worker  *
3991*7c568831SAndroid Build Coastguard Worker  * register an external mechanism to do variable lookup
3992*7c568831SAndroid Build Coastguard Worker  */
3993*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,xmlXPathVariableLookupFunc f,void * data)3994*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
3995*7c568831SAndroid Build Coastguard Worker 	 xmlXPathVariableLookupFunc f, void *data) {
3996*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
3997*7c568831SAndroid Build Coastguard Worker 	return;
3998*7c568831SAndroid Build Coastguard Worker     ctxt->varLookupFunc = f;
3999*7c568831SAndroid Build Coastguard Worker     ctxt->varLookupData = data;
4000*7c568831SAndroid Build Coastguard Worker }
4001*7c568831SAndroid Build Coastguard Worker 
4002*7c568831SAndroid Build Coastguard Worker /**
4003*7c568831SAndroid Build Coastguard Worker  * xmlXPathVariableLookup:
4004*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
4005*7c568831SAndroid Build Coastguard Worker  * @name:  the variable name
4006*7c568831SAndroid Build Coastguard Worker  *
4007*7c568831SAndroid Build Coastguard Worker  * Search in the Variable array of the context for the given
4008*7c568831SAndroid Build Coastguard Worker  * variable value.
4009*7c568831SAndroid Build Coastguard Worker  *
4010*7c568831SAndroid Build Coastguard Worker  * Returns a copy of the value or NULL if not found
4011*7c568831SAndroid Build Coastguard Worker  */
4012*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathVariableLookup(xmlXPathContextPtr ctxt,const xmlChar * name)4013*7c568831SAndroid Build Coastguard Worker xmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
4014*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
4015*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4016*7c568831SAndroid Build Coastguard Worker 
4017*7c568831SAndroid Build Coastguard Worker     if (ctxt->varLookupFunc != NULL) {
4018*7c568831SAndroid Build Coastguard Worker 	xmlXPathObjectPtr ret;
4019*7c568831SAndroid Build Coastguard Worker 
4020*7c568831SAndroid Build Coastguard Worker 	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
4021*7c568831SAndroid Build Coastguard Worker 	        (ctxt->varLookupData, name, NULL);
4022*7c568831SAndroid Build Coastguard Worker 	return(ret);
4023*7c568831SAndroid Build Coastguard Worker     }
4024*7c568831SAndroid Build Coastguard Worker     return(xmlXPathVariableLookupNS(ctxt, name, NULL));
4025*7c568831SAndroid Build Coastguard Worker }
4026*7c568831SAndroid Build Coastguard Worker 
4027*7c568831SAndroid Build Coastguard Worker /**
4028*7c568831SAndroid Build Coastguard Worker  * xmlXPathVariableLookupNS:
4029*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
4030*7c568831SAndroid Build Coastguard Worker  * @name:  the variable name
4031*7c568831SAndroid Build Coastguard Worker  * @ns_uri:  the variable namespace URI
4032*7c568831SAndroid Build Coastguard Worker  *
4033*7c568831SAndroid Build Coastguard Worker  * Search in the Variable array of the context for the given
4034*7c568831SAndroid Build Coastguard Worker  * variable value.
4035*7c568831SAndroid Build Coastguard Worker  *
4036*7c568831SAndroid Build Coastguard Worker  * Returns the a copy of the value or NULL if not found
4037*7c568831SAndroid Build Coastguard Worker  */
4038*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri)4039*7c568831SAndroid Build Coastguard Worker xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
4040*7c568831SAndroid Build Coastguard Worker 			 const xmlChar *ns_uri) {
4041*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
4042*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4043*7c568831SAndroid Build Coastguard Worker 
4044*7c568831SAndroid Build Coastguard Worker     if (ctxt->varLookupFunc != NULL) {
4045*7c568831SAndroid Build Coastguard Worker 	xmlXPathObjectPtr ret;
4046*7c568831SAndroid Build Coastguard Worker 
4047*7c568831SAndroid Build Coastguard Worker 	ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
4048*7c568831SAndroid Build Coastguard Worker 	        (ctxt->varLookupData, name, ns_uri);
4049*7c568831SAndroid Build Coastguard Worker 	if (ret != NULL) return(ret);
4050*7c568831SAndroid Build Coastguard Worker     }
4051*7c568831SAndroid Build Coastguard Worker 
4052*7c568831SAndroid Build Coastguard Worker     if (ctxt->varHash == NULL)
4053*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4054*7c568831SAndroid Build Coastguard Worker     if (name == NULL)
4055*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4056*7c568831SAndroid Build Coastguard Worker 
4057*7c568831SAndroid Build Coastguard Worker     return(xmlXPathObjectCopy(xmlHashLookup2(ctxt->varHash, name, ns_uri)));
4058*7c568831SAndroid Build Coastguard Worker }
4059*7c568831SAndroid Build Coastguard Worker 
4060*7c568831SAndroid Build Coastguard Worker /**
4061*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisteredVariablesCleanup:
4062*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
4063*7c568831SAndroid Build Coastguard Worker  *
4064*7c568831SAndroid Build Coastguard Worker  * Cleanup the XPath context data associated to registered variables
4065*7c568831SAndroid Build Coastguard Worker  */
4066*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt)4067*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
4068*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
4069*7c568831SAndroid Build Coastguard Worker 	return;
4070*7c568831SAndroid Build Coastguard Worker 
4071*7c568831SAndroid Build Coastguard Worker     xmlHashFree(ctxt->varHash, xmlXPathFreeObjectEntry);
4072*7c568831SAndroid Build Coastguard Worker     ctxt->varHash = NULL;
4073*7c568831SAndroid Build Coastguard Worker }
4074*7c568831SAndroid Build Coastguard Worker 
4075*7c568831SAndroid Build Coastguard Worker /**
4076*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisterNs:
4077*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
4078*7c568831SAndroid Build Coastguard Worker  * @prefix:  the namespace prefix cannot be NULL or empty string
4079*7c568831SAndroid Build Coastguard Worker  * @ns_uri:  the namespace name
4080*7c568831SAndroid Build Coastguard Worker  *
4081*7c568831SAndroid Build Coastguard Worker  * Register a new namespace. If @ns_uri is NULL it unregisters
4082*7c568831SAndroid Build Coastguard Worker  * the namespace
4083*7c568831SAndroid Build Coastguard Worker  *
4084*7c568831SAndroid Build Coastguard Worker  * Returns 0 in case of success, -1 in case of error
4085*7c568831SAndroid Build Coastguard Worker  */
4086*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterNs(xmlXPathContextPtr ctxt,const xmlChar * prefix,const xmlChar * ns_uri)4087*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
4088*7c568831SAndroid Build Coastguard Worker 			   const xmlChar *ns_uri) {
4089*7c568831SAndroid Build Coastguard Worker     xmlChar *copy;
4090*7c568831SAndroid Build Coastguard Worker 
4091*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
4092*7c568831SAndroid Build Coastguard Worker 	return(-1);
4093*7c568831SAndroid Build Coastguard Worker     if (prefix == NULL)
4094*7c568831SAndroid Build Coastguard Worker 	return(-1);
4095*7c568831SAndroid Build Coastguard Worker     if (prefix[0] == 0)
4096*7c568831SAndroid Build Coastguard Worker 	return(-1);
4097*7c568831SAndroid Build Coastguard Worker 
4098*7c568831SAndroid Build Coastguard Worker     if (ctxt->nsHash == NULL)
4099*7c568831SAndroid Build Coastguard Worker 	ctxt->nsHash = xmlHashCreate(10);
4100*7c568831SAndroid Build Coastguard Worker     if (ctxt->nsHash == NULL) {
4101*7c568831SAndroid Build Coastguard Worker         xmlXPathErrMemory(ctxt);
4102*7c568831SAndroid Build Coastguard Worker 	return(-1);
4103*7c568831SAndroid Build Coastguard Worker     }
4104*7c568831SAndroid Build Coastguard Worker     if (ns_uri == NULL)
4105*7c568831SAndroid Build Coastguard Worker         return(xmlHashRemoveEntry(ctxt->nsHash, prefix,
4106*7c568831SAndroid Build Coastguard Worker 	                          xmlHashDefaultDeallocator));
4107*7c568831SAndroid Build Coastguard Worker 
4108*7c568831SAndroid Build Coastguard Worker     copy = xmlStrdup(ns_uri);
4109*7c568831SAndroid Build Coastguard Worker     if (copy == NULL) {
4110*7c568831SAndroid Build Coastguard Worker         xmlXPathErrMemory(ctxt);
4111*7c568831SAndroid Build Coastguard Worker         return(-1);
4112*7c568831SAndroid Build Coastguard Worker     }
4113*7c568831SAndroid Build Coastguard Worker     if (xmlHashUpdateEntry(ctxt->nsHash, prefix, copy,
4114*7c568831SAndroid Build Coastguard Worker                            xmlHashDefaultDeallocator) < 0) {
4115*7c568831SAndroid Build Coastguard Worker         xmlXPathErrMemory(ctxt);
4116*7c568831SAndroid Build Coastguard Worker         xmlFree(copy);
4117*7c568831SAndroid Build Coastguard Worker         return(-1);
4118*7c568831SAndroid Build Coastguard Worker     }
4119*7c568831SAndroid Build Coastguard Worker 
4120*7c568831SAndroid Build Coastguard Worker     return(0);
4121*7c568831SAndroid Build Coastguard Worker }
4122*7c568831SAndroid Build Coastguard Worker 
4123*7c568831SAndroid Build Coastguard Worker /**
4124*7c568831SAndroid Build Coastguard Worker  * xmlXPathNsLookup:
4125*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
4126*7c568831SAndroid Build Coastguard Worker  * @prefix:  the namespace prefix value
4127*7c568831SAndroid Build Coastguard Worker  *
4128*7c568831SAndroid Build Coastguard Worker  * Search in the namespace declaration array of the context for the given
4129*7c568831SAndroid Build Coastguard Worker  * namespace name associated to the given prefix
4130*7c568831SAndroid Build Coastguard Worker  *
4131*7c568831SAndroid Build Coastguard Worker  * Returns the value or NULL if not found
4132*7c568831SAndroid Build Coastguard Worker  */
4133*7c568831SAndroid Build Coastguard Worker const xmlChar *
xmlXPathNsLookup(xmlXPathContextPtr ctxt,const xmlChar * prefix)4134*7c568831SAndroid Build Coastguard Worker xmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
4135*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
4136*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4137*7c568831SAndroid Build Coastguard Worker     if (prefix == NULL)
4138*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4139*7c568831SAndroid Build Coastguard Worker 
4140*7c568831SAndroid Build Coastguard Worker     if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
4141*7c568831SAndroid Build Coastguard Worker 	return(XML_XML_NAMESPACE);
4142*7c568831SAndroid Build Coastguard Worker 
4143*7c568831SAndroid Build Coastguard Worker     if (ctxt->namespaces != NULL) {
4144*7c568831SAndroid Build Coastguard Worker 	int i;
4145*7c568831SAndroid Build Coastguard Worker 
4146*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ctxt->nsNr;i++) {
4147*7c568831SAndroid Build Coastguard Worker 	    if ((ctxt->namespaces[i] != NULL) &&
4148*7c568831SAndroid Build Coastguard Worker 		(xmlStrEqual(ctxt->namespaces[i]->prefix, prefix)))
4149*7c568831SAndroid Build Coastguard Worker 		return(ctxt->namespaces[i]->href);
4150*7c568831SAndroid Build Coastguard Worker 	}
4151*7c568831SAndroid Build Coastguard Worker     }
4152*7c568831SAndroid Build Coastguard Worker 
4153*7c568831SAndroid Build Coastguard Worker     return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
4154*7c568831SAndroid Build Coastguard Worker }
4155*7c568831SAndroid Build Coastguard Worker 
4156*7c568831SAndroid Build Coastguard Worker /**
4157*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisteredNsCleanup:
4158*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
4159*7c568831SAndroid Build Coastguard Worker  *
4160*7c568831SAndroid Build Coastguard Worker  * Cleanup the XPath context data associated to registered variables
4161*7c568831SAndroid Build Coastguard Worker  */
4162*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt)4163*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
4164*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
4165*7c568831SAndroid Build Coastguard Worker 	return;
4166*7c568831SAndroid Build Coastguard Worker 
4167*7c568831SAndroid Build Coastguard Worker     xmlHashFree(ctxt->nsHash, xmlHashDefaultDeallocator);
4168*7c568831SAndroid Build Coastguard Worker     ctxt->nsHash = NULL;
4169*7c568831SAndroid Build Coastguard Worker }
4170*7c568831SAndroid Build Coastguard Worker 
4171*7c568831SAndroid Build Coastguard Worker /************************************************************************
4172*7c568831SAndroid Build Coastguard Worker  *									*
4173*7c568831SAndroid Build Coastguard Worker  *			Routines to handle Values			*
4174*7c568831SAndroid Build Coastguard Worker  *									*
4175*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
4176*7c568831SAndroid Build Coastguard Worker 
4177*7c568831SAndroid Build Coastguard Worker /* Allocations are terrible, one needs to optimize all this !!! */
4178*7c568831SAndroid Build Coastguard Worker 
4179*7c568831SAndroid Build Coastguard Worker /**
4180*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewFloat:
4181*7c568831SAndroid Build Coastguard Worker  * @val:  the double value
4182*7c568831SAndroid Build Coastguard Worker  *
4183*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathObjectPtr of type double and of value @val
4184*7c568831SAndroid Build Coastguard Worker  *
4185*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
4186*7c568831SAndroid Build Coastguard Worker  */
4187*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewFloat(double val)4188*7c568831SAndroid Build Coastguard Worker xmlXPathNewFloat(double val) {
4189*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
4190*7c568831SAndroid Build Coastguard Worker 
4191*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4192*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
4193*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4194*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathObject));
4195*7c568831SAndroid Build Coastguard Worker     ret->type = XPATH_NUMBER;
4196*7c568831SAndroid Build Coastguard Worker     ret->floatval = val;
4197*7c568831SAndroid Build Coastguard Worker     return(ret);
4198*7c568831SAndroid Build Coastguard Worker }
4199*7c568831SAndroid Build Coastguard Worker 
4200*7c568831SAndroid Build Coastguard Worker /**
4201*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewBoolean:
4202*7c568831SAndroid Build Coastguard Worker  * @val:  the boolean value
4203*7c568831SAndroid Build Coastguard Worker  *
4204*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathObjectPtr of type boolean and of value @val
4205*7c568831SAndroid Build Coastguard Worker  *
4206*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
4207*7c568831SAndroid Build Coastguard Worker  */
4208*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewBoolean(int val)4209*7c568831SAndroid Build Coastguard Worker xmlXPathNewBoolean(int val) {
4210*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
4211*7c568831SAndroid Build Coastguard Worker 
4212*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4213*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
4214*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4215*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathObject));
4216*7c568831SAndroid Build Coastguard Worker     ret->type = XPATH_BOOLEAN;
4217*7c568831SAndroid Build Coastguard Worker     ret->boolval = (val != 0);
4218*7c568831SAndroid Build Coastguard Worker     return(ret);
4219*7c568831SAndroid Build Coastguard Worker }
4220*7c568831SAndroid Build Coastguard Worker 
4221*7c568831SAndroid Build Coastguard Worker /**
4222*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewString:
4223*7c568831SAndroid Build Coastguard Worker  * @val:  the xmlChar * value
4224*7c568831SAndroid Build Coastguard Worker  *
4225*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathObjectPtr of type string and of value @val
4226*7c568831SAndroid Build Coastguard Worker  *
4227*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
4228*7c568831SAndroid Build Coastguard Worker  */
4229*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewString(const xmlChar * val)4230*7c568831SAndroid Build Coastguard Worker xmlXPathNewString(const xmlChar *val) {
4231*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
4232*7c568831SAndroid Build Coastguard Worker 
4233*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4234*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
4235*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4236*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathObject));
4237*7c568831SAndroid Build Coastguard Worker     ret->type = XPATH_STRING;
4238*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
4239*7c568831SAndroid Build Coastguard Worker         val = BAD_CAST "";
4240*7c568831SAndroid Build Coastguard Worker     ret->stringval = xmlStrdup(val);
4241*7c568831SAndroid Build Coastguard Worker     if (ret->stringval == NULL) {
4242*7c568831SAndroid Build Coastguard Worker         xmlFree(ret);
4243*7c568831SAndroid Build Coastguard Worker         return(NULL);
4244*7c568831SAndroid Build Coastguard Worker     }
4245*7c568831SAndroid Build Coastguard Worker     return(ret);
4246*7c568831SAndroid Build Coastguard Worker }
4247*7c568831SAndroid Build Coastguard Worker 
4248*7c568831SAndroid Build Coastguard Worker /**
4249*7c568831SAndroid Build Coastguard Worker  * xmlXPathWrapString:
4250*7c568831SAndroid Build Coastguard Worker  * @val:  the xmlChar * value
4251*7c568831SAndroid Build Coastguard Worker  *
4252*7c568831SAndroid Build Coastguard Worker  * Wraps the @val string into an XPath object.
4253*7c568831SAndroid Build Coastguard Worker  *
4254*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
4255*7c568831SAndroid Build Coastguard Worker  *
4256*7c568831SAndroid Build Coastguard Worker  * Frees @val in case of error.
4257*7c568831SAndroid Build Coastguard Worker  */
4258*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapString(xmlChar * val)4259*7c568831SAndroid Build Coastguard Worker xmlXPathWrapString (xmlChar *val) {
4260*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
4261*7c568831SAndroid Build Coastguard Worker 
4262*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4263*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
4264*7c568831SAndroid Build Coastguard Worker         xmlFree(val);
4265*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4266*7c568831SAndroid Build Coastguard Worker     }
4267*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathObject));
4268*7c568831SAndroid Build Coastguard Worker     ret->type = XPATH_STRING;
4269*7c568831SAndroid Build Coastguard Worker     ret->stringval = val;
4270*7c568831SAndroid Build Coastguard Worker     return(ret);
4271*7c568831SAndroid Build Coastguard Worker }
4272*7c568831SAndroid Build Coastguard Worker 
4273*7c568831SAndroid Build Coastguard Worker /**
4274*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewCString:
4275*7c568831SAndroid Build Coastguard Worker  * @val:  the char * value
4276*7c568831SAndroid Build Coastguard Worker  *
4277*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathObjectPtr of type string and of value @val
4278*7c568831SAndroid Build Coastguard Worker  *
4279*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
4280*7c568831SAndroid Build Coastguard Worker  */
4281*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewCString(const char * val)4282*7c568831SAndroid Build Coastguard Worker xmlXPathNewCString(const char *val) {
4283*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNewString(BAD_CAST val));
4284*7c568831SAndroid Build Coastguard Worker }
4285*7c568831SAndroid Build Coastguard Worker 
4286*7c568831SAndroid Build Coastguard Worker /**
4287*7c568831SAndroid Build Coastguard Worker  * xmlXPathWrapCString:
4288*7c568831SAndroid Build Coastguard Worker  * @val:  the char * value
4289*7c568831SAndroid Build Coastguard Worker  *
4290*7c568831SAndroid Build Coastguard Worker  * Wraps a string into an XPath object.
4291*7c568831SAndroid Build Coastguard Worker  *
4292*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
4293*7c568831SAndroid Build Coastguard Worker  */
4294*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapCString(char * val)4295*7c568831SAndroid Build Coastguard Worker xmlXPathWrapCString (char * val) {
4296*7c568831SAndroid Build Coastguard Worker     return(xmlXPathWrapString((xmlChar *)(val)));
4297*7c568831SAndroid Build Coastguard Worker }
4298*7c568831SAndroid Build Coastguard Worker 
4299*7c568831SAndroid Build Coastguard Worker /**
4300*7c568831SAndroid Build Coastguard Worker  * xmlXPathWrapExternal:
4301*7c568831SAndroid Build Coastguard Worker  * @val:  the user data
4302*7c568831SAndroid Build Coastguard Worker  *
4303*7c568831SAndroid Build Coastguard Worker  * Wraps the @val data into an XPath object.
4304*7c568831SAndroid Build Coastguard Worker  *
4305*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
4306*7c568831SAndroid Build Coastguard Worker  */
4307*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapExternal(void * val)4308*7c568831SAndroid Build Coastguard Worker xmlXPathWrapExternal (void *val) {
4309*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
4310*7c568831SAndroid Build Coastguard Worker 
4311*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4312*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
4313*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4314*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathObject));
4315*7c568831SAndroid Build Coastguard Worker     ret->type = XPATH_USERS;
4316*7c568831SAndroid Build Coastguard Worker     ret->user = val;
4317*7c568831SAndroid Build Coastguard Worker     return(ret);
4318*7c568831SAndroid Build Coastguard Worker }
4319*7c568831SAndroid Build Coastguard Worker 
4320*7c568831SAndroid Build Coastguard Worker /**
4321*7c568831SAndroid Build Coastguard Worker  * xmlXPathObjectCopy:
4322*7c568831SAndroid Build Coastguard Worker  * @val:  the original object
4323*7c568831SAndroid Build Coastguard Worker  *
4324*7c568831SAndroid Build Coastguard Worker  * allocate a new copy of a given object
4325*7c568831SAndroid Build Coastguard Worker  *
4326*7c568831SAndroid Build Coastguard Worker  * Returns the newly created object.
4327*7c568831SAndroid Build Coastguard Worker  */
4328*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathObjectCopy(xmlXPathObjectPtr val)4329*7c568831SAndroid Build Coastguard Worker xmlXPathObjectCopy(xmlXPathObjectPtr val) {
4330*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
4331*7c568831SAndroid Build Coastguard Worker 
4332*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
4333*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4334*7c568831SAndroid Build Coastguard Worker 
4335*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4336*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
4337*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4338*7c568831SAndroid Build Coastguard Worker     memcpy(ret, val , sizeof(xmlXPathObject));
4339*7c568831SAndroid Build Coastguard Worker     switch (val->type) {
4340*7c568831SAndroid Build Coastguard Worker 	case XPATH_BOOLEAN:
4341*7c568831SAndroid Build Coastguard Worker 	case XPATH_NUMBER:
4342*7c568831SAndroid Build Coastguard Worker 	    break;
4343*7c568831SAndroid Build Coastguard Worker 	case XPATH_STRING:
4344*7c568831SAndroid Build Coastguard Worker 	    ret->stringval = xmlStrdup(val->stringval);
4345*7c568831SAndroid Build Coastguard Worker             if (ret->stringval == NULL) {
4346*7c568831SAndroid Build Coastguard Worker                 xmlFree(ret);
4347*7c568831SAndroid Build Coastguard Worker                 return(NULL);
4348*7c568831SAndroid Build Coastguard Worker             }
4349*7c568831SAndroid Build Coastguard Worker 	    break;
4350*7c568831SAndroid Build Coastguard Worker 	case XPATH_XSLT_TREE:
4351*7c568831SAndroid Build Coastguard Worker 	case XPATH_NODESET:
4352*7c568831SAndroid Build Coastguard Worker 	    ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
4353*7c568831SAndroid Build Coastguard Worker             if (ret->nodesetval == NULL) {
4354*7c568831SAndroid Build Coastguard Worker                 xmlFree(ret);
4355*7c568831SAndroid Build Coastguard Worker                 return(NULL);
4356*7c568831SAndroid Build Coastguard Worker             }
4357*7c568831SAndroid Build Coastguard Worker 	    /* Do not deallocate the copied tree value */
4358*7c568831SAndroid Build Coastguard Worker 	    ret->boolval = 0;
4359*7c568831SAndroid Build Coastguard Worker 	    break;
4360*7c568831SAndroid Build Coastguard Worker         case XPATH_USERS:
4361*7c568831SAndroid Build Coastguard Worker 	    ret->user = val->user;
4362*7c568831SAndroid Build Coastguard Worker 	    break;
4363*7c568831SAndroid Build Coastguard Worker         default:
4364*7c568831SAndroid Build Coastguard Worker             xmlFree(ret);
4365*7c568831SAndroid Build Coastguard Worker             ret = NULL;
4366*7c568831SAndroid Build Coastguard Worker 	    break;
4367*7c568831SAndroid Build Coastguard Worker     }
4368*7c568831SAndroid Build Coastguard Worker     return(ret);
4369*7c568831SAndroid Build Coastguard Worker }
4370*7c568831SAndroid Build Coastguard Worker 
4371*7c568831SAndroid Build Coastguard Worker /**
4372*7c568831SAndroid Build Coastguard Worker  * xmlXPathFreeObject:
4373*7c568831SAndroid Build Coastguard Worker  * @obj:  the object to free
4374*7c568831SAndroid Build Coastguard Worker  *
4375*7c568831SAndroid Build Coastguard Worker  * Free up an xmlXPathObjectPtr object.
4376*7c568831SAndroid Build Coastguard Worker  */
4377*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeObject(xmlXPathObjectPtr obj)4378*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(xmlXPathObjectPtr obj) {
4379*7c568831SAndroid Build Coastguard Worker     if (obj == NULL) return;
4380*7c568831SAndroid Build Coastguard Worker     if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
4381*7c568831SAndroid Build Coastguard Worker         if (obj->nodesetval != NULL)
4382*7c568831SAndroid Build Coastguard Worker             xmlXPathFreeNodeSet(obj->nodesetval);
4383*7c568831SAndroid Build Coastguard Worker     } else if (obj->type == XPATH_STRING) {
4384*7c568831SAndroid Build Coastguard Worker 	if (obj->stringval != NULL)
4385*7c568831SAndroid Build Coastguard Worker 	    xmlFree(obj->stringval);
4386*7c568831SAndroid Build Coastguard Worker     }
4387*7c568831SAndroid Build Coastguard Worker     xmlFree(obj);
4388*7c568831SAndroid Build Coastguard Worker }
4389*7c568831SAndroid Build Coastguard Worker 
4390*7c568831SAndroid Build Coastguard Worker static void
xmlXPathFreeObjectEntry(void * obj,const xmlChar * name ATTRIBUTE_UNUSED)4391*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObjectEntry(void *obj, const xmlChar *name ATTRIBUTE_UNUSED) {
4392*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeObject((xmlXPathObjectPtr) obj);
4393*7c568831SAndroid Build Coastguard Worker }
4394*7c568831SAndroid Build Coastguard Worker 
4395*7c568831SAndroid Build Coastguard Worker /**
4396*7c568831SAndroid Build Coastguard Worker  * xmlXPathReleaseObject:
4397*7c568831SAndroid Build Coastguard Worker  * @obj:  the xmlXPathObjectPtr to free or to cache
4398*7c568831SAndroid Build Coastguard Worker  *
4399*7c568831SAndroid Build Coastguard Worker  * Depending on the state of the cache this frees the given
4400*7c568831SAndroid Build Coastguard Worker  * XPath object or stores it in the cache.
4401*7c568831SAndroid Build Coastguard Worker  */
4402*7c568831SAndroid Build Coastguard Worker static void
xmlXPathReleaseObject(xmlXPathContextPtr ctxt,xmlXPathObjectPtr obj)4403*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj)
4404*7c568831SAndroid Build Coastguard Worker {
4405*7c568831SAndroid Build Coastguard Worker     if (obj == NULL)
4406*7c568831SAndroid Build Coastguard Worker 	return;
4407*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->cache == NULL)) {
4408*7c568831SAndroid Build Coastguard Worker 	 xmlXPathFreeObject(obj);
4409*7c568831SAndroid Build Coastguard Worker     } else {
4410*7c568831SAndroid Build Coastguard Worker 	xmlXPathContextCachePtr cache =
4411*7c568831SAndroid Build Coastguard Worker 	    (xmlXPathContextCachePtr) ctxt->cache;
4412*7c568831SAndroid Build Coastguard Worker 
4413*7c568831SAndroid Build Coastguard Worker 	switch (obj->type) {
4414*7c568831SAndroid Build Coastguard Worker 	    case XPATH_NODESET:
4415*7c568831SAndroid Build Coastguard Worker 	    case XPATH_XSLT_TREE:
4416*7c568831SAndroid Build Coastguard Worker 		if (obj->nodesetval != NULL) {
4417*7c568831SAndroid Build Coastguard Worker 		    if ((obj->nodesetval->nodeMax <= 40) &&
4418*7c568831SAndroid Build Coastguard Worker 			(cache->numNodeset < cache->maxNodeset)) {
4419*7c568831SAndroid Build Coastguard Worker                         obj->stringval = (void *) cache->nodesetObjs;
4420*7c568831SAndroid Build Coastguard Worker                         cache->nodesetObjs = obj;
4421*7c568831SAndroid Build Coastguard Worker                         cache->numNodeset += 1;
4422*7c568831SAndroid Build Coastguard Worker 			goto obj_cached;
4423*7c568831SAndroid Build Coastguard Worker 		    } else {
4424*7c568831SAndroid Build Coastguard Worker 			xmlXPathFreeNodeSet(obj->nodesetval);
4425*7c568831SAndroid Build Coastguard Worker 			obj->nodesetval = NULL;
4426*7c568831SAndroid Build Coastguard Worker 		    }
4427*7c568831SAndroid Build Coastguard Worker 		}
4428*7c568831SAndroid Build Coastguard Worker 		break;
4429*7c568831SAndroid Build Coastguard Worker 	    case XPATH_STRING:
4430*7c568831SAndroid Build Coastguard Worker 		if (obj->stringval != NULL)
4431*7c568831SAndroid Build Coastguard Worker 		    xmlFree(obj->stringval);
4432*7c568831SAndroid Build Coastguard Worker                 obj->stringval = NULL;
4433*7c568831SAndroid Build Coastguard Worker 		break;
4434*7c568831SAndroid Build Coastguard Worker 	    case XPATH_BOOLEAN:
4435*7c568831SAndroid Build Coastguard Worker 	    case XPATH_NUMBER:
4436*7c568831SAndroid Build Coastguard Worker 		break;
4437*7c568831SAndroid Build Coastguard Worker 	    default:
4438*7c568831SAndroid Build Coastguard Worker 		goto free_obj;
4439*7c568831SAndroid Build Coastguard Worker 	}
4440*7c568831SAndroid Build Coastguard Worker 
4441*7c568831SAndroid Build Coastguard Worker 	/*
4442*7c568831SAndroid Build Coastguard Worker 	* Fallback to adding to the misc-objects slot.
4443*7c568831SAndroid Build Coastguard Worker 	*/
4444*7c568831SAndroid Build Coastguard Worker         if (cache->numMisc >= cache->maxMisc)
4445*7c568831SAndroid Build Coastguard Worker 	    goto free_obj;
4446*7c568831SAndroid Build Coastguard Worker         obj->stringval = (void *) cache->miscObjs;
4447*7c568831SAndroid Build Coastguard Worker         cache->miscObjs = obj;
4448*7c568831SAndroid Build Coastguard Worker         cache->numMisc += 1;
4449*7c568831SAndroid Build Coastguard Worker 
4450*7c568831SAndroid Build Coastguard Worker obj_cached:
4451*7c568831SAndroid Build Coastguard Worker         obj->boolval = 0;
4452*7c568831SAndroid Build Coastguard Worker 	if (obj->nodesetval != NULL) {
4453*7c568831SAndroid Build Coastguard Worker 	    xmlNodeSetPtr tmpset = obj->nodesetval;
4454*7c568831SAndroid Build Coastguard Worker 
4455*7c568831SAndroid Build Coastguard Worker 	    /*
4456*7c568831SAndroid Build Coastguard Worker 	    * Due to those nasty ns-nodes, we need to traverse
4457*7c568831SAndroid Build Coastguard Worker 	    * the list and free the ns-nodes.
4458*7c568831SAndroid Build Coastguard Worker 	    */
4459*7c568831SAndroid Build Coastguard Worker 	    if (tmpset->nodeNr > 0) {
4460*7c568831SAndroid Build Coastguard Worker 		int i;
4461*7c568831SAndroid Build Coastguard Worker 		xmlNodePtr node;
4462*7c568831SAndroid Build Coastguard Worker 
4463*7c568831SAndroid Build Coastguard Worker 		for (i = 0; i < tmpset->nodeNr; i++) {
4464*7c568831SAndroid Build Coastguard Worker 		    node = tmpset->nodeTab[i];
4465*7c568831SAndroid Build Coastguard Worker 		    if ((node != NULL) &&
4466*7c568831SAndroid Build Coastguard Worker 			(node->type == XML_NAMESPACE_DECL))
4467*7c568831SAndroid Build Coastguard Worker 		    {
4468*7c568831SAndroid Build Coastguard Worker 			xmlXPathNodeSetFreeNs((xmlNsPtr) node);
4469*7c568831SAndroid Build Coastguard Worker 		    }
4470*7c568831SAndroid Build Coastguard Worker 		}
4471*7c568831SAndroid Build Coastguard Worker 	    }
4472*7c568831SAndroid Build Coastguard Worker 	    tmpset->nodeNr = 0;
4473*7c568831SAndroid Build Coastguard Worker         }
4474*7c568831SAndroid Build Coastguard Worker 
4475*7c568831SAndroid Build Coastguard Worker 	return;
4476*7c568831SAndroid Build Coastguard Worker 
4477*7c568831SAndroid Build Coastguard Worker free_obj:
4478*7c568831SAndroid Build Coastguard Worker 	/*
4479*7c568831SAndroid Build Coastguard Worker 	* Cache is full; free the object.
4480*7c568831SAndroid Build Coastguard Worker 	*/
4481*7c568831SAndroid Build Coastguard Worker 	if (obj->nodesetval != NULL)
4482*7c568831SAndroid Build Coastguard Worker 	    xmlXPathFreeNodeSet(obj->nodesetval);
4483*7c568831SAndroid Build Coastguard Worker 	xmlFree(obj);
4484*7c568831SAndroid Build Coastguard Worker     }
4485*7c568831SAndroid Build Coastguard Worker }
4486*7c568831SAndroid Build Coastguard Worker 
4487*7c568831SAndroid Build Coastguard Worker 
4488*7c568831SAndroid Build Coastguard Worker /************************************************************************
4489*7c568831SAndroid Build Coastguard Worker  *									*
4490*7c568831SAndroid Build Coastguard Worker  *			Type Casting Routines				*
4491*7c568831SAndroid Build Coastguard Worker  *									*
4492*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
4493*7c568831SAndroid Build Coastguard Worker 
4494*7c568831SAndroid Build Coastguard Worker /**
4495*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastBooleanToString:
4496*7c568831SAndroid Build Coastguard Worker  * @val:  a boolean
4497*7c568831SAndroid Build Coastguard Worker  *
4498*7c568831SAndroid Build Coastguard Worker  * Converts a boolean to its string value.
4499*7c568831SAndroid Build Coastguard Worker  *
4500*7c568831SAndroid Build Coastguard Worker  * Returns a newly allocated string.
4501*7c568831SAndroid Build Coastguard Worker  */
4502*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastBooleanToString(int val)4503*7c568831SAndroid Build Coastguard Worker xmlXPathCastBooleanToString (int val) {
4504*7c568831SAndroid Build Coastguard Worker     xmlChar *ret;
4505*7c568831SAndroid Build Coastguard Worker     if (val)
4506*7c568831SAndroid Build Coastguard Worker 	ret = xmlStrdup((const xmlChar *) "true");
4507*7c568831SAndroid Build Coastguard Worker     else
4508*7c568831SAndroid Build Coastguard Worker 	ret = xmlStrdup((const xmlChar *) "false");
4509*7c568831SAndroid Build Coastguard Worker     return(ret);
4510*7c568831SAndroid Build Coastguard Worker }
4511*7c568831SAndroid Build Coastguard Worker 
4512*7c568831SAndroid Build Coastguard Worker /**
4513*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastNumberToString:
4514*7c568831SAndroid Build Coastguard Worker  * @val:  a number
4515*7c568831SAndroid Build Coastguard Worker  *
4516*7c568831SAndroid Build Coastguard Worker  * Converts a number to its string value.
4517*7c568831SAndroid Build Coastguard Worker  *
4518*7c568831SAndroid Build Coastguard Worker  * Returns a newly allocated string.
4519*7c568831SAndroid Build Coastguard Worker  */
4520*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNumberToString(double val)4521*7c568831SAndroid Build Coastguard Worker xmlXPathCastNumberToString (double val) {
4522*7c568831SAndroid Build Coastguard Worker     xmlChar *ret;
4523*7c568831SAndroid Build Coastguard Worker     switch (xmlXPathIsInf(val)) {
4524*7c568831SAndroid Build Coastguard Worker     case 1:
4525*7c568831SAndroid Build Coastguard Worker 	ret = xmlStrdup((const xmlChar *) "Infinity");
4526*7c568831SAndroid Build Coastguard Worker 	break;
4527*7c568831SAndroid Build Coastguard Worker     case -1:
4528*7c568831SAndroid Build Coastguard Worker 	ret = xmlStrdup((const xmlChar *) "-Infinity");
4529*7c568831SAndroid Build Coastguard Worker 	break;
4530*7c568831SAndroid Build Coastguard Worker     default:
4531*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathIsNaN(val)) {
4532*7c568831SAndroid Build Coastguard Worker 	    ret = xmlStrdup((const xmlChar *) "NaN");
4533*7c568831SAndroid Build Coastguard Worker 	} else if (val == 0) {
4534*7c568831SAndroid Build Coastguard Worker             /* Omit sign for negative zero. */
4535*7c568831SAndroid Build Coastguard Worker 	    ret = xmlStrdup((const xmlChar *) "0");
4536*7c568831SAndroid Build Coastguard Worker 	} else {
4537*7c568831SAndroid Build Coastguard Worker 	    /* could be improved */
4538*7c568831SAndroid Build Coastguard Worker 	    char buf[100];
4539*7c568831SAndroid Build Coastguard Worker 	    xmlXPathFormatNumber(val, buf, 99);
4540*7c568831SAndroid Build Coastguard Worker 	    buf[99] = 0;
4541*7c568831SAndroid Build Coastguard Worker 	    ret = xmlStrdup((const xmlChar *) buf);
4542*7c568831SAndroid Build Coastguard Worker 	}
4543*7c568831SAndroid Build Coastguard Worker     }
4544*7c568831SAndroid Build Coastguard Worker     return(ret);
4545*7c568831SAndroid Build Coastguard Worker }
4546*7c568831SAndroid Build Coastguard Worker 
4547*7c568831SAndroid Build Coastguard Worker /**
4548*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastNodeToString:
4549*7c568831SAndroid Build Coastguard Worker  * @node:  a node
4550*7c568831SAndroid Build Coastguard Worker  *
4551*7c568831SAndroid Build Coastguard Worker  * Converts a node to its string value.
4552*7c568831SAndroid Build Coastguard Worker  *
4553*7c568831SAndroid Build Coastguard Worker  * Returns a newly allocated string.
4554*7c568831SAndroid Build Coastguard Worker  */
4555*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNodeToString(xmlNodePtr node)4556*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeToString (xmlNodePtr node) {
4557*7c568831SAndroid Build Coastguard Worker     return(xmlNodeGetContent(node));
4558*7c568831SAndroid Build Coastguard Worker }
4559*7c568831SAndroid Build Coastguard Worker 
4560*7c568831SAndroid Build Coastguard Worker /**
4561*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastNodeSetToString:
4562*7c568831SAndroid Build Coastguard Worker  * @ns:  a node-set
4563*7c568831SAndroid Build Coastguard Worker  *
4564*7c568831SAndroid Build Coastguard Worker  * Converts a node-set to its string value.
4565*7c568831SAndroid Build Coastguard Worker  *
4566*7c568831SAndroid Build Coastguard Worker  * Returns a newly allocated string.
4567*7c568831SAndroid Build Coastguard Worker  */
4568*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNodeSetToString(xmlNodeSetPtr ns)4569*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
4570*7c568831SAndroid Build Coastguard Worker     if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
4571*7c568831SAndroid Build Coastguard Worker 	return(xmlStrdup((const xmlChar *) ""));
4572*7c568831SAndroid Build Coastguard Worker 
4573*7c568831SAndroid Build Coastguard Worker     if (ns->nodeNr > 1)
4574*7c568831SAndroid Build Coastguard Worker 	xmlXPathNodeSetSort(ns);
4575*7c568831SAndroid Build Coastguard Worker     return(xmlXPathCastNodeToString(ns->nodeTab[0]));
4576*7c568831SAndroid Build Coastguard Worker }
4577*7c568831SAndroid Build Coastguard Worker 
4578*7c568831SAndroid Build Coastguard Worker /**
4579*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastToString:
4580*7c568831SAndroid Build Coastguard Worker  * @val:  an XPath object
4581*7c568831SAndroid Build Coastguard Worker  *
4582*7c568831SAndroid Build Coastguard Worker  * Converts an existing object to its string() equivalent
4583*7c568831SAndroid Build Coastguard Worker  *
4584*7c568831SAndroid Build Coastguard Worker  * Returns the allocated string value of the object, NULL in case of error.
4585*7c568831SAndroid Build Coastguard Worker  *         It's up to the caller to free the string memory with xmlFree().
4586*7c568831SAndroid Build Coastguard Worker  */
4587*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastToString(xmlXPathObjectPtr val)4588*7c568831SAndroid Build Coastguard Worker xmlXPathCastToString(xmlXPathObjectPtr val) {
4589*7c568831SAndroid Build Coastguard Worker     xmlChar *ret = NULL;
4590*7c568831SAndroid Build Coastguard Worker 
4591*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
4592*7c568831SAndroid Build Coastguard Worker 	return(xmlStrdup((const xmlChar *) ""));
4593*7c568831SAndroid Build Coastguard Worker     switch (val->type) {
4594*7c568831SAndroid Build Coastguard Worker 	case XPATH_UNDEFINED:
4595*7c568831SAndroid Build Coastguard Worker 	    ret = xmlStrdup((const xmlChar *) "");
4596*7c568831SAndroid Build Coastguard Worker 	    break;
4597*7c568831SAndroid Build Coastguard Worker         case XPATH_NODESET:
4598*7c568831SAndroid Build Coastguard Worker         case XPATH_XSLT_TREE:
4599*7c568831SAndroid Build Coastguard Worker 	    ret = xmlXPathCastNodeSetToString(val->nodesetval);
4600*7c568831SAndroid Build Coastguard Worker 	    break;
4601*7c568831SAndroid Build Coastguard Worker 	case XPATH_STRING:
4602*7c568831SAndroid Build Coastguard Worker 	    return(xmlStrdup(val->stringval));
4603*7c568831SAndroid Build Coastguard Worker         case XPATH_BOOLEAN:
4604*7c568831SAndroid Build Coastguard Worker 	    ret = xmlXPathCastBooleanToString(val->boolval);
4605*7c568831SAndroid Build Coastguard Worker 	    break;
4606*7c568831SAndroid Build Coastguard Worker 	case XPATH_NUMBER: {
4607*7c568831SAndroid Build Coastguard Worker 	    ret = xmlXPathCastNumberToString(val->floatval);
4608*7c568831SAndroid Build Coastguard Worker 	    break;
4609*7c568831SAndroid Build Coastguard Worker 	}
4610*7c568831SAndroid Build Coastguard Worker 	case XPATH_USERS:
4611*7c568831SAndroid Build Coastguard Worker 	    /* TODO */
4612*7c568831SAndroid Build Coastguard Worker 	    ret = xmlStrdup((const xmlChar *) "");
4613*7c568831SAndroid Build Coastguard Worker 	    break;
4614*7c568831SAndroid Build Coastguard Worker     }
4615*7c568831SAndroid Build Coastguard Worker     return(ret);
4616*7c568831SAndroid Build Coastguard Worker }
4617*7c568831SAndroid Build Coastguard Worker 
4618*7c568831SAndroid Build Coastguard Worker /**
4619*7c568831SAndroid Build Coastguard Worker  * xmlXPathConvertString:
4620*7c568831SAndroid Build Coastguard Worker  * @val:  an XPath object
4621*7c568831SAndroid Build Coastguard Worker  *
4622*7c568831SAndroid Build Coastguard Worker  * Converts an existing object to its string() equivalent
4623*7c568831SAndroid Build Coastguard Worker  *
4624*7c568831SAndroid Build Coastguard Worker  * Returns the new object, the old one is freed (or the operation
4625*7c568831SAndroid Build Coastguard Worker  *         is done directly on @val)
4626*7c568831SAndroid Build Coastguard Worker  */
4627*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertString(xmlXPathObjectPtr val)4628*7c568831SAndroid Build Coastguard Worker xmlXPathConvertString(xmlXPathObjectPtr val) {
4629*7c568831SAndroid Build Coastguard Worker     xmlChar *res = NULL;
4630*7c568831SAndroid Build Coastguard Worker 
4631*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
4632*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNewCString(""));
4633*7c568831SAndroid Build Coastguard Worker 
4634*7c568831SAndroid Build Coastguard Worker     switch (val->type) {
4635*7c568831SAndroid Build Coastguard Worker     case XPATH_UNDEFINED:
4636*7c568831SAndroid Build Coastguard Worker 	break;
4637*7c568831SAndroid Build Coastguard Worker     case XPATH_NODESET:
4638*7c568831SAndroid Build Coastguard Worker     case XPATH_XSLT_TREE:
4639*7c568831SAndroid Build Coastguard Worker 	res = xmlXPathCastNodeSetToString(val->nodesetval);
4640*7c568831SAndroid Build Coastguard Worker 	break;
4641*7c568831SAndroid Build Coastguard Worker     case XPATH_STRING:
4642*7c568831SAndroid Build Coastguard Worker 	return(val);
4643*7c568831SAndroid Build Coastguard Worker     case XPATH_BOOLEAN:
4644*7c568831SAndroid Build Coastguard Worker 	res = xmlXPathCastBooleanToString(val->boolval);
4645*7c568831SAndroid Build Coastguard Worker 	break;
4646*7c568831SAndroid Build Coastguard Worker     case XPATH_NUMBER:
4647*7c568831SAndroid Build Coastguard Worker 	res = xmlXPathCastNumberToString(val->floatval);
4648*7c568831SAndroid Build Coastguard Worker 	break;
4649*7c568831SAndroid Build Coastguard Worker     case XPATH_USERS:
4650*7c568831SAndroid Build Coastguard Worker 	/* TODO */
4651*7c568831SAndroid Build Coastguard Worker 	break;
4652*7c568831SAndroid Build Coastguard Worker     }
4653*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeObject(val);
4654*7c568831SAndroid Build Coastguard Worker     if (res == NULL)
4655*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNewCString(""));
4656*7c568831SAndroid Build Coastguard Worker     return(xmlXPathWrapString(res));
4657*7c568831SAndroid Build Coastguard Worker }
4658*7c568831SAndroid Build Coastguard Worker 
4659*7c568831SAndroid Build Coastguard Worker /**
4660*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastBooleanToNumber:
4661*7c568831SAndroid Build Coastguard Worker  * @val:  a boolean
4662*7c568831SAndroid Build Coastguard Worker  *
4663*7c568831SAndroid Build Coastguard Worker  * Converts a boolean to its number value
4664*7c568831SAndroid Build Coastguard Worker  *
4665*7c568831SAndroid Build Coastguard Worker  * Returns the number value
4666*7c568831SAndroid Build Coastguard Worker  */
4667*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastBooleanToNumber(int val)4668*7c568831SAndroid Build Coastguard Worker xmlXPathCastBooleanToNumber(int val) {
4669*7c568831SAndroid Build Coastguard Worker     if (val)
4670*7c568831SAndroid Build Coastguard Worker 	return(1.0);
4671*7c568831SAndroid Build Coastguard Worker     return(0.0);
4672*7c568831SAndroid Build Coastguard Worker }
4673*7c568831SAndroid Build Coastguard Worker 
4674*7c568831SAndroid Build Coastguard Worker /**
4675*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastStringToNumber:
4676*7c568831SAndroid Build Coastguard Worker  * @val:  a string
4677*7c568831SAndroid Build Coastguard Worker  *
4678*7c568831SAndroid Build Coastguard Worker  * Converts a string to its number value
4679*7c568831SAndroid Build Coastguard Worker  *
4680*7c568831SAndroid Build Coastguard Worker  * Returns the number value
4681*7c568831SAndroid Build Coastguard Worker  */
4682*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastStringToNumber(const xmlChar * val)4683*7c568831SAndroid Build Coastguard Worker xmlXPathCastStringToNumber(const xmlChar * val) {
4684*7c568831SAndroid Build Coastguard Worker     return(xmlXPathStringEvalNumber(val));
4685*7c568831SAndroid Build Coastguard Worker }
4686*7c568831SAndroid Build Coastguard Worker 
4687*7c568831SAndroid Build Coastguard Worker /**
4688*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeToNumberInternal:
4689*7c568831SAndroid Build Coastguard Worker  * @node:  a node
4690*7c568831SAndroid Build Coastguard Worker  *
4691*7c568831SAndroid Build Coastguard Worker  * Converts a node to its number value
4692*7c568831SAndroid Build Coastguard Worker  *
4693*7c568831SAndroid Build Coastguard Worker  * Returns the number value
4694*7c568831SAndroid Build Coastguard Worker  */
4695*7c568831SAndroid Build Coastguard Worker static double
xmlXPathNodeToNumberInternal(xmlXPathParserContextPtr ctxt,xmlNodePtr node)4696*7c568831SAndroid Build Coastguard Worker xmlXPathNodeToNumberInternal(xmlXPathParserContextPtr ctxt, xmlNodePtr node) {
4697*7c568831SAndroid Build Coastguard Worker     xmlChar *strval;
4698*7c568831SAndroid Build Coastguard Worker     double ret;
4699*7c568831SAndroid Build Coastguard Worker 
4700*7c568831SAndroid Build Coastguard Worker     if (node == NULL)
4701*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNAN);
4702*7c568831SAndroid Build Coastguard Worker     strval = xmlXPathCastNodeToString(node);
4703*7c568831SAndroid Build Coastguard Worker     if (strval == NULL) {
4704*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
4705*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNAN);
4706*7c568831SAndroid Build Coastguard Worker     }
4707*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathCastStringToNumber(strval);
4708*7c568831SAndroid Build Coastguard Worker     xmlFree(strval);
4709*7c568831SAndroid Build Coastguard Worker 
4710*7c568831SAndroid Build Coastguard Worker     return(ret);
4711*7c568831SAndroid Build Coastguard Worker }
4712*7c568831SAndroid Build Coastguard Worker 
4713*7c568831SAndroid Build Coastguard Worker /**
4714*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastNodeToNumber:
4715*7c568831SAndroid Build Coastguard Worker  * @node:  a node
4716*7c568831SAndroid Build Coastguard Worker  *
4717*7c568831SAndroid Build Coastguard Worker  * Converts a node to its number value
4718*7c568831SAndroid Build Coastguard Worker  *
4719*7c568831SAndroid Build Coastguard Worker  * Returns the number value
4720*7c568831SAndroid Build Coastguard Worker  */
4721*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastNodeToNumber(xmlNodePtr node)4722*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeToNumber (xmlNodePtr node) {
4723*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNodeToNumberInternal(NULL, node));
4724*7c568831SAndroid Build Coastguard Worker }
4725*7c568831SAndroid Build Coastguard Worker 
4726*7c568831SAndroid Build Coastguard Worker /**
4727*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastNodeSetToNumber:
4728*7c568831SAndroid Build Coastguard Worker  * @ns:  a node-set
4729*7c568831SAndroid Build Coastguard Worker  *
4730*7c568831SAndroid Build Coastguard Worker  * Converts a node-set to its number value
4731*7c568831SAndroid Build Coastguard Worker  *
4732*7c568831SAndroid Build Coastguard Worker  * Returns the number value
4733*7c568831SAndroid Build Coastguard Worker  */
4734*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastNodeSetToNumber(xmlNodeSetPtr ns)4735*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
4736*7c568831SAndroid Build Coastguard Worker     xmlChar *str;
4737*7c568831SAndroid Build Coastguard Worker     double ret;
4738*7c568831SAndroid Build Coastguard Worker 
4739*7c568831SAndroid Build Coastguard Worker     if (ns == NULL)
4740*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNAN);
4741*7c568831SAndroid Build Coastguard Worker     str = xmlXPathCastNodeSetToString(ns);
4742*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathCastStringToNumber(str);
4743*7c568831SAndroid Build Coastguard Worker     xmlFree(str);
4744*7c568831SAndroid Build Coastguard Worker     return(ret);
4745*7c568831SAndroid Build Coastguard Worker }
4746*7c568831SAndroid Build Coastguard Worker 
4747*7c568831SAndroid Build Coastguard Worker /**
4748*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastToNumber:
4749*7c568831SAndroid Build Coastguard Worker  * @val:  an XPath object
4750*7c568831SAndroid Build Coastguard Worker  *
4751*7c568831SAndroid Build Coastguard Worker  * Converts an XPath object to its number value
4752*7c568831SAndroid Build Coastguard Worker  *
4753*7c568831SAndroid Build Coastguard Worker  * Returns the number value
4754*7c568831SAndroid Build Coastguard Worker  */
4755*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastToNumber(xmlXPathObjectPtr val)4756*7c568831SAndroid Build Coastguard Worker xmlXPathCastToNumber(xmlXPathObjectPtr val) {
4757*7c568831SAndroid Build Coastguard Worker     return(xmlXPathCastToNumberInternal(NULL, val));
4758*7c568831SAndroid Build Coastguard Worker }
4759*7c568831SAndroid Build Coastguard Worker 
4760*7c568831SAndroid Build Coastguard Worker /**
4761*7c568831SAndroid Build Coastguard Worker  * xmlXPathConvertNumber:
4762*7c568831SAndroid Build Coastguard Worker  * @val:  an XPath object
4763*7c568831SAndroid Build Coastguard Worker  *
4764*7c568831SAndroid Build Coastguard Worker  * Converts an existing object to its number() equivalent
4765*7c568831SAndroid Build Coastguard Worker  *
4766*7c568831SAndroid Build Coastguard Worker  * Returns the new object, the old one is freed (or the operation
4767*7c568831SAndroid Build Coastguard Worker  *         is done directly on @val)
4768*7c568831SAndroid Build Coastguard Worker  */
4769*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertNumber(xmlXPathObjectPtr val)4770*7c568831SAndroid Build Coastguard Worker xmlXPathConvertNumber(xmlXPathObjectPtr val) {
4771*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
4772*7c568831SAndroid Build Coastguard Worker 
4773*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
4774*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNewFloat(0.0));
4775*7c568831SAndroid Build Coastguard Worker     if (val->type == XPATH_NUMBER)
4776*7c568831SAndroid Build Coastguard Worker 	return(val);
4777*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
4778*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeObject(val);
4779*7c568831SAndroid Build Coastguard Worker     return(ret);
4780*7c568831SAndroid Build Coastguard Worker }
4781*7c568831SAndroid Build Coastguard Worker 
4782*7c568831SAndroid Build Coastguard Worker /**
4783*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastNumberToBoolean:
4784*7c568831SAndroid Build Coastguard Worker  * @val:  a number
4785*7c568831SAndroid Build Coastguard Worker  *
4786*7c568831SAndroid Build Coastguard Worker  * Converts a number to its boolean value
4787*7c568831SAndroid Build Coastguard Worker  *
4788*7c568831SAndroid Build Coastguard Worker  * Returns the boolean value
4789*7c568831SAndroid Build Coastguard Worker  */
4790*7c568831SAndroid Build Coastguard Worker int
xmlXPathCastNumberToBoolean(double val)4791*7c568831SAndroid Build Coastguard Worker xmlXPathCastNumberToBoolean (double val) {
4792*7c568831SAndroid Build Coastguard Worker      if (xmlXPathIsNaN(val) || (val == 0.0))
4793*7c568831SAndroid Build Coastguard Worker 	 return(0);
4794*7c568831SAndroid Build Coastguard Worker      return(1);
4795*7c568831SAndroid Build Coastguard Worker }
4796*7c568831SAndroid Build Coastguard Worker 
4797*7c568831SAndroid Build Coastguard Worker /**
4798*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastStringToBoolean:
4799*7c568831SAndroid Build Coastguard Worker  * @val:  a string
4800*7c568831SAndroid Build Coastguard Worker  *
4801*7c568831SAndroid Build Coastguard Worker  * Converts a string to its boolean value
4802*7c568831SAndroid Build Coastguard Worker  *
4803*7c568831SAndroid Build Coastguard Worker  * Returns the boolean value
4804*7c568831SAndroid Build Coastguard Worker  */
4805*7c568831SAndroid Build Coastguard Worker int
xmlXPathCastStringToBoolean(const xmlChar * val)4806*7c568831SAndroid Build Coastguard Worker xmlXPathCastStringToBoolean (const xmlChar *val) {
4807*7c568831SAndroid Build Coastguard Worker     if ((val == NULL) || (xmlStrlen(val) == 0))
4808*7c568831SAndroid Build Coastguard Worker 	return(0);
4809*7c568831SAndroid Build Coastguard Worker     return(1);
4810*7c568831SAndroid Build Coastguard Worker }
4811*7c568831SAndroid Build Coastguard Worker 
4812*7c568831SAndroid Build Coastguard Worker /**
4813*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastNodeSetToBoolean:
4814*7c568831SAndroid Build Coastguard Worker  * @ns:  a node-set
4815*7c568831SAndroid Build Coastguard Worker  *
4816*7c568831SAndroid Build Coastguard Worker  * Converts a node-set to its boolean value
4817*7c568831SAndroid Build Coastguard Worker  *
4818*7c568831SAndroid Build Coastguard Worker  * Returns the boolean value
4819*7c568831SAndroid Build Coastguard Worker  */
4820*7c568831SAndroid Build Coastguard Worker int
xmlXPathCastNodeSetToBoolean(xmlNodeSetPtr ns)4821*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
4822*7c568831SAndroid Build Coastguard Worker     if ((ns == NULL) || (ns->nodeNr == 0))
4823*7c568831SAndroid Build Coastguard Worker 	return(0);
4824*7c568831SAndroid Build Coastguard Worker     return(1);
4825*7c568831SAndroid Build Coastguard Worker }
4826*7c568831SAndroid Build Coastguard Worker 
4827*7c568831SAndroid Build Coastguard Worker /**
4828*7c568831SAndroid Build Coastguard Worker  * xmlXPathCastToBoolean:
4829*7c568831SAndroid Build Coastguard Worker  * @val:  an XPath object
4830*7c568831SAndroid Build Coastguard Worker  *
4831*7c568831SAndroid Build Coastguard Worker  * Converts an XPath object to its boolean value
4832*7c568831SAndroid Build Coastguard Worker  *
4833*7c568831SAndroid Build Coastguard Worker  * Returns the boolean value
4834*7c568831SAndroid Build Coastguard Worker  */
4835*7c568831SAndroid Build Coastguard Worker int
xmlXPathCastToBoolean(xmlXPathObjectPtr val)4836*7c568831SAndroid Build Coastguard Worker xmlXPathCastToBoolean (xmlXPathObjectPtr val) {
4837*7c568831SAndroid Build Coastguard Worker     int ret = 0;
4838*7c568831SAndroid Build Coastguard Worker 
4839*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
4840*7c568831SAndroid Build Coastguard Worker 	return(0);
4841*7c568831SAndroid Build Coastguard Worker     switch (val->type) {
4842*7c568831SAndroid Build Coastguard Worker     case XPATH_UNDEFINED:
4843*7c568831SAndroid Build Coastguard Worker 	ret = 0;
4844*7c568831SAndroid Build Coastguard Worker 	break;
4845*7c568831SAndroid Build Coastguard Worker     case XPATH_NODESET:
4846*7c568831SAndroid Build Coastguard Worker     case XPATH_XSLT_TREE:
4847*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
4848*7c568831SAndroid Build Coastguard Worker 	break;
4849*7c568831SAndroid Build Coastguard Worker     case XPATH_STRING:
4850*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathCastStringToBoolean(val->stringval);
4851*7c568831SAndroid Build Coastguard Worker 	break;
4852*7c568831SAndroid Build Coastguard Worker     case XPATH_NUMBER:
4853*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathCastNumberToBoolean(val->floatval);
4854*7c568831SAndroid Build Coastguard Worker 	break;
4855*7c568831SAndroid Build Coastguard Worker     case XPATH_BOOLEAN:
4856*7c568831SAndroid Build Coastguard Worker 	ret = val->boolval;
4857*7c568831SAndroid Build Coastguard Worker 	break;
4858*7c568831SAndroid Build Coastguard Worker     case XPATH_USERS:
4859*7c568831SAndroid Build Coastguard Worker 	/* TODO */
4860*7c568831SAndroid Build Coastguard Worker 	ret = 0;
4861*7c568831SAndroid Build Coastguard Worker 	break;
4862*7c568831SAndroid Build Coastguard Worker     }
4863*7c568831SAndroid Build Coastguard Worker     return(ret);
4864*7c568831SAndroid Build Coastguard Worker }
4865*7c568831SAndroid Build Coastguard Worker 
4866*7c568831SAndroid Build Coastguard Worker 
4867*7c568831SAndroid Build Coastguard Worker /**
4868*7c568831SAndroid Build Coastguard Worker  * xmlXPathConvertBoolean:
4869*7c568831SAndroid Build Coastguard Worker  * @val:  an XPath object
4870*7c568831SAndroid Build Coastguard Worker  *
4871*7c568831SAndroid Build Coastguard Worker  * Converts an existing object to its boolean() equivalent
4872*7c568831SAndroid Build Coastguard Worker  *
4873*7c568831SAndroid Build Coastguard Worker  * Returns the new object, the old one is freed (or the operation
4874*7c568831SAndroid Build Coastguard Worker  *         is done directly on @val)
4875*7c568831SAndroid Build Coastguard Worker  */
4876*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertBoolean(xmlXPathObjectPtr val)4877*7c568831SAndroid Build Coastguard Worker xmlXPathConvertBoolean(xmlXPathObjectPtr val) {
4878*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr ret;
4879*7c568831SAndroid Build Coastguard Worker 
4880*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
4881*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathNewBoolean(0));
4882*7c568831SAndroid Build Coastguard Worker     if (val->type == XPATH_BOOLEAN)
4883*7c568831SAndroid Build Coastguard Worker 	return(val);
4884*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
4885*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeObject(val);
4886*7c568831SAndroid Build Coastguard Worker     return(ret);
4887*7c568831SAndroid Build Coastguard Worker }
4888*7c568831SAndroid Build Coastguard Worker 
4889*7c568831SAndroid Build Coastguard Worker /************************************************************************
4890*7c568831SAndroid Build Coastguard Worker  *									*
4891*7c568831SAndroid Build Coastguard Worker  *		Routines to handle XPath contexts			*
4892*7c568831SAndroid Build Coastguard Worker  *									*
4893*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
4894*7c568831SAndroid Build Coastguard Worker 
4895*7c568831SAndroid Build Coastguard Worker /**
4896*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewContext:
4897*7c568831SAndroid Build Coastguard Worker  * @doc:  the XML document
4898*7c568831SAndroid Build Coastguard Worker  *
4899*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathContext
4900*7c568831SAndroid Build Coastguard Worker  *
4901*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathContext just allocated. The caller will need to free it.
4902*7c568831SAndroid Build Coastguard Worker  */
4903*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr
xmlXPathNewContext(xmlDocPtr doc)4904*7c568831SAndroid Build Coastguard Worker xmlXPathNewContext(xmlDocPtr doc) {
4905*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ret;
4906*7c568831SAndroid Build Coastguard Worker 
4907*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
4908*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
4909*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4910*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathContext));
4911*7c568831SAndroid Build Coastguard Worker     ret->doc = doc;
4912*7c568831SAndroid Build Coastguard Worker     ret->node = NULL;
4913*7c568831SAndroid Build Coastguard Worker 
4914*7c568831SAndroid Build Coastguard Worker     ret->varHash = NULL;
4915*7c568831SAndroid Build Coastguard Worker 
4916*7c568831SAndroid Build Coastguard Worker     ret->nb_types = 0;
4917*7c568831SAndroid Build Coastguard Worker     ret->max_types = 0;
4918*7c568831SAndroid Build Coastguard Worker     ret->types = NULL;
4919*7c568831SAndroid Build Coastguard Worker 
4920*7c568831SAndroid Build Coastguard Worker     ret->nb_axis = 0;
4921*7c568831SAndroid Build Coastguard Worker     ret->max_axis = 0;
4922*7c568831SAndroid Build Coastguard Worker     ret->axis = NULL;
4923*7c568831SAndroid Build Coastguard Worker 
4924*7c568831SAndroid Build Coastguard Worker     ret->nsHash = NULL;
4925*7c568831SAndroid Build Coastguard Worker     ret->user = NULL;
4926*7c568831SAndroid Build Coastguard Worker 
4927*7c568831SAndroid Build Coastguard Worker     ret->contextSize = -1;
4928*7c568831SAndroid Build Coastguard Worker     ret->proximityPosition = -1;
4929*7c568831SAndroid Build Coastguard Worker 
4930*7c568831SAndroid Build Coastguard Worker #ifdef XP_DEFAULT_CACHE_ON
4931*7c568831SAndroid Build Coastguard Worker     if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
4932*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeContext(ret);
4933*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4934*7c568831SAndroid Build Coastguard Worker     }
4935*7c568831SAndroid Build Coastguard Worker #endif
4936*7c568831SAndroid Build Coastguard Worker 
4937*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterAllFunctions(ret);
4938*7c568831SAndroid Build Coastguard Worker 
4939*7c568831SAndroid Build Coastguard Worker     if (ret->lastError.code != XML_ERR_OK) {
4940*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeContext(ret);
4941*7c568831SAndroid Build Coastguard Worker 	return(NULL);
4942*7c568831SAndroid Build Coastguard Worker     }
4943*7c568831SAndroid Build Coastguard Worker 
4944*7c568831SAndroid Build Coastguard Worker     return(ret);
4945*7c568831SAndroid Build Coastguard Worker }
4946*7c568831SAndroid Build Coastguard Worker 
4947*7c568831SAndroid Build Coastguard Worker /**
4948*7c568831SAndroid Build Coastguard Worker  * xmlXPathFreeContext:
4949*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the context to free
4950*7c568831SAndroid Build Coastguard Worker  *
4951*7c568831SAndroid Build Coastguard Worker  * Free up an xmlXPathContext
4952*7c568831SAndroid Build Coastguard Worker  */
4953*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeContext(xmlXPathContextPtr ctxt)4954*7c568831SAndroid Build Coastguard Worker xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
4955*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return;
4956*7c568831SAndroid Build Coastguard Worker 
4957*7c568831SAndroid Build Coastguard Worker     if (ctxt->cache != NULL)
4958*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
4959*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisteredNsCleanup(ctxt);
4960*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisteredFuncsCleanup(ctxt);
4961*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisteredVariablesCleanup(ctxt);
4962*7c568831SAndroid Build Coastguard Worker     xmlResetError(&ctxt->lastError);
4963*7c568831SAndroid Build Coastguard Worker     xmlFree(ctxt);
4964*7c568831SAndroid Build Coastguard Worker }
4965*7c568831SAndroid Build Coastguard Worker 
4966*7c568831SAndroid Build Coastguard Worker /**
4967*7c568831SAndroid Build Coastguard Worker  * xmlXPathSetErrorHandler:
4968*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
4969*7c568831SAndroid Build Coastguard Worker  * @handler:  error handler
4970*7c568831SAndroid Build Coastguard Worker  * @data:  user data which will be passed to the handler
4971*7c568831SAndroid Build Coastguard Worker  *
4972*7c568831SAndroid Build Coastguard Worker  * Register a callback function that will be called on errors and
4973*7c568831SAndroid Build Coastguard Worker  * warnings. If handler is NULL, the error handler will be deactivated.
4974*7c568831SAndroid Build Coastguard Worker  *
4975*7c568831SAndroid Build Coastguard Worker  * Available since 2.13.0.
4976*7c568831SAndroid Build Coastguard Worker  */
4977*7c568831SAndroid Build Coastguard Worker void
xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt,xmlStructuredErrorFunc handler,void * data)4978*7c568831SAndroid Build Coastguard Worker xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt,
4979*7c568831SAndroid Build Coastguard Worker                         xmlStructuredErrorFunc handler, void *data) {
4980*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
4981*7c568831SAndroid Build Coastguard Worker         return;
4982*7c568831SAndroid Build Coastguard Worker 
4983*7c568831SAndroid Build Coastguard Worker     ctxt->error = handler;
4984*7c568831SAndroid Build Coastguard Worker     ctxt->userData = data;
4985*7c568831SAndroid Build Coastguard Worker }
4986*7c568831SAndroid Build Coastguard Worker 
4987*7c568831SAndroid Build Coastguard Worker /************************************************************************
4988*7c568831SAndroid Build Coastguard Worker  *									*
4989*7c568831SAndroid Build Coastguard Worker  *		Routines to handle XPath parser contexts		*
4990*7c568831SAndroid Build Coastguard Worker  *									*
4991*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
4992*7c568831SAndroid Build Coastguard Worker 
4993*7c568831SAndroid Build Coastguard Worker /**
4994*7c568831SAndroid Build Coastguard Worker  * xmlXPathNewParserContext:
4995*7c568831SAndroid Build Coastguard Worker  * @str:  the XPath expression
4996*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
4997*7c568831SAndroid Build Coastguard Worker  *
4998*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathParserContext
4999*7c568831SAndroid Build Coastguard Worker  *
5000*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathParserContext just allocated.
5001*7c568831SAndroid Build Coastguard Worker  */
5002*7c568831SAndroid Build Coastguard Worker xmlXPathParserContextPtr
xmlXPathNewParserContext(const xmlChar * str,xmlXPathContextPtr ctxt)5003*7c568831SAndroid Build Coastguard Worker xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
5004*7c568831SAndroid Build Coastguard Worker     xmlXPathParserContextPtr ret;
5005*7c568831SAndroid Build Coastguard Worker 
5006*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
5007*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
5008*7c568831SAndroid Build Coastguard Worker         xmlXPathErrMemory(ctxt);
5009*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5010*7c568831SAndroid Build Coastguard Worker     }
5011*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathParserContext));
5012*7c568831SAndroid Build Coastguard Worker     ret->cur = ret->base = str;
5013*7c568831SAndroid Build Coastguard Worker     ret->context = ctxt;
5014*7c568831SAndroid Build Coastguard Worker 
5015*7c568831SAndroid Build Coastguard Worker     ret->comp = xmlXPathNewCompExpr();
5016*7c568831SAndroid Build Coastguard Worker     if (ret->comp == NULL) {
5017*7c568831SAndroid Build Coastguard Worker         xmlXPathErrMemory(ctxt);
5018*7c568831SAndroid Build Coastguard Worker 	xmlFree(ret->valueTab);
5019*7c568831SAndroid Build Coastguard Worker 	xmlFree(ret);
5020*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5021*7c568831SAndroid Build Coastguard Worker     }
5022*7c568831SAndroid Build Coastguard Worker     if ((ctxt != NULL) && (ctxt->dict != NULL)) {
5023*7c568831SAndroid Build Coastguard Worker         ret->comp->dict = ctxt->dict;
5024*7c568831SAndroid Build Coastguard Worker 	xmlDictReference(ret->comp->dict);
5025*7c568831SAndroid Build Coastguard Worker     }
5026*7c568831SAndroid Build Coastguard Worker 
5027*7c568831SAndroid Build Coastguard Worker     return(ret);
5028*7c568831SAndroid Build Coastguard Worker }
5029*7c568831SAndroid Build Coastguard Worker 
5030*7c568831SAndroid Build Coastguard Worker /**
5031*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompParserContext:
5032*7c568831SAndroid Build Coastguard Worker  * @comp:  the XPath compiled expression
5033*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
5034*7c568831SAndroid Build Coastguard Worker  *
5035*7c568831SAndroid Build Coastguard Worker  * Create a new xmlXPathParserContext when processing a compiled expression
5036*7c568831SAndroid Build Coastguard Worker  *
5037*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathParserContext just allocated.
5038*7c568831SAndroid Build Coastguard Worker  */
5039*7c568831SAndroid Build Coastguard Worker static xmlXPathParserContextPtr
xmlXPathCompParserContext(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt)5040*7c568831SAndroid Build Coastguard Worker xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
5041*7c568831SAndroid Build Coastguard Worker     xmlXPathParserContextPtr ret;
5042*7c568831SAndroid Build Coastguard Worker 
5043*7c568831SAndroid Build Coastguard Worker     ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
5044*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
5045*7c568831SAndroid Build Coastguard Worker         xmlXPathErrMemory(ctxt);
5046*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5047*7c568831SAndroid Build Coastguard Worker     }
5048*7c568831SAndroid Build Coastguard Worker     memset(ret, 0 , sizeof(xmlXPathParserContext));
5049*7c568831SAndroid Build Coastguard Worker 
5050*7c568831SAndroid Build Coastguard Worker     /* Allocate the value stack */
5051*7c568831SAndroid Build Coastguard Worker     ret->valueTab = (xmlXPathObjectPtr *)
5052*7c568831SAndroid Build Coastguard Worker                      xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
5053*7c568831SAndroid Build Coastguard Worker     if (ret->valueTab == NULL) {
5054*7c568831SAndroid Build Coastguard Worker 	xmlFree(ret);
5055*7c568831SAndroid Build Coastguard Worker 	xmlXPathErrMemory(ctxt);
5056*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5057*7c568831SAndroid Build Coastguard Worker     }
5058*7c568831SAndroid Build Coastguard Worker     ret->valueNr = 0;
5059*7c568831SAndroid Build Coastguard Worker     ret->valueMax = 10;
5060*7c568831SAndroid Build Coastguard Worker     ret->value = NULL;
5061*7c568831SAndroid Build Coastguard Worker 
5062*7c568831SAndroid Build Coastguard Worker     ret->context = ctxt;
5063*7c568831SAndroid Build Coastguard Worker     ret->comp = comp;
5064*7c568831SAndroid Build Coastguard Worker 
5065*7c568831SAndroid Build Coastguard Worker     return(ret);
5066*7c568831SAndroid Build Coastguard Worker }
5067*7c568831SAndroid Build Coastguard Worker 
5068*7c568831SAndroid Build Coastguard Worker /**
5069*7c568831SAndroid Build Coastguard Worker  * xmlXPathFreeParserContext:
5070*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the context to free
5071*7c568831SAndroid Build Coastguard Worker  *
5072*7c568831SAndroid Build Coastguard Worker  * Free up an xmlXPathParserContext
5073*7c568831SAndroid Build Coastguard Worker  */
5074*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt)5075*7c568831SAndroid Build Coastguard Worker xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
5076*7c568831SAndroid Build Coastguard Worker     int i;
5077*7c568831SAndroid Build Coastguard Worker 
5078*7c568831SAndroid Build Coastguard Worker     if (ctxt->valueTab != NULL) {
5079*7c568831SAndroid Build Coastguard Worker         for (i = 0; i < ctxt->valueNr; i++) {
5080*7c568831SAndroid Build Coastguard Worker             if (ctxt->context)
5081*7c568831SAndroid Build Coastguard Worker                 xmlXPathReleaseObject(ctxt->context, ctxt->valueTab[i]);
5082*7c568831SAndroid Build Coastguard Worker             else
5083*7c568831SAndroid Build Coastguard Worker                 xmlXPathFreeObject(ctxt->valueTab[i]);
5084*7c568831SAndroid Build Coastguard Worker         }
5085*7c568831SAndroid Build Coastguard Worker         xmlFree(ctxt->valueTab);
5086*7c568831SAndroid Build Coastguard Worker     }
5087*7c568831SAndroid Build Coastguard Worker     if (ctxt->comp != NULL) {
5088*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
5089*7c568831SAndroid Build Coastguard Worker 	if (ctxt->comp->stream != NULL) {
5090*7c568831SAndroid Build Coastguard Worker 	    xmlFreePatternList(ctxt->comp->stream);
5091*7c568831SAndroid Build Coastguard Worker 	    ctxt->comp->stream = NULL;
5092*7c568831SAndroid Build Coastguard Worker 	}
5093*7c568831SAndroid Build Coastguard Worker #endif
5094*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeCompExpr(ctxt->comp);
5095*7c568831SAndroid Build Coastguard Worker     }
5096*7c568831SAndroid Build Coastguard Worker     xmlFree(ctxt);
5097*7c568831SAndroid Build Coastguard Worker }
5098*7c568831SAndroid Build Coastguard Worker 
5099*7c568831SAndroid Build Coastguard Worker /************************************************************************
5100*7c568831SAndroid Build Coastguard Worker  *									*
5101*7c568831SAndroid Build Coastguard Worker  *		The implicit core function library			*
5102*7c568831SAndroid Build Coastguard Worker  *									*
5103*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
5104*7c568831SAndroid Build Coastguard Worker 
5105*7c568831SAndroid Build Coastguard Worker /**
5106*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeValHash:
5107*7c568831SAndroid Build Coastguard Worker  * @node:  a node pointer
5108*7c568831SAndroid Build Coastguard Worker  *
5109*7c568831SAndroid Build Coastguard Worker  * Function computing the beginning of the string value of the node,
5110*7c568831SAndroid Build Coastguard Worker  * used to speed up comparisons
5111*7c568831SAndroid Build Coastguard Worker  *
5112*7c568831SAndroid Build Coastguard Worker  * Returns an int usable as a hash
5113*7c568831SAndroid Build Coastguard Worker  */
5114*7c568831SAndroid Build Coastguard Worker static unsigned int
xmlXPathNodeValHash(xmlNodePtr node)5115*7c568831SAndroid Build Coastguard Worker xmlXPathNodeValHash(xmlNodePtr node) {
5116*7c568831SAndroid Build Coastguard Worker     int len = 2;
5117*7c568831SAndroid Build Coastguard Worker     const xmlChar * string = NULL;
5118*7c568831SAndroid Build Coastguard Worker     xmlNodePtr tmp = NULL;
5119*7c568831SAndroid Build Coastguard Worker     unsigned int ret = 0;
5120*7c568831SAndroid Build Coastguard Worker 
5121*7c568831SAndroid Build Coastguard Worker     if (node == NULL)
5122*7c568831SAndroid Build Coastguard Worker 	return(0);
5123*7c568831SAndroid Build Coastguard Worker 
5124*7c568831SAndroid Build Coastguard Worker     if (node->type == XML_DOCUMENT_NODE) {
5125*7c568831SAndroid Build Coastguard Worker 	tmp = xmlDocGetRootElement((xmlDocPtr) node);
5126*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL)
5127*7c568831SAndroid Build Coastguard Worker 	    node = node->children;
5128*7c568831SAndroid Build Coastguard Worker 	else
5129*7c568831SAndroid Build Coastguard Worker 	    node = tmp;
5130*7c568831SAndroid Build Coastguard Worker 
5131*7c568831SAndroid Build Coastguard Worker 	if (node == NULL)
5132*7c568831SAndroid Build Coastguard Worker 	    return(0);
5133*7c568831SAndroid Build Coastguard Worker     }
5134*7c568831SAndroid Build Coastguard Worker 
5135*7c568831SAndroid Build Coastguard Worker     switch (node->type) {
5136*7c568831SAndroid Build Coastguard Worker 	case XML_COMMENT_NODE:
5137*7c568831SAndroid Build Coastguard Worker 	case XML_PI_NODE:
5138*7c568831SAndroid Build Coastguard Worker 	case XML_CDATA_SECTION_NODE:
5139*7c568831SAndroid Build Coastguard Worker 	case XML_TEXT_NODE:
5140*7c568831SAndroid Build Coastguard Worker 	    string = node->content;
5141*7c568831SAndroid Build Coastguard Worker 	    if (string == NULL)
5142*7c568831SAndroid Build Coastguard Worker 		return(0);
5143*7c568831SAndroid Build Coastguard Worker 	    if (string[0] == 0)
5144*7c568831SAndroid Build Coastguard Worker 		return(0);
5145*7c568831SAndroid Build Coastguard Worker 	    return(string[0] + (string[1] << 8));
5146*7c568831SAndroid Build Coastguard Worker 	case XML_NAMESPACE_DECL:
5147*7c568831SAndroid Build Coastguard Worker 	    string = ((xmlNsPtr)node)->href;
5148*7c568831SAndroid Build Coastguard Worker 	    if (string == NULL)
5149*7c568831SAndroid Build Coastguard Worker 		return(0);
5150*7c568831SAndroid Build Coastguard Worker 	    if (string[0] == 0)
5151*7c568831SAndroid Build Coastguard Worker 		return(0);
5152*7c568831SAndroid Build Coastguard Worker 	    return(string[0] + (string[1] << 8));
5153*7c568831SAndroid Build Coastguard Worker 	case XML_ATTRIBUTE_NODE:
5154*7c568831SAndroid Build Coastguard Worker 	    tmp = ((xmlAttrPtr) node)->children;
5155*7c568831SAndroid Build Coastguard Worker 	    break;
5156*7c568831SAndroid Build Coastguard Worker 	case XML_ELEMENT_NODE:
5157*7c568831SAndroid Build Coastguard Worker 	    tmp = node->children;
5158*7c568831SAndroid Build Coastguard Worker 	    break;
5159*7c568831SAndroid Build Coastguard Worker 	default:
5160*7c568831SAndroid Build Coastguard Worker 	    return(0);
5161*7c568831SAndroid Build Coastguard Worker     }
5162*7c568831SAndroid Build Coastguard Worker     while (tmp != NULL) {
5163*7c568831SAndroid Build Coastguard Worker 	switch (tmp->type) {
5164*7c568831SAndroid Build Coastguard Worker 	    case XML_CDATA_SECTION_NODE:
5165*7c568831SAndroid Build Coastguard Worker 	    case XML_TEXT_NODE:
5166*7c568831SAndroid Build Coastguard Worker 		string = tmp->content;
5167*7c568831SAndroid Build Coastguard Worker 		break;
5168*7c568831SAndroid Build Coastguard Worker 	    default:
5169*7c568831SAndroid Build Coastguard Worker                 string = NULL;
5170*7c568831SAndroid Build Coastguard Worker 		break;
5171*7c568831SAndroid Build Coastguard Worker 	}
5172*7c568831SAndroid Build Coastguard Worker 	if ((string != NULL) && (string[0] != 0)) {
5173*7c568831SAndroid Build Coastguard Worker 	    if (len == 1) {
5174*7c568831SAndroid Build Coastguard Worker 		return(ret + (string[0] << 8));
5175*7c568831SAndroid Build Coastguard Worker 	    }
5176*7c568831SAndroid Build Coastguard Worker 	    if (string[1] == 0) {
5177*7c568831SAndroid Build Coastguard Worker 		len = 1;
5178*7c568831SAndroid Build Coastguard Worker 		ret = string[0];
5179*7c568831SAndroid Build Coastguard Worker 	    } else {
5180*7c568831SAndroid Build Coastguard Worker 		return(string[0] + (string[1] << 8));
5181*7c568831SAndroid Build Coastguard Worker 	    }
5182*7c568831SAndroid Build Coastguard Worker 	}
5183*7c568831SAndroid Build Coastguard Worker 	/*
5184*7c568831SAndroid Build Coastguard Worker 	 * Skip to next node
5185*7c568831SAndroid Build Coastguard Worker 	 */
5186*7c568831SAndroid Build Coastguard Worker         if ((tmp->children != NULL) &&
5187*7c568831SAndroid Build Coastguard Worker             (tmp->type != XML_DTD_NODE) &&
5188*7c568831SAndroid Build Coastguard Worker             (tmp->type != XML_ENTITY_REF_NODE) &&
5189*7c568831SAndroid Build Coastguard Worker             (tmp->children->type != XML_ENTITY_DECL)) {
5190*7c568831SAndroid Build Coastguard Worker             tmp = tmp->children;
5191*7c568831SAndroid Build Coastguard Worker             continue;
5192*7c568831SAndroid Build Coastguard Worker 	}
5193*7c568831SAndroid Build Coastguard Worker 	if (tmp == node)
5194*7c568831SAndroid Build Coastguard Worker 	    break;
5195*7c568831SAndroid Build Coastguard Worker 
5196*7c568831SAndroid Build Coastguard Worker 	if (tmp->next != NULL) {
5197*7c568831SAndroid Build Coastguard Worker 	    tmp = tmp->next;
5198*7c568831SAndroid Build Coastguard Worker 	    continue;
5199*7c568831SAndroid Build Coastguard Worker 	}
5200*7c568831SAndroid Build Coastguard Worker 
5201*7c568831SAndroid Build Coastguard Worker 	do {
5202*7c568831SAndroid Build Coastguard Worker 	    tmp = tmp->parent;
5203*7c568831SAndroid Build Coastguard Worker 	    if (tmp == NULL)
5204*7c568831SAndroid Build Coastguard Worker 		break;
5205*7c568831SAndroid Build Coastguard Worker 	    if (tmp == node) {
5206*7c568831SAndroid Build Coastguard Worker 		tmp = NULL;
5207*7c568831SAndroid Build Coastguard Worker 		break;
5208*7c568831SAndroid Build Coastguard Worker 	    }
5209*7c568831SAndroid Build Coastguard Worker 	    if (tmp->next != NULL) {
5210*7c568831SAndroid Build Coastguard Worker 		tmp = tmp->next;
5211*7c568831SAndroid Build Coastguard Worker 		break;
5212*7c568831SAndroid Build Coastguard Worker 	    }
5213*7c568831SAndroid Build Coastguard Worker 	} while (tmp != NULL);
5214*7c568831SAndroid Build Coastguard Worker     }
5215*7c568831SAndroid Build Coastguard Worker     return(ret);
5216*7c568831SAndroid Build Coastguard Worker }
5217*7c568831SAndroid Build Coastguard Worker 
5218*7c568831SAndroid Build Coastguard Worker /**
5219*7c568831SAndroid Build Coastguard Worker  * xmlXPathStringHash:
5220*7c568831SAndroid Build Coastguard Worker  * @string:  a string
5221*7c568831SAndroid Build Coastguard Worker  *
5222*7c568831SAndroid Build Coastguard Worker  * Function computing the beginning of the string value of the node,
5223*7c568831SAndroid Build Coastguard Worker  * used to speed up comparisons
5224*7c568831SAndroid Build Coastguard Worker  *
5225*7c568831SAndroid Build Coastguard Worker  * Returns an int usable as a hash
5226*7c568831SAndroid Build Coastguard Worker  */
5227*7c568831SAndroid Build Coastguard Worker static unsigned int
xmlXPathStringHash(const xmlChar * string)5228*7c568831SAndroid Build Coastguard Worker xmlXPathStringHash(const xmlChar * string) {
5229*7c568831SAndroid Build Coastguard Worker     if (string == NULL)
5230*7c568831SAndroid Build Coastguard Worker 	return(0);
5231*7c568831SAndroid Build Coastguard Worker     if (string[0] == 0)
5232*7c568831SAndroid Build Coastguard Worker 	return(0);
5233*7c568831SAndroid Build Coastguard Worker     return(string[0] + (string[1] << 8));
5234*7c568831SAndroid Build Coastguard Worker }
5235*7c568831SAndroid Build Coastguard Worker 
5236*7c568831SAndroid Build Coastguard Worker /**
5237*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompareNodeSetFloat:
5238*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
5239*7c568831SAndroid Build Coastguard Worker  * @inf:  less than (1) or greater than (0)
5240*7c568831SAndroid Build Coastguard Worker  * @strict:  is the comparison strict
5241*7c568831SAndroid Build Coastguard Worker  * @arg:  the node set
5242*7c568831SAndroid Build Coastguard Worker  * @f:  the value
5243*7c568831SAndroid Build Coastguard Worker  *
5244*7c568831SAndroid Build Coastguard Worker  * Implement the compare operation between a nodeset and a number
5245*7c568831SAndroid Build Coastguard Worker  *     @ns < @val    (1, 1, ...
5246*7c568831SAndroid Build Coastguard Worker  *     @ns <= @val   (1, 0, ...
5247*7c568831SAndroid Build Coastguard Worker  *     @ns > @val    (0, 1, ...
5248*7c568831SAndroid Build Coastguard Worker  *     @ns >= @val   (0, 0, ...
5249*7c568831SAndroid Build Coastguard Worker  *
5250*7c568831SAndroid Build Coastguard Worker  * If one object to be compared is a node-set and the other is a number,
5251*7c568831SAndroid Build Coastguard Worker  * then the comparison will be true if and only if there is a node in the
5252*7c568831SAndroid Build Coastguard Worker  * node-set such that the result of performing the comparison on the number
5253*7c568831SAndroid Build Coastguard Worker  * to be compared and on the result of converting the string-value of that
5254*7c568831SAndroid Build Coastguard Worker  * node to a number using the number function is true.
5255*7c568831SAndroid Build Coastguard Worker  *
5256*7c568831SAndroid Build Coastguard Worker  * Returns 0 or 1 depending on the results of the test.
5257*7c568831SAndroid Build Coastguard Worker  */
5258*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr f)5259*7c568831SAndroid Build Coastguard Worker xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
5260*7c568831SAndroid Build Coastguard Worker 	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr f) {
5261*7c568831SAndroid Build Coastguard Worker     int i, ret = 0;
5262*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ns;
5263*7c568831SAndroid Build Coastguard Worker     xmlChar *str2;
5264*7c568831SAndroid Build Coastguard Worker 
5265*7c568831SAndroid Build Coastguard Worker     if ((f == NULL) || (arg == NULL) ||
5266*7c568831SAndroid Build Coastguard Worker 	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
5267*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, arg);
5268*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, f);
5269*7c568831SAndroid Build Coastguard Worker         return(0);
5270*7c568831SAndroid Build Coastguard Worker     }
5271*7c568831SAndroid Build Coastguard Worker     ns = arg->nodesetval;
5272*7c568831SAndroid Build Coastguard Worker     if (ns != NULL) {
5273*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ns->nodeNr;i++) {
5274*7c568831SAndroid Build Coastguard Worker 	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5275*7c568831SAndroid Build Coastguard Worker 	     if (str2 != NULL) {
5276*7c568831SAndroid Build Coastguard Worker 		 valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2));
5277*7c568831SAndroid Build Coastguard Worker 		 xmlFree(str2);
5278*7c568831SAndroid Build Coastguard Worker 		 xmlXPathNumberFunction(ctxt, 1);
5279*7c568831SAndroid Build Coastguard Worker 		 valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, f));
5280*7c568831SAndroid Build Coastguard Worker 		 ret = xmlXPathCompareValues(ctxt, inf, strict);
5281*7c568831SAndroid Build Coastguard Worker 		 if (ret)
5282*7c568831SAndroid Build Coastguard Worker 		     break;
5283*7c568831SAndroid Build Coastguard Worker 	     } else {
5284*7c568831SAndroid Build Coastguard Worker                  xmlXPathPErrMemory(ctxt);
5285*7c568831SAndroid Build Coastguard Worker              }
5286*7c568831SAndroid Build Coastguard Worker 	}
5287*7c568831SAndroid Build Coastguard Worker     }
5288*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg);
5289*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, f);
5290*7c568831SAndroid Build Coastguard Worker     return(ret);
5291*7c568831SAndroid Build Coastguard Worker }
5292*7c568831SAndroid Build Coastguard Worker 
5293*7c568831SAndroid Build Coastguard Worker /**
5294*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompareNodeSetString:
5295*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
5296*7c568831SAndroid Build Coastguard Worker  * @inf:  less than (1) or greater than (0)
5297*7c568831SAndroid Build Coastguard Worker  * @strict:  is the comparison strict
5298*7c568831SAndroid Build Coastguard Worker  * @arg:  the node set
5299*7c568831SAndroid Build Coastguard Worker  * @s:  the value
5300*7c568831SAndroid Build Coastguard Worker  *
5301*7c568831SAndroid Build Coastguard Worker  * Implement the compare operation between a nodeset and a string
5302*7c568831SAndroid Build Coastguard Worker  *     @ns < @val    (1, 1, ...
5303*7c568831SAndroid Build Coastguard Worker  *     @ns <= @val   (1, 0, ...
5304*7c568831SAndroid Build Coastguard Worker  *     @ns > @val    (0, 1, ...
5305*7c568831SAndroid Build Coastguard Worker  *     @ns >= @val   (0, 0, ...
5306*7c568831SAndroid Build Coastguard Worker  *
5307*7c568831SAndroid Build Coastguard Worker  * If one object to be compared is a node-set and the other is a string,
5308*7c568831SAndroid Build Coastguard Worker  * then the comparison will be true if and only if there is a node in
5309*7c568831SAndroid Build Coastguard Worker  * the node-set such that the result of performing the comparison on the
5310*7c568831SAndroid Build Coastguard Worker  * string-value of the node and the other string is true.
5311*7c568831SAndroid Build Coastguard Worker  *
5312*7c568831SAndroid Build Coastguard Worker  * Returns 0 or 1 depending on the results of the test.
5313*7c568831SAndroid Build Coastguard Worker  */
5314*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr s)5315*7c568831SAndroid Build Coastguard Worker xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
5316*7c568831SAndroid Build Coastguard Worker 	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr s) {
5317*7c568831SAndroid Build Coastguard Worker     int i, ret = 0;
5318*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ns;
5319*7c568831SAndroid Build Coastguard Worker     xmlChar *str2;
5320*7c568831SAndroid Build Coastguard Worker 
5321*7c568831SAndroid Build Coastguard Worker     if ((s == NULL) || (arg == NULL) ||
5322*7c568831SAndroid Build Coastguard Worker 	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
5323*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, arg);
5324*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, s);
5325*7c568831SAndroid Build Coastguard Worker         return(0);
5326*7c568831SAndroid Build Coastguard Worker     }
5327*7c568831SAndroid Build Coastguard Worker     ns = arg->nodesetval;
5328*7c568831SAndroid Build Coastguard Worker     if (ns != NULL) {
5329*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ns->nodeNr;i++) {
5330*7c568831SAndroid Build Coastguard Worker 	     str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5331*7c568831SAndroid Build Coastguard Worker 	     if (str2 != NULL) {
5332*7c568831SAndroid Build Coastguard Worker 		 valuePush(ctxt,
5333*7c568831SAndroid Build Coastguard Worker 			   xmlXPathCacheNewString(ctxt, str2));
5334*7c568831SAndroid Build Coastguard Worker 		 xmlFree(str2);
5335*7c568831SAndroid Build Coastguard Worker 		 valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, s));
5336*7c568831SAndroid Build Coastguard Worker 		 ret = xmlXPathCompareValues(ctxt, inf, strict);
5337*7c568831SAndroid Build Coastguard Worker 		 if (ret)
5338*7c568831SAndroid Build Coastguard Worker 		     break;
5339*7c568831SAndroid Build Coastguard Worker 	     } else {
5340*7c568831SAndroid Build Coastguard Worker                  xmlXPathPErrMemory(ctxt);
5341*7c568831SAndroid Build Coastguard Worker              }
5342*7c568831SAndroid Build Coastguard Worker 	}
5343*7c568831SAndroid Build Coastguard Worker     }
5344*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg);
5345*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, s);
5346*7c568831SAndroid Build Coastguard Worker     return(ret);
5347*7c568831SAndroid Build Coastguard Worker }
5348*7c568831SAndroid Build Coastguard Worker 
5349*7c568831SAndroid Build Coastguard Worker /**
5350*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompareNodeSets:
5351*7c568831SAndroid Build Coastguard Worker  * @inf:  less than (1) or greater than (0)
5352*7c568831SAndroid Build Coastguard Worker  * @strict:  is the comparison strict
5353*7c568831SAndroid Build Coastguard Worker  * @arg1:  the first node set object
5354*7c568831SAndroid Build Coastguard Worker  * @arg2:  the second node set object
5355*7c568831SAndroid Build Coastguard Worker  *
5356*7c568831SAndroid Build Coastguard Worker  * Implement the compare operation on nodesets:
5357*7c568831SAndroid Build Coastguard Worker  *
5358*7c568831SAndroid Build Coastguard Worker  * If both objects to be compared are node-sets, then the comparison
5359*7c568831SAndroid Build Coastguard Worker  * will be true if and only if there is a node in the first node-set
5360*7c568831SAndroid Build Coastguard Worker  * and a node in the second node-set such that the result of performing
5361*7c568831SAndroid Build Coastguard Worker  * the comparison on the string-values of the two nodes is true.
5362*7c568831SAndroid Build Coastguard Worker  * ....
5363*7c568831SAndroid Build Coastguard Worker  * When neither object to be compared is a node-set and the operator
5364*7c568831SAndroid Build Coastguard Worker  * is <=, <, >= or >, then the objects are compared by converting both
5365*7c568831SAndroid Build Coastguard Worker  * objects to numbers and comparing the numbers according to IEEE 754.
5366*7c568831SAndroid Build Coastguard Worker  * ....
5367*7c568831SAndroid Build Coastguard Worker  * The number function converts its argument to a number as follows:
5368*7c568831SAndroid Build Coastguard Worker  *  - a string that consists of optional whitespace followed by an
5369*7c568831SAndroid Build Coastguard Worker  *    optional minus sign followed by a Number followed by whitespace
5370*7c568831SAndroid Build Coastguard Worker  *    is converted to the IEEE 754 number that is nearest (according
5371*7c568831SAndroid Build Coastguard Worker  *    to the IEEE 754 round-to-nearest rule) to the mathematical value
5372*7c568831SAndroid Build Coastguard Worker  *    represented by the string; any other string is converted to NaN
5373*7c568831SAndroid Build Coastguard Worker  *
5374*7c568831SAndroid Build Coastguard Worker  * Conclusion all nodes need to be converted first to their string value
5375*7c568831SAndroid Build Coastguard Worker  * and then the comparison must be done when possible
5376*7c568831SAndroid Build Coastguard Worker  */
5377*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2)5378*7c568831SAndroid Build Coastguard Worker xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt, int inf, int strict,
5379*7c568831SAndroid Build Coastguard Worker 	                xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
5380*7c568831SAndroid Build Coastguard Worker     int i, j, init = 0;
5381*7c568831SAndroid Build Coastguard Worker     double val1;
5382*7c568831SAndroid Build Coastguard Worker     double *values2;
5383*7c568831SAndroid Build Coastguard Worker     int ret = 0;
5384*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ns1;
5385*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ns2;
5386*7c568831SAndroid Build Coastguard Worker 
5387*7c568831SAndroid Build Coastguard Worker     if ((arg1 == NULL) ||
5388*7c568831SAndroid Build Coastguard Worker 	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) {
5389*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg2);
5390*7c568831SAndroid Build Coastguard Worker         return(0);
5391*7c568831SAndroid Build Coastguard Worker     }
5392*7c568831SAndroid Build Coastguard Worker     if ((arg2 == NULL) ||
5393*7c568831SAndroid Build Coastguard Worker 	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) {
5394*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg1);
5395*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg2);
5396*7c568831SAndroid Build Coastguard Worker         return(0);
5397*7c568831SAndroid Build Coastguard Worker     }
5398*7c568831SAndroid Build Coastguard Worker 
5399*7c568831SAndroid Build Coastguard Worker     ns1 = arg1->nodesetval;
5400*7c568831SAndroid Build Coastguard Worker     ns2 = arg2->nodesetval;
5401*7c568831SAndroid Build Coastguard Worker 
5402*7c568831SAndroid Build Coastguard Worker     if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
5403*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg1);
5404*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg2);
5405*7c568831SAndroid Build Coastguard Worker 	return(0);
5406*7c568831SAndroid Build Coastguard Worker     }
5407*7c568831SAndroid Build Coastguard Worker     if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
5408*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg1);
5409*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg2);
5410*7c568831SAndroid Build Coastguard Worker 	return(0);
5411*7c568831SAndroid Build Coastguard Worker     }
5412*7c568831SAndroid Build Coastguard Worker 
5413*7c568831SAndroid Build Coastguard Worker     values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
5414*7c568831SAndroid Build Coastguard Worker     if (values2 == NULL) {
5415*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
5416*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg1);
5417*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg2);
5418*7c568831SAndroid Build Coastguard Worker 	return(0);
5419*7c568831SAndroid Build Coastguard Worker     }
5420*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < ns1->nodeNr;i++) {
5421*7c568831SAndroid Build Coastguard Worker 	val1 = xmlXPathNodeToNumberInternal(ctxt, ns1->nodeTab[i]);
5422*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathIsNaN(val1))
5423*7c568831SAndroid Build Coastguard Worker 	    continue;
5424*7c568831SAndroid Build Coastguard Worker 	for (j = 0;j < ns2->nodeNr;j++) {
5425*7c568831SAndroid Build Coastguard Worker 	    if (init == 0) {
5426*7c568831SAndroid Build Coastguard Worker 		values2[j] = xmlXPathNodeToNumberInternal(ctxt,
5427*7c568831SAndroid Build Coastguard Worker                                                           ns2->nodeTab[j]);
5428*7c568831SAndroid Build Coastguard Worker 	    }
5429*7c568831SAndroid Build Coastguard Worker 	    if (xmlXPathIsNaN(values2[j]))
5430*7c568831SAndroid Build Coastguard Worker 		continue;
5431*7c568831SAndroid Build Coastguard Worker 	    if (inf && strict)
5432*7c568831SAndroid Build Coastguard Worker 		ret = (val1 < values2[j]);
5433*7c568831SAndroid Build Coastguard Worker 	    else if (inf && !strict)
5434*7c568831SAndroid Build Coastguard Worker 		ret = (val1 <= values2[j]);
5435*7c568831SAndroid Build Coastguard Worker 	    else if (!inf && strict)
5436*7c568831SAndroid Build Coastguard Worker 		ret = (val1 > values2[j]);
5437*7c568831SAndroid Build Coastguard Worker 	    else if (!inf && !strict)
5438*7c568831SAndroid Build Coastguard Worker 		ret = (val1 >= values2[j]);
5439*7c568831SAndroid Build Coastguard Worker 	    if (ret)
5440*7c568831SAndroid Build Coastguard Worker 		break;
5441*7c568831SAndroid Build Coastguard Worker 	}
5442*7c568831SAndroid Build Coastguard Worker 	if (ret)
5443*7c568831SAndroid Build Coastguard Worker 	    break;
5444*7c568831SAndroid Build Coastguard Worker 	init = 1;
5445*7c568831SAndroid Build Coastguard Worker     }
5446*7c568831SAndroid Build Coastguard Worker     xmlFree(values2);
5447*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeObject(arg1);
5448*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeObject(arg2);
5449*7c568831SAndroid Build Coastguard Worker     return(ret);
5450*7c568831SAndroid Build Coastguard Worker }
5451*7c568831SAndroid Build Coastguard Worker 
5452*7c568831SAndroid Build Coastguard Worker /**
5453*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompareNodeSetValue:
5454*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
5455*7c568831SAndroid Build Coastguard Worker  * @inf:  less than (1) or greater than (0)
5456*7c568831SAndroid Build Coastguard Worker  * @strict:  is the comparison strict
5457*7c568831SAndroid Build Coastguard Worker  * @arg:  the node set
5458*7c568831SAndroid Build Coastguard Worker  * @val:  the value
5459*7c568831SAndroid Build Coastguard Worker  *
5460*7c568831SAndroid Build Coastguard Worker  * Implement the compare operation between a nodeset and a value
5461*7c568831SAndroid Build Coastguard Worker  *     @ns < @val    (1, 1, ...
5462*7c568831SAndroid Build Coastguard Worker  *     @ns <= @val   (1, 0, ...
5463*7c568831SAndroid Build Coastguard Worker  *     @ns > @val    (0, 1, ...
5464*7c568831SAndroid Build Coastguard Worker  *     @ns >= @val   (0, 0, ...
5465*7c568831SAndroid Build Coastguard Worker  *
5466*7c568831SAndroid Build Coastguard Worker  * If one object to be compared is a node-set and the other is a boolean,
5467*7c568831SAndroid Build Coastguard Worker  * then the comparison will be true if and only if the result of performing
5468*7c568831SAndroid Build Coastguard Worker  * the comparison on the boolean and on the result of converting
5469*7c568831SAndroid Build Coastguard Worker  * the node-set to a boolean using the boolean function is true.
5470*7c568831SAndroid Build Coastguard Worker  *
5471*7c568831SAndroid Build Coastguard Worker  * Returns 0 or 1 depending on the results of the test.
5472*7c568831SAndroid Build Coastguard Worker  */
5473*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr val)5474*7c568831SAndroid Build Coastguard Worker xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
5475*7c568831SAndroid Build Coastguard Worker 	                    xmlXPathObjectPtr arg, xmlXPathObjectPtr val) {
5476*7c568831SAndroid Build Coastguard Worker     if ((val == NULL) || (arg == NULL) ||
5477*7c568831SAndroid Build Coastguard Worker 	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5478*7c568831SAndroid Build Coastguard Worker         return(0);
5479*7c568831SAndroid Build Coastguard Worker 
5480*7c568831SAndroid Build Coastguard Worker     switch(val->type) {
5481*7c568831SAndroid Build Coastguard Worker         case XPATH_NUMBER:
5482*7c568831SAndroid Build Coastguard Worker 	    return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
5483*7c568831SAndroid Build Coastguard Worker         case XPATH_NODESET:
5484*7c568831SAndroid Build Coastguard Worker         case XPATH_XSLT_TREE:
5485*7c568831SAndroid Build Coastguard Worker 	    return(xmlXPathCompareNodeSets(ctxt, inf, strict, arg, val));
5486*7c568831SAndroid Build Coastguard Worker         case XPATH_STRING:
5487*7c568831SAndroid Build Coastguard Worker 	    return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
5488*7c568831SAndroid Build Coastguard Worker         case XPATH_BOOLEAN:
5489*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, arg);
5490*7c568831SAndroid Build Coastguard Worker 	    xmlXPathBooleanFunction(ctxt, 1);
5491*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, val);
5492*7c568831SAndroid Build Coastguard Worker 	    return(xmlXPathCompareValues(ctxt, inf, strict));
5493*7c568831SAndroid Build Coastguard Worker 	default:
5494*7c568831SAndroid Build Coastguard Worker             xmlXPathReleaseObject(ctxt->context, arg);
5495*7c568831SAndroid Build Coastguard Worker             xmlXPathReleaseObject(ctxt->context, val);
5496*7c568831SAndroid Build Coastguard Worker             XP_ERROR0(XPATH_INVALID_TYPE);
5497*7c568831SAndroid Build Coastguard Worker     }
5498*7c568831SAndroid Build Coastguard Worker     return(0);
5499*7c568831SAndroid Build Coastguard Worker }
5500*7c568831SAndroid Build Coastguard Worker 
5501*7c568831SAndroid Build Coastguard Worker /**
5502*7c568831SAndroid Build Coastguard Worker  * xmlXPathEqualNodeSetString:
5503*7c568831SAndroid Build Coastguard Worker  * @arg:  the nodeset object argument
5504*7c568831SAndroid Build Coastguard Worker  * @str:  the string to compare to.
5505*7c568831SAndroid Build Coastguard Worker  * @neq:  flag to show whether for '=' (0) or '!=' (1)
5506*7c568831SAndroid Build Coastguard Worker  *
5507*7c568831SAndroid Build Coastguard Worker  * Implement the equal operation on XPath objects content: @arg1 == @arg2
5508*7c568831SAndroid Build Coastguard Worker  * If one object to be compared is a node-set and the other is a string,
5509*7c568831SAndroid Build Coastguard Worker  * then the comparison will be true if and only if there is a node in
5510*7c568831SAndroid Build Coastguard Worker  * the node-set such that the result of performing the comparison on the
5511*7c568831SAndroid Build Coastguard Worker  * string-value of the node and the other string is true.
5512*7c568831SAndroid Build Coastguard Worker  *
5513*7c568831SAndroid Build Coastguard Worker  * Returns 0 or 1 depending on the results of the test.
5514*7c568831SAndroid Build Coastguard Worker  */
5515*7c568831SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSetString(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg,const xmlChar * str,int neq)5516*7c568831SAndroid Build Coastguard Worker xmlXPathEqualNodeSetString(xmlXPathParserContextPtr ctxt,
5517*7c568831SAndroid Build Coastguard Worker                            xmlXPathObjectPtr arg, const xmlChar * str, int neq)
5518*7c568831SAndroid Build Coastguard Worker {
5519*7c568831SAndroid Build Coastguard Worker     int i;
5520*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ns;
5521*7c568831SAndroid Build Coastguard Worker     xmlChar *str2;
5522*7c568831SAndroid Build Coastguard Worker     unsigned int hash;
5523*7c568831SAndroid Build Coastguard Worker 
5524*7c568831SAndroid Build Coastguard Worker     if ((str == NULL) || (arg == NULL) ||
5525*7c568831SAndroid Build Coastguard Worker         ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5526*7c568831SAndroid Build Coastguard Worker         return (0);
5527*7c568831SAndroid Build Coastguard Worker     ns = arg->nodesetval;
5528*7c568831SAndroid Build Coastguard Worker     /*
5529*7c568831SAndroid Build Coastguard Worker      * A NULL nodeset compared with a string is always false
5530*7c568831SAndroid Build Coastguard Worker      * (since there is no node equal, and no node not equal)
5531*7c568831SAndroid Build Coastguard Worker      */
5532*7c568831SAndroid Build Coastguard Worker     if ((ns == NULL) || (ns->nodeNr <= 0) )
5533*7c568831SAndroid Build Coastguard Worker         return (0);
5534*7c568831SAndroid Build Coastguard Worker     hash = xmlXPathStringHash(str);
5535*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < ns->nodeNr; i++) {
5536*7c568831SAndroid Build Coastguard Worker         if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
5537*7c568831SAndroid Build Coastguard Worker             str2 = xmlNodeGetContent(ns->nodeTab[i]);
5538*7c568831SAndroid Build Coastguard Worker             if (str2 == NULL) {
5539*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
5540*7c568831SAndroid Build Coastguard Worker                 return(0);
5541*7c568831SAndroid Build Coastguard Worker             }
5542*7c568831SAndroid Build Coastguard Worker             if (xmlStrEqual(str, str2)) {
5543*7c568831SAndroid Build Coastguard Worker                 xmlFree(str2);
5544*7c568831SAndroid Build Coastguard Worker 		if (neq)
5545*7c568831SAndroid Build Coastguard Worker 		    continue;
5546*7c568831SAndroid Build Coastguard Worker                 return (1);
5547*7c568831SAndroid Build Coastguard Worker             } else if (neq) {
5548*7c568831SAndroid Build Coastguard Worker 		xmlFree(str2);
5549*7c568831SAndroid Build Coastguard Worker 		return (1);
5550*7c568831SAndroid Build Coastguard Worker 	    }
5551*7c568831SAndroid Build Coastguard Worker             xmlFree(str2);
5552*7c568831SAndroid Build Coastguard Worker         } else if (neq)
5553*7c568831SAndroid Build Coastguard Worker 	    return (1);
5554*7c568831SAndroid Build Coastguard Worker     }
5555*7c568831SAndroid Build Coastguard Worker     return (0);
5556*7c568831SAndroid Build Coastguard Worker }
5557*7c568831SAndroid Build Coastguard Worker 
5558*7c568831SAndroid Build Coastguard Worker /**
5559*7c568831SAndroid Build Coastguard Worker  * xmlXPathEqualNodeSetFloat:
5560*7c568831SAndroid Build Coastguard Worker  * @arg:  the nodeset object argument
5561*7c568831SAndroid Build Coastguard Worker  * @f:  the float to compare to
5562*7c568831SAndroid Build Coastguard Worker  * @neq:  flag to show whether to compare '=' (0) or '!=' (1)
5563*7c568831SAndroid Build Coastguard Worker  *
5564*7c568831SAndroid Build Coastguard Worker  * Implement the equal operation on XPath objects content: @arg1 == @arg2
5565*7c568831SAndroid Build Coastguard Worker  * If one object to be compared is a node-set and the other is a number,
5566*7c568831SAndroid Build Coastguard Worker  * then the comparison will be true if and only if there is a node in
5567*7c568831SAndroid Build Coastguard Worker  * the node-set such that the result of performing the comparison on the
5568*7c568831SAndroid Build Coastguard Worker  * number to be compared and on the result of converting the string-value
5569*7c568831SAndroid Build Coastguard Worker  * of that node to a number using the number function is true.
5570*7c568831SAndroid Build Coastguard Worker  *
5571*7c568831SAndroid Build Coastguard Worker  * Returns 0 or 1 depending on the results of the test.
5572*7c568831SAndroid Build Coastguard Worker  */
5573*7c568831SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg,double f,int neq)5574*7c568831SAndroid Build Coastguard Worker xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
5575*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg, double f, int neq) {
5576*7c568831SAndroid Build Coastguard Worker   int i, ret=0;
5577*7c568831SAndroid Build Coastguard Worker   xmlNodeSetPtr ns;
5578*7c568831SAndroid Build Coastguard Worker   xmlChar *str2;
5579*7c568831SAndroid Build Coastguard Worker   xmlXPathObjectPtr val;
5580*7c568831SAndroid Build Coastguard Worker   double v;
5581*7c568831SAndroid Build Coastguard Worker 
5582*7c568831SAndroid Build Coastguard Worker     if ((arg == NULL) ||
5583*7c568831SAndroid Build Coastguard Worker 	((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5584*7c568831SAndroid Build Coastguard Worker         return(0);
5585*7c568831SAndroid Build Coastguard Worker 
5586*7c568831SAndroid Build Coastguard Worker     ns = arg->nodesetval;
5587*7c568831SAndroid Build Coastguard Worker     if (ns != NULL) {
5588*7c568831SAndroid Build Coastguard Worker 	for (i=0;i<ns->nodeNr;i++) {
5589*7c568831SAndroid Build Coastguard Worker 	    str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5590*7c568831SAndroid Build Coastguard Worker 	    if (str2 != NULL) {
5591*7c568831SAndroid Build Coastguard Worker 		valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2));
5592*7c568831SAndroid Build Coastguard Worker 		xmlFree(str2);
5593*7c568831SAndroid Build Coastguard Worker 		xmlXPathNumberFunction(ctxt, 1);
5594*7c568831SAndroid Build Coastguard Worker                 CHECK_ERROR0;
5595*7c568831SAndroid Build Coastguard Worker 		val = valuePop(ctxt);
5596*7c568831SAndroid Build Coastguard Worker 		v = val->floatval;
5597*7c568831SAndroid Build Coastguard Worker 		xmlXPathReleaseObject(ctxt->context, val);
5598*7c568831SAndroid Build Coastguard Worker 		if (!xmlXPathIsNaN(v)) {
5599*7c568831SAndroid Build Coastguard Worker 		    if ((!neq) && (v==f)) {
5600*7c568831SAndroid Build Coastguard Worker 			ret = 1;
5601*7c568831SAndroid Build Coastguard Worker 			break;
5602*7c568831SAndroid Build Coastguard Worker 		    } else if ((neq) && (v!=f)) {
5603*7c568831SAndroid Build Coastguard Worker 			ret = 1;
5604*7c568831SAndroid Build Coastguard Worker 			break;
5605*7c568831SAndroid Build Coastguard Worker 		    }
5606*7c568831SAndroid Build Coastguard Worker 		} else {	/* NaN is unequal to any value */
5607*7c568831SAndroid Build Coastguard Worker 		    if (neq)
5608*7c568831SAndroid Build Coastguard Worker 			ret = 1;
5609*7c568831SAndroid Build Coastguard Worker 		}
5610*7c568831SAndroid Build Coastguard Worker 	    } else {
5611*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
5612*7c568831SAndroid Build Coastguard Worker             }
5613*7c568831SAndroid Build Coastguard Worker 	}
5614*7c568831SAndroid Build Coastguard Worker     }
5615*7c568831SAndroid Build Coastguard Worker 
5616*7c568831SAndroid Build Coastguard Worker     return(ret);
5617*7c568831SAndroid Build Coastguard Worker }
5618*7c568831SAndroid Build Coastguard Worker 
5619*7c568831SAndroid Build Coastguard Worker 
5620*7c568831SAndroid Build Coastguard Worker /**
5621*7c568831SAndroid Build Coastguard Worker  * xmlXPathEqualNodeSets:
5622*7c568831SAndroid Build Coastguard Worker  * @arg1:  first nodeset object argument
5623*7c568831SAndroid Build Coastguard Worker  * @arg2:  second nodeset object argument
5624*7c568831SAndroid Build Coastguard Worker  * @neq:   flag to show whether to test '=' (0) or '!=' (1)
5625*7c568831SAndroid Build Coastguard Worker  *
5626*7c568831SAndroid Build Coastguard Worker  * Implement the equal / not equal operation on XPath nodesets:
5627*7c568831SAndroid Build Coastguard Worker  * @arg1 == @arg2  or  @arg1 != @arg2
5628*7c568831SAndroid Build Coastguard Worker  * If both objects to be compared are node-sets, then the comparison
5629*7c568831SAndroid Build Coastguard Worker  * will be true if and only if there is a node in the first node-set and
5630*7c568831SAndroid Build Coastguard Worker  * a node in the second node-set such that the result of performing the
5631*7c568831SAndroid Build Coastguard Worker  * comparison on the string-values of the two nodes is true.
5632*7c568831SAndroid Build Coastguard Worker  *
5633*7c568831SAndroid Build Coastguard Worker  * (needless to say, this is a costly operation)
5634*7c568831SAndroid Build Coastguard Worker  *
5635*7c568831SAndroid Build Coastguard Worker  * Returns 0 or 1 depending on the results of the test.
5636*7c568831SAndroid Build Coastguard Worker  */
5637*7c568831SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSets(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2,int neq)5638*7c568831SAndroid Build Coastguard Worker xmlXPathEqualNodeSets(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr arg1,
5639*7c568831SAndroid Build Coastguard Worker                       xmlXPathObjectPtr arg2, int neq) {
5640*7c568831SAndroid Build Coastguard Worker     int i, j;
5641*7c568831SAndroid Build Coastguard Worker     unsigned int *hashs1;
5642*7c568831SAndroid Build Coastguard Worker     unsigned int *hashs2;
5643*7c568831SAndroid Build Coastguard Worker     xmlChar **values1;
5644*7c568831SAndroid Build Coastguard Worker     xmlChar **values2;
5645*7c568831SAndroid Build Coastguard Worker     int ret = 0;
5646*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ns1;
5647*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ns2;
5648*7c568831SAndroid Build Coastguard Worker 
5649*7c568831SAndroid Build Coastguard Worker     if ((arg1 == NULL) ||
5650*7c568831SAndroid Build Coastguard Worker 	((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)))
5651*7c568831SAndroid Build Coastguard Worker         return(0);
5652*7c568831SAndroid Build Coastguard Worker     if ((arg2 == NULL) ||
5653*7c568831SAndroid Build Coastguard Worker 	((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE)))
5654*7c568831SAndroid Build Coastguard Worker         return(0);
5655*7c568831SAndroid Build Coastguard Worker 
5656*7c568831SAndroid Build Coastguard Worker     ns1 = arg1->nodesetval;
5657*7c568831SAndroid Build Coastguard Worker     ns2 = arg2->nodesetval;
5658*7c568831SAndroid Build Coastguard Worker 
5659*7c568831SAndroid Build Coastguard Worker     if ((ns1 == NULL) || (ns1->nodeNr <= 0))
5660*7c568831SAndroid Build Coastguard Worker 	return(0);
5661*7c568831SAndroid Build Coastguard Worker     if ((ns2 == NULL) || (ns2->nodeNr <= 0))
5662*7c568831SAndroid Build Coastguard Worker 	return(0);
5663*7c568831SAndroid Build Coastguard Worker 
5664*7c568831SAndroid Build Coastguard Worker     /*
5665*7c568831SAndroid Build Coastguard Worker      * for equal, check if there is a node pertaining to both sets
5666*7c568831SAndroid Build Coastguard Worker      */
5667*7c568831SAndroid Build Coastguard Worker     if (neq == 0)
5668*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ns1->nodeNr;i++)
5669*7c568831SAndroid Build Coastguard Worker 	    for (j = 0;j < ns2->nodeNr;j++)
5670*7c568831SAndroid Build Coastguard Worker 		if (ns1->nodeTab[i] == ns2->nodeTab[j])
5671*7c568831SAndroid Build Coastguard Worker 		    return(1);
5672*7c568831SAndroid Build Coastguard Worker 
5673*7c568831SAndroid Build Coastguard Worker     values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
5674*7c568831SAndroid Build Coastguard Worker     if (values1 == NULL) {
5675*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
5676*7c568831SAndroid Build Coastguard Worker 	return(0);
5677*7c568831SAndroid Build Coastguard Worker     }
5678*7c568831SAndroid Build Coastguard Worker     hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
5679*7c568831SAndroid Build Coastguard Worker     if (hashs1 == NULL) {
5680*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
5681*7c568831SAndroid Build Coastguard Worker 	xmlFree(values1);
5682*7c568831SAndroid Build Coastguard Worker 	return(0);
5683*7c568831SAndroid Build Coastguard Worker     }
5684*7c568831SAndroid Build Coastguard Worker     memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
5685*7c568831SAndroid Build Coastguard Worker     values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
5686*7c568831SAndroid Build Coastguard Worker     if (values2 == NULL) {
5687*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
5688*7c568831SAndroid Build Coastguard Worker 	xmlFree(hashs1);
5689*7c568831SAndroid Build Coastguard Worker 	xmlFree(values1);
5690*7c568831SAndroid Build Coastguard Worker 	return(0);
5691*7c568831SAndroid Build Coastguard Worker     }
5692*7c568831SAndroid Build Coastguard Worker     hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
5693*7c568831SAndroid Build Coastguard Worker     if (hashs2 == NULL) {
5694*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
5695*7c568831SAndroid Build Coastguard Worker 	xmlFree(hashs1);
5696*7c568831SAndroid Build Coastguard Worker 	xmlFree(values1);
5697*7c568831SAndroid Build Coastguard Worker 	xmlFree(values2);
5698*7c568831SAndroid Build Coastguard Worker 	return(0);
5699*7c568831SAndroid Build Coastguard Worker     }
5700*7c568831SAndroid Build Coastguard Worker     memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *));
5701*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < ns1->nodeNr;i++) {
5702*7c568831SAndroid Build Coastguard Worker 	hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]);
5703*7c568831SAndroid Build Coastguard Worker 	for (j = 0;j < ns2->nodeNr;j++) {
5704*7c568831SAndroid Build Coastguard Worker 	    if (i == 0)
5705*7c568831SAndroid Build Coastguard Worker 		hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]);
5706*7c568831SAndroid Build Coastguard Worker 	    if (hashs1[i] != hashs2[j]) {
5707*7c568831SAndroid Build Coastguard Worker 		if (neq) {
5708*7c568831SAndroid Build Coastguard Worker 		    ret = 1;
5709*7c568831SAndroid Build Coastguard Worker 		    break;
5710*7c568831SAndroid Build Coastguard Worker 		}
5711*7c568831SAndroid Build Coastguard Worker 	    }
5712*7c568831SAndroid Build Coastguard Worker 	    else {
5713*7c568831SAndroid Build Coastguard Worker 		if (values1[i] == NULL) {
5714*7c568831SAndroid Build Coastguard Worker 		    values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
5715*7c568831SAndroid Build Coastguard Worker                     if (values1[i] == NULL)
5716*7c568831SAndroid Build Coastguard Worker                         xmlXPathPErrMemory(ctxt);
5717*7c568831SAndroid Build Coastguard Worker                 }
5718*7c568831SAndroid Build Coastguard Worker 		if (values2[j] == NULL) {
5719*7c568831SAndroid Build Coastguard Worker 		    values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
5720*7c568831SAndroid Build Coastguard Worker                     if (values2[j] == NULL)
5721*7c568831SAndroid Build Coastguard Worker                         xmlXPathPErrMemory(ctxt);
5722*7c568831SAndroid Build Coastguard Worker                 }
5723*7c568831SAndroid Build Coastguard Worker 		ret = xmlStrEqual(values1[i], values2[j]) ^ neq;
5724*7c568831SAndroid Build Coastguard Worker 		if (ret)
5725*7c568831SAndroid Build Coastguard Worker 		    break;
5726*7c568831SAndroid Build Coastguard Worker 	    }
5727*7c568831SAndroid Build Coastguard Worker 	}
5728*7c568831SAndroid Build Coastguard Worker 	if (ret)
5729*7c568831SAndroid Build Coastguard Worker 	    break;
5730*7c568831SAndroid Build Coastguard Worker     }
5731*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < ns1->nodeNr;i++)
5732*7c568831SAndroid Build Coastguard Worker 	if (values1[i] != NULL)
5733*7c568831SAndroid Build Coastguard Worker 	    xmlFree(values1[i]);
5734*7c568831SAndroid Build Coastguard Worker     for (j = 0;j < ns2->nodeNr;j++)
5735*7c568831SAndroid Build Coastguard Worker 	if (values2[j] != NULL)
5736*7c568831SAndroid Build Coastguard Worker 	    xmlFree(values2[j]);
5737*7c568831SAndroid Build Coastguard Worker     xmlFree(values1);
5738*7c568831SAndroid Build Coastguard Worker     xmlFree(values2);
5739*7c568831SAndroid Build Coastguard Worker     xmlFree(hashs1);
5740*7c568831SAndroid Build Coastguard Worker     xmlFree(hashs2);
5741*7c568831SAndroid Build Coastguard Worker     return(ret);
5742*7c568831SAndroid Build Coastguard Worker }
5743*7c568831SAndroid Build Coastguard Worker 
5744*7c568831SAndroid Build Coastguard Worker static int
xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2)5745*7c568831SAndroid Build Coastguard Worker xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
5746*7c568831SAndroid Build Coastguard Worker   xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
5747*7c568831SAndroid Build Coastguard Worker     int ret = 0;
5748*7c568831SAndroid Build Coastguard Worker     /*
5749*7c568831SAndroid Build Coastguard Worker      *At this point we are assured neither arg1 nor arg2
5750*7c568831SAndroid Build Coastguard Worker      *is a nodeset, so we can just pick the appropriate routine.
5751*7c568831SAndroid Build Coastguard Worker      */
5752*7c568831SAndroid Build Coastguard Worker     switch (arg1->type) {
5753*7c568831SAndroid Build Coastguard Worker         case XPATH_UNDEFINED:
5754*7c568831SAndroid Build Coastguard Worker 	    break;
5755*7c568831SAndroid Build Coastguard Worker         case XPATH_BOOLEAN:
5756*7c568831SAndroid Build Coastguard Worker 	    switch (arg2->type) {
5757*7c568831SAndroid Build Coastguard Worker 	        case XPATH_UNDEFINED:
5758*7c568831SAndroid Build Coastguard Worker 		    break;
5759*7c568831SAndroid Build Coastguard Worker 		case XPATH_BOOLEAN:
5760*7c568831SAndroid Build Coastguard Worker 		    ret = (arg1->boolval == arg2->boolval);
5761*7c568831SAndroid Build Coastguard Worker 		    break;
5762*7c568831SAndroid Build Coastguard Worker 		case XPATH_NUMBER:
5763*7c568831SAndroid Build Coastguard Worker 		    ret = (arg1->boolval ==
5764*7c568831SAndroid Build Coastguard Worker 			   xmlXPathCastNumberToBoolean(arg2->floatval));
5765*7c568831SAndroid Build Coastguard Worker 		    break;
5766*7c568831SAndroid Build Coastguard Worker 		case XPATH_STRING:
5767*7c568831SAndroid Build Coastguard Worker 		    if ((arg2->stringval == NULL) ||
5768*7c568831SAndroid Build Coastguard Worker 			(arg2->stringval[0] == 0)) ret = 0;
5769*7c568831SAndroid Build Coastguard Worker 		    else
5770*7c568831SAndroid Build Coastguard Worker 			ret = 1;
5771*7c568831SAndroid Build Coastguard Worker 		    ret = (arg1->boolval == ret);
5772*7c568831SAndroid Build Coastguard Worker 		    break;
5773*7c568831SAndroid Build Coastguard Worker 		case XPATH_USERS:
5774*7c568831SAndroid Build Coastguard Worker 		    /* TODO */
5775*7c568831SAndroid Build Coastguard Worker 		    break;
5776*7c568831SAndroid Build Coastguard Worker 		case XPATH_NODESET:
5777*7c568831SAndroid Build Coastguard Worker 		case XPATH_XSLT_TREE:
5778*7c568831SAndroid Build Coastguard Worker 		    break;
5779*7c568831SAndroid Build Coastguard Worker 	    }
5780*7c568831SAndroid Build Coastguard Worker 	    break;
5781*7c568831SAndroid Build Coastguard Worker         case XPATH_NUMBER:
5782*7c568831SAndroid Build Coastguard Worker 	    switch (arg2->type) {
5783*7c568831SAndroid Build Coastguard Worker 	        case XPATH_UNDEFINED:
5784*7c568831SAndroid Build Coastguard Worker 		    break;
5785*7c568831SAndroid Build Coastguard Worker 		case XPATH_BOOLEAN:
5786*7c568831SAndroid Build Coastguard Worker 		    ret = (arg2->boolval==
5787*7c568831SAndroid Build Coastguard Worker 			   xmlXPathCastNumberToBoolean(arg1->floatval));
5788*7c568831SAndroid Build Coastguard Worker 		    break;
5789*7c568831SAndroid Build Coastguard Worker 		case XPATH_STRING:
5790*7c568831SAndroid Build Coastguard Worker 		    valuePush(ctxt, arg2);
5791*7c568831SAndroid Build Coastguard Worker 		    xmlXPathNumberFunction(ctxt, 1);
5792*7c568831SAndroid Build Coastguard Worker 		    arg2 = valuePop(ctxt);
5793*7c568831SAndroid Build Coastguard Worker                     if (ctxt->error)
5794*7c568831SAndroid Build Coastguard Worker                         break;
5795*7c568831SAndroid Build Coastguard Worker                     /* Falls through. */
5796*7c568831SAndroid Build Coastguard Worker 		case XPATH_NUMBER:
5797*7c568831SAndroid Build Coastguard Worker 		    /* Hand check NaN and Infinity equalities */
5798*7c568831SAndroid Build Coastguard Worker 		    if (xmlXPathIsNaN(arg1->floatval) ||
5799*7c568831SAndroid Build Coastguard Worker 			    xmlXPathIsNaN(arg2->floatval)) {
5800*7c568831SAndroid Build Coastguard Worker 		        ret = 0;
5801*7c568831SAndroid Build Coastguard Worker 		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
5802*7c568831SAndroid Build Coastguard Worker 		        if (xmlXPathIsInf(arg2->floatval) == 1)
5803*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
5804*7c568831SAndroid Build Coastguard Worker 			else
5805*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
5806*7c568831SAndroid Build Coastguard Worker 		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
5807*7c568831SAndroid Build Coastguard Worker 			if (xmlXPathIsInf(arg2->floatval) == -1)
5808*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
5809*7c568831SAndroid Build Coastguard Worker 			else
5810*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
5811*7c568831SAndroid Build Coastguard Worker 		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
5812*7c568831SAndroid Build Coastguard Worker 			if (xmlXPathIsInf(arg1->floatval) == 1)
5813*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
5814*7c568831SAndroid Build Coastguard Worker 			else
5815*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
5816*7c568831SAndroid Build Coastguard Worker 		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
5817*7c568831SAndroid Build Coastguard Worker 			if (xmlXPathIsInf(arg1->floatval) == -1)
5818*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
5819*7c568831SAndroid Build Coastguard Worker 			else
5820*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
5821*7c568831SAndroid Build Coastguard Worker 		    } else {
5822*7c568831SAndroid Build Coastguard Worker 		        ret = (arg1->floatval == arg2->floatval);
5823*7c568831SAndroid Build Coastguard Worker 		    }
5824*7c568831SAndroid Build Coastguard Worker 		    break;
5825*7c568831SAndroid Build Coastguard Worker 		case XPATH_USERS:
5826*7c568831SAndroid Build Coastguard Worker 		    /* TODO */
5827*7c568831SAndroid Build Coastguard Worker 		    break;
5828*7c568831SAndroid Build Coastguard Worker 		case XPATH_NODESET:
5829*7c568831SAndroid Build Coastguard Worker 		case XPATH_XSLT_TREE:
5830*7c568831SAndroid Build Coastguard Worker 		    break;
5831*7c568831SAndroid Build Coastguard Worker 	    }
5832*7c568831SAndroid Build Coastguard Worker 	    break;
5833*7c568831SAndroid Build Coastguard Worker         case XPATH_STRING:
5834*7c568831SAndroid Build Coastguard Worker 	    switch (arg2->type) {
5835*7c568831SAndroid Build Coastguard Worker 	        case XPATH_UNDEFINED:
5836*7c568831SAndroid Build Coastguard Worker 		    break;
5837*7c568831SAndroid Build Coastguard Worker 		case XPATH_BOOLEAN:
5838*7c568831SAndroid Build Coastguard Worker 		    if ((arg1->stringval == NULL) ||
5839*7c568831SAndroid Build Coastguard Worker 			(arg1->stringval[0] == 0)) ret = 0;
5840*7c568831SAndroid Build Coastguard Worker 		    else
5841*7c568831SAndroid Build Coastguard Worker 			ret = 1;
5842*7c568831SAndroid Build Coastguard Worker 		    ret = (arg2->boolval == ret);
5843*7c568831SAndroid Build Coastguard Worker 		    break;
5844*7c568831SAndroid Build Coastguard Worker 		case XPATH_STRING:
5845*7c568831SAndroid Build Coastguard Worker 		    ret = xmlStrEqual(arg1->stringval, arg2->stringval);
5846*7c568831SAndroid Build Coastguard Worker 		    break;
5847*7c568831SAndroid Build Coastguard Worker 		case XPATH_NUMBER:
5848*7c568831SAndroid Build Coastguard Worker 		    valuePush(ctxt, arg1);
5849*7c568831SAndroid Build Coastguard Worker 		    xmlXPathNumberFunction(ctxt, 1);
5850*7c568831SAndroid Build Coastguard Worker 		    arg1 = valuePop(ctxt);
5851*7c568831SAndroid Build Coastguard Worker                     if (ctxt->error)
5852*7c568831SAndroid Build Coastguard Worker                         break;
5853*7c568831SAndroid Build Coastguard Worker 		    /* Hand check NaN and Infinity equalities */
5854*7c568831SAndroid Build Coastguard Worker 		    if (xmlXPathIsNaN(arg1->floatval) ||
5855*7c568831SAndroid Build Coastguard Worker 			    xmlXPathIsNaN(arg2->floatval)) {
5856*7c568831SAndroid Build Coastguard Worker 		        ret = 0;
5857*7c568831SAndroid Build Coastguard Worker 		    } else if (xmlXPathIsInf(arg1->floatval) == 1) {
5858*7c568831SAndroid Build Coastguard Worker 			if (xmlXPathIsInf(arg2->floatval) == 1)
5859*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
5860*7c568831SAndroid Build Coastguard Worker 			else
5861*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
5862*7c568831SAndroid Build Coastguard Worker 		    } else if (xmlXPathIsInf(arg1->floatval) == -1) {
5863*7c568831SAndroid Build Coastguard Worker 			if (xmlXPathIsInf(arg2->floatval) == -1)
5864*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
5865*7c568831SAndroid Build Coastguard Worker 			else
5866*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
5867*7c568831SAndroid Build Coastguard Worker 		    } else if (xmlXPathIsInf(arg2->floatval) == 1) {
5868*7c568831SAndroid Build Coastguard Worker 			if (xmlXPathIsInf(arg1->floatval) == 1)
5869*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
5870*7c568831SAndroid Build Coastguard Worker 			else
5871*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
5872*7c568831SAndroid Build Coastguard Worker 		    } else if (xmlXPathIsInf(arg2->floatval) == -1) {
5873*7c568831SAndroid Build Coastguard Worker 			if (xmlXPathIsInf(arg1->floatval) == -1)
5874*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
5875*7c568831SAndroid Build Coastguard Worker 			else
5876*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
5877*7c568831SAndroid Build Coastguard Worker 		    } else {
5878*7c568831SAndroid Build Coastguard Worker 		        ret = (arg1->floatval == arg2->floatval);
5879*7c568831SAndroid Build Coastguard Worker 		    }
5880*7c568831SAndroid Build Coastguard Worker 		    break;
5881*7c568831SAndroid Build Coastguard Worker 		case XPATH_USERS:
5882*7c568831SAndroid Build Coastguard Worker 		    /* TODO */
5883*7c568831SAndroid Build Coastguard Worker 		    break;
5884*7c568831SAndroid Build Coastguard Worker 		case XPATH_NODESET:
5885*7c568831SAndroid Build Coastguard Worker 		case XPATH_XSLT_TREE:
5886*7c568831SAndroid Build Coastguard Worker 		    break;
5887*7c568831SAndroid Build Coastguard Worker 	    }
5888*7c568831SAndroid Build Coastguard Worker 	    break;
5889*7c568831SAndroid Build Coastguard Worker         case XPATH_USERS:
5890*7c568831SAndroid Build Coastguard Worker 	    /* TODO */
5891*7c568831SAndroid Build Coastguard Worker 	    break;
5892*7c568831SAndroid Build Coastguard Worker 	case XPATH_NODESET:
5893*7c568831SAndroid Build Coastguard Worker 	case XPATH_XSLT_TREE:
5894*7c568831SAndroid Build Coastguard Worker 	    break;
5895*7c568831SAndroid Build Coastguard Worker     }
5896*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg1);
5897*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg2);
5898*7c568831SAndroid Build Coastguard Worker     return(ret);
5899*7c568831SAndroid Build Coastguard Worker }
5900*7c568831SAndroid Build Coastguard Worker 
5901*7c568831SAndroid Build Coastguard Worker /**
5902*7c568831SAndroid Build Coastguard Worker  * xmlXPathEqualValues:
5903*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
5904*7c568831SAndroid Build Coastguard Worker  *
5905*7c568831SAndroid Build Coastguard Worker  * Implement the equal operation on XPath objects content: @arg1 == @arg2
5906*7c568831SAndroid Build Coastguard Worker  *
5907*7c568831SAndroid Build Coastguard Worker  * Returns 0 or 1 depending on the results of the test.
5908*7c568831SAndroid Build Coastguard Worker  */
5909*7c568831SAndroid Build Coastguard Worker int
xmlXPathEqualValues(xmlXPathParserContextPtr ctxt)5910*7c568831SAndroid Build Coastguard Worker xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
5911*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg1, arg2, argtmp;
5912*7c568831SAndroid Build Coastguard Worker     int ret = 0;
5913*7c568831SAndroid Build Coastguard Worker 
5914*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
5915*7c568831SAndroid Build Coastguard Worker     arg2 = valuePop(ctxt);
5916*7c568831SAndroid Build Coastguard Worker     arg1 = valuePop(ctxt);
5917*7c568831SAndroid Build Coastguard Worker     if ((arg1 == NULL) || (arg2 == NULL)) {
5918*7c568831SAndroid Build Coastguard Worker 	if (arg1 != NULL)
5919*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg1);
5920*7c568831SAndroid Build Coastguard Worker 	else
5921*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg2);
5922*7c568831SAndroid Build Coastguard Worker 	XP_ERROR0(XPATH_INVALID_OPERAND);
5923*7c568831SAndroid Build Coastguard Worker     }
5924*7c568831SAndroid Build Coastguard Worker 
5925*7c568831SAndroid Build Coastguard Worker     if (arg1 == arg2) {
5926*7c568831SAndroid Build Coastguard Worker 	xmlXPathFreeObject(arg1);
5927*7c568831SAndroid Build Coastguard Worker         return(1);
5928*7c568831SAndroid Build Coastguard Worker     }
5929*7c568831SAndroid Build Coastguard Worker 
5930*7c568831SAndroid Build Coastguard Worker     /*
5931*7c568831SAndroid Build Coastguard Worker      *If either argument is a nodeset, it's a 'special case'
5932*7c568831SAndroid Build Coastguard Worker      */
5933*7c568831SAndroid Build Coastguard Worker     if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
5934*7c568831SAndroid Build Coastguard Worker       (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
5935*7c568831SAndroid Build Coastguard Worker 	/*
5936*7c568831SAndroid Build Coastguard Worker 	 *Hack it to assure arg1 is the nodeset
5937*7c568831SAndroid Build Coastguard Worker 	 */
5938*7c568831SAndroid Build Coastguard Worker 	if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
5939*7c568831SAndroid Build Coastguard Worker 		argtmp = arg2;
5940*7c568831SAndroid Build Coastguard Worker 		arg2 = arg1;
5941*7c568831SAndroid Build Coastguard Worker 		arg1 = argtmp;
5942*7c568831SAndroid Build Coastguard Worker 	}
5943*7c568831SAndroid Build Coastguard Worker 	switch (arg2->type) {
5944*7c568831SAndroid Build Coastguard Worker 	    case XPATH_UNDEFINED:
5945*7c568831SAndroid Build Coastguard Worker 		break;
5946*7c568831SAndroid Build Coastguard Worker 	    case XPATH_NODESET:
5947*7c568831SAndroid Build Coastguard Worker 	    case XPATH_XSLT_TREE:
5948*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 0);
5949*7c568831SAndroid Build Coastguard Worker 		break;
5950*7c568831SAndroid Build Coastguard Worker 	    case XPATH_BOOLEAN:
5951*7c568831SAndroid Build Coastguard Worker 		if ((arg1->nodesetval == NULL) ||
5952*7c568831SAndroid Build Coastguard Worker 		  (arg1->nodesetval->nodeNr == 0)) ret = 0;
5953*7c568831SAndroid Build Coastguard Worker 		else
5954*7c568831SAndroid Build Coastguard Worker 		    ret = 1;
5955*7c568831SAndroid Build Coastguard Worker 		ret = (ret == arg2->boolval);
5956*7c568831SAndroid Build Coastguard Worker 		break;
5957*7c568831SAndroid Build Coastguard Worker 	    case XPATH_NUMBER:
5958*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0);
5959*7c568831SAndroid Build Coastguard Worker 		break;
5960*7c568831SAndroid Build Coastguard Worker 	    case XPATH_STRING:
5961*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathEqualNodeSetString(ctxt, arg1,
5962*7c568831SAndroid Build Coastguard Worker                                                  arg2->stringval, 0);
5963*7c568831SAndroid Build Coastguard Worker 		break;
5964*7c568831SAndroid Build Coastguard Worker 	    case XPATH_USERS:
5965*7c568831SAndroid Build Coastguard Worker 		/* TODO */
5966*7c568831SAndroid Build Coastguard Worker 		break;
5967*7c568831SAndroid Build Coastguard Worker 	}
5968*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, arg1);
5969*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, arg2);
5970*7c568831SAndroid Build Coastguard Worker 	return(ret);
5971*7c568831SAndroid Build Coastguard Worker     }
5972*7c568831SAndroid Build Coastguard Worker 
5973*7c568831SAndroid Build Coastguard Worker     return (xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
5974*7c568831SAndroid Build Coastguard Worker }
5975*7c568831SAndroid Build Coastguard Worker 
5976*7c568831SAndroid Build Coastguard Worker /**
5977*7c568831SAndroid Build Coastguard Worker  * xmlXPathNotEqualValues:
5978*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
5979*7c568831SAndroid Build Coastguard Worker  *
5980*7c568831SAndroid Build Coastguard Worker  * Implement the equal operation on XPath objects content: @arg1 == @arg2
5981*7c568831SAndroid Build Coastguard Worker  *
5982*7c568831SAndroid Build Coastguard Worker  * Returns 0 or 1 depending on the results of the test.
5983*7c568831SAndroid Build Coastguard Worker  */
5984*7c568831SAndroid Build Coastguard Worker int
xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt)5985*7c568831SAndroid Build Coastguard Worker xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
5986*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg1, arg2, argtmp;
5987*7c568831SAndroid Build Coastguard Worker     int ret = 0;
5988*7c568831SAndroid Build Coastguard Worker 
5989*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
5990*7c568831SAndroid Build Coastguard Worker     arg2 = valuePop(ctxt);
5991*7c568831SAndroid Build Coastguard Worker     arg1 = valuePop(ctxt);
5992*7c568831SAndroid Build Coastguard Worker     if ((arg1 == NULL) || (arg2 == NULL)) {
5993*7c568831SAndroid Build Coastguard Worker 	if (arg1 != NULL)
5994*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg1);
5995*7c568831SAndroid Build Coastguard Worker 	else
5996*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg2);
5997*7c568831SAndroid Build Coastguard Worker 	XP_ERROR0(XPATH_INVALID_OPERAND);
5998*7c568831SAndroid Build Coastguard Worker     }
5999*7c568831SAndroid Build Coastguard Worker 
6000*7c568831SAndroid Build Coastguard Worker     if (arg1 == arg2) {
6001*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, arg1);
6002*7c568831SAndroid Build Coastguard Worker         return(0);
6003*7c568831SAndroid Build Coastguard Worker     }
6004*7c568831SAndroid Build Coastguard Worker 
6005*7c568831SAndroid Build Coastguard Worker     /*
6006*7c568831SAndroid Build Coastguard Worker      *If either argument is a nodeset, it's a 'special case'
6007*7c568831SAndroid Build Coastguard Worker      */
6008*7c568831SAndroid Build Coastguard Worker     if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
6009*7c568831SAndroid Build Coastguard Worker       (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6010*7c568831SAndroid Build Coastguard Worker 	/*
6011*7c568831SAndroid Build Coastguard Worker 	 *Hack it to assure arg1 is the nodeset
6012*7c568831SAndroid Build Coastguard Worker 	 */
6013*7c568831SAndroid Build Coastguard Worker 	if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
6014*7c568831SAndroid Build Coastguard Worker 		argtmp = arg2;
6015*7c568831SAndroid Build Coastguard Worker 		arg2 = arg1;
6016*7c568831SAndroid Build Coastguard Worker 		arg1 = argtmp;
6017*7c568831SAndroid Build Coastguard Worker 	}
6018*7c568831SAndroid Build Coastguard Worker 	switch (arg2->type) {
6019*7c568831SAndroid Build Coastguard Worker 	    case XPATH_UNDEFINED:
6020*7c568831SAndroid Build Coastguard Worker 		break;
6021*7c568831SAndroid Build Coastguard Worker 	    case XPATH_NODESET:
6022*7c568831SAndroid Build Coastguard Worker 	    case XPATH_XSLT_TREE:
6023*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 1);
6024*7c568831SAndroid Build Coastguard Worker 		break;
6025*7c568831SAndroid Build Coastguard Worker 	    case XPATH_BOOLEAN:
6026*7c568831SAndroid Build Coastguard Worker 		if ((arg1->nodesetval == NULL) ||
6027*7c568831SAndroid Build Coastguard Worker 		  (arg1->nodesetval->nodeNr == 0)) ret = 0;
6028*7c568831SAndroid Build Coastguard Worker 		else
6029*7c568831SAndroid Build Coastguard Worker 		    ret = 1;
6030*7c568831SAndroid Build Coastguard Worker 		ret = (ret != arg2->boolval);
6031*7c568831SAndroid Build Coastguard Worker 		break;
6032*7c568831SAndroid Build Coastguard Worker 	    case XPATH_NUMBER:
6033*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1);
6034*7c568831SAndroid Build Coastguard Worker 		break;
6035*7c568831SAndroid Build Coastguard Worker 	    case XPATH_STRING:
6036*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathEqualNodeSetString(ctxt, arg1,
6037*7c568831SAndroid Build Coastguard Worker                                                  arg2->stringval, 1);
6038*7c568831SAndroid Build Coastguard Worker 		break;
6039*7c568831SAndroid Build Coastguard Worker 	    case XPATH_USERS:
6040*7c568831SAndroid Build Coastguard Worker 		/* TODO */
6041*7c568831SAndroid Build Coastguard Worker 		break;
6042*7c568831SAndroid Build Coastguard Worker 	}
6043*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, arg1);
6044*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, arg2);
6045*7c568831SAndroid Build Coastguard Worker 	return(ret);
6046*7c568831SAndroid Build Coastguard Worker     }
6047*7c568831SAndroid Build Coastguard Worker 
6048*7c568831SAndroid Build Coastguard Worker     return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
6049*7c568831SAndroid Build Coastguard Worker }
6050*7c568831SAndroid Build Coastguard Worker 
6051*7c568831SAndroid Build Coastguard Worker /**
6052*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompareValues:
6053*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6054*7c568831SAndroid Build Coastguard Worker  * @inf:  less than (1) or greater than (0)
6055*7c568831SAndroid Build Coastguard Worker  * @strict:  is the comparison strict
6056*7c568831SAndroid Build Coastguard Worker  *
6057*7c568831SAndroid Build Coastguard Worker  * Implement the compare operation on XPath objects:
6058*7c568831SAndroid Build Coastguard Worker  *     @arg1 < @arg2    (1, 1, ...
6059*7c568831SAndroid Build Coastguard Worker  *     @arg1 <= @arg2   (1, 0, ...
6060*7c568831SAndroid Build Coastguard Worker  *     @arg1 > @arg2    (0, 1, ...
6061*7c568831SAndroid Build Coastguard Worker  *     @arg1 >= @arg2   (0, 0, ...
6062*7c568831SAndroid Build Coastguard Worker  *
6063*7c568831SAndroid Build Coastguard Worker  * When neither object to be compared is a node-set and the operator is
6064*7c568831SAndroid Build Coastguard Worker  * <=, <, >=, >, then the objects are compared by converted both objects
6065*7c568831SAndroid Build Coastguard Worker  * to numbers and comparing the numbers according to IEEE 754. The <
6066*7c568831SAndroid Build Coastguard Worker  * comparison will be true if and only if the first number is less than the
6067*7c568831SAndroid Build Coastguard Worker  * second number. The <= comparison will be true if and only if the first
6068*7c568831SAndroid Build Coastguard Worker  * number is less than or equal to the second number. The > comparison
6069*7c568831SAndroid Build Coastguard Worker  * will be true if and only if the first number is greater than the second
6070*7c568831SAndroid Build Coastguard Worker  * number. The >= comparison will be true if and only if the first number
6071*7c568831SAndroid Build Coastguard Worker  * is greater than or equal to the second number.
6072*7c568831SAndroid Build Coastguard Worker  *
6073*7c568831SAndroid Build Coastguard Worker  * Returns 1 if the comparison succeeded, 0 if it failed
6074*7c568831SAndroid Build Coastguard Worker  */
6075*7c568831SAndroid Build Coastguard Worker int
xmlXPathCompareValues(xmlXPathParserContextPtr ctxt,int inf,int strict)6076*7c568831SAndroid Build Coastguard Worker xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
6077*7c568831SAndroid Build Coastguard Worker     int ret = 0, arg1i = 0, arg2i = 0;
6078*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg1, arg2;
6079*7c568831SAndroid Build Coastguard Worker 
6080*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
6081*7c568831SAndroid Build Coastguard Worker     arg2 = valuePop(ctxt);
6082*7c568831SAndroid Build Coastguard Worker     arg1 = valuePop(ctxt);
6083*7c568831SAndroid Build Coastguard Worker     if ((arg1 == NULL) || (arg2 == NULL)) {
6084*7c568831SAndroid Build Coastguard Worker 	if (arg1 != NULL)
6085*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg1);
6086*7c568831SAndroid Build Coastguard Worker 	else
6087*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg2);
6088*7c568831SAndroid Build Coastguard Worker 	XP_ERROR0(XPATH_INVALID_OPERAND);
6089*7c568831SAndroid Build Coastguard Worker     }
6090*7c568831SAndroid Build Coastguard Worker 
6091*7c568831SAndroid Build Coastguard Worker     if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
6092*7c568831SAndroid Build Coastguard Worker       (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6093*7c568831SAndroid Build Coastguard Worker 	/*
6094*7c568831SAndroid Build Coastguard Worker 	 * If either argument is a XPATH_NODESET or XPATH_XSLT_TREE the two arguments
6095*7c568831SAndroid Build Coastguard Worker 	 * are not freed from within this routine; they will be freed from the
6096*7c568831SAndroid Build Coastguard Worker 	 * called routine, e.g. xmlXPathCompareNodeSets or xmlXPathCompareNodeSetValue
6097*7c568831SAndroid Build Coastguard Worker 	 */
6098*7c568831SAndroid Build Coastguard Worker 	if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) &&
6099*7c568831SAndroid Build Coastguard Worker 	  ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){
6100*7c568831SAndroid Build Coastguard Worker 	    ret = xmlXPathCompareNodeSets(ctxt, inf, strict, arg1, arg2);
6101*7c568831SAndroid Build Coastguard Worker 	} else {
6102*7c568831SAndroid Build Coastguard Worker 	    if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6103*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
6104*7c568831SAndroid Build Coastguard Worker 			                          arg1, arg2);
6105*7c568831SAndroid Build Coastguard Worker 	    } else {
6106*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict,
6107*7c568831SAndroid Build Coastguard Worker 			                          arg2, arg1);
6108*7c568831SAndroid Build Coastguard Worker 	    }
6109*7c568831SAndroid Build Coastguard Worker 	}
6110*7c568831SAndroid Build Coastguard Worker 	return(ret);
6111*7c568831SAndroid Build Coastguard Worker     }
6112*7c568831SAndroid Build Coastguard Worker 
6113*7c568831SAndroid Build Coastguard Worker     if (arg1->type != XPATH_NUMBER) {
6114*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, arg1);
6115*7c568831SAndroid Build Coastguard Worker 	xmlXPathNumberFunction(ctxt, 1);
6116*7c568831SAndroid Build Coastguard Worker 	arg1 = valuePop(ctxt);
6117*7c568831SAndroid Build Coastguard Worker     }
6118*7c568831SAndroid Build Coastguard Worker     if (arg2->type != XPATH_NUMBER) {
6119*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, arg2);
6120*7c568831SAndroid Build Coastguard Worker 	xmlXPathNumberFunction(ctxt, 1);
6121*7c568831SAndroid Build Coastguard Worker 	arg2 = valuePop(ctxt);
6122*7c568831SAndroid Build Coastguard Worker     }
6123*7c568831SAndroid Build Coastguard Worker     if (ctxt->error)
6124*7c568831SAndroid Build Coastguard Worker         goto error;
6125*7c568831SAndroid Build Coastguard Worker     /*
6126*7c568831SAndroid Build Coastguard Worker      * Add tests for infinity and nan
6127*7c568831SAndroid Build Coastguard Worker      * => feedback on 3.4 for Inf and NaN
6128*7c568831SAndroid Build Coastguard Worker      */
6129*7c568831SAndroid Build Coastguard Worker     /* Hand check NaN and Infinity comparisons */
6130*7c568831SAndroid Build Coastguard Worker     if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
6131*7c568831SAndroid Build Coastguard Worker 	ret=0;
6132*7c568831SAndroid Build Coastguard Worker     } else {
6133*7c568831SAndroid Build Coastguard Worker 	arg1i=xmlXPathIsInf(arg1->floatval);
6134*7c568831SAndroid Build Coastguard Worker 	arg2i=xmlXPathIsInf(arg2->floatval);
6135*7c568831SAndroid Build Coastguard Worker 	if (inf && strict) {
6136*7c568831SAndroid Build Coastguard Worker 	    if ((arg1i == -1 && arg2i != -1) ||
6137*7c568831SAndroid Build Coastguard Worker 		(arg2i == 1 && arg1i != 1)) {
6138*7c568831SAndroid Build Coastguard Worker 		ret = 1;
6139*7c568831SAndroid Build Coastguard Worker 	    } else if (arg1i == 0 && arg2i == 0) {
6140*7c568831SAndroid Build Coastguard Worker 		ret = (arg1->floatval < arg2->floatval);
6141*7c568831SAndroid Build Coastguard Worker 	    } else {
6142*7c568831SAndroid Build Coastguard Worker 		ret = 0;
6143*7c568831SAndroid Build Coastguard Worker 	    }
6144*7c568831SAndroid Build Coastguard Worker 	}
6145*7c568831SAndroid Build Coastguard Worker 	else if (inf && !strict) {
6146*7c568831SAndroid Build Coastguard Worker 	    if (arg1i == -1 || arg2i == 1) {
6147*7c568831SAndroid Build Coastguard Worker 		ret = 1;
6148*7c568831SAndroid Build Coastguard Worker 	    } else if (arg1i == 0 && arg2i == 0) {
6149*7c568831SAndroid Build Coastguard Worker 		ret = (arg1->floatval <= arg2->floatval);
6150*7c568831SAndroid Build Coastguard Worker 	    } else {
6151*7c568831SAndroid Build Coastguard Worker 		ret = 0;
6152*7c568831SAndroid Build Coastguard Worker 	    }
6153*7c568831SAndroid Build Coastguard Worker 	}
6154*7c568831SAndroid Build Coastguard Worker 	else if (!inf && strict) {
6155*7c568831SAndroid Build Coastguard Worker 	    if ((arg1i == 1 && arg2i != 1) ||
6156*7c568831SAndroid Build Coastguard Worker 		(arg2i == -1 && arg1i != -1)) {
6157*7c568831SAndroid Build Coastguard Worker 		ret = 1;
6158*7c568831SAndroid Build Coastguard Worker 	    } else if (arg1i == 0 && arg2i == 0) {
6159*7c568831SAndroid Build Coastguard Worker 		ret = (arg1->floatval > arg2->floatval);
6160*7c568831SAndroid Build Coastguard Worker 	    } else {
6161*7c568831SAndroid Build Coastguard Worker 		ret = 0;
6162*7c568831SAndroid Build Coastguard Worker 	    }
6163*7c568831SAndroid Build Coastguard Worker 	}
6164*7c568831SAndroid Build Coastguard Worker 	else if (!inf && !strict) {
6165*7c568831SAndroid Build Coastguard Worker 	    if (arg1i == 1 || arg2i == -1) {
6166*7c568831SAndroid Build Coastguard Worker 		ret = 1;
6167*7c568831SAndroid Build Coastguard Worker 	    } else if (arg1i == 0 && arg2i == 0) {
6168*7c568831SAndroid Build Coastguard Worker 		ret = (arg1->floatval >= arg2->floatval);
6169*7c568831SAndroid Build Coastguard Worker 	    } else {
6170*7c568831SAndroid Build Coastguard Worker 		ret = 0;
6171*7c568831SAndroid Build Coastguard Worker 	    }
6172*7c568831SAndroid Build Coastguard Worker 	}
6173*7c568831SAndroid Build Coastguard Worker     }
6174*7c568831SAndroid Build Coastguard Worker error:
6175*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg1);
6176*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg2);
6177*7c568831SAndroid Build Coastguard Worker     return(ret);
6178*7c568831SAndroid Build Coastguard Worker }
6179*7c568831SAndroid Build Coastguard Worker 
6180*7c568831SAndroid Build Coastguard Worker /**
6181*7c568831SAndroid Build Coastguard Worker  * xmlXPathValueFlipSign:
6182*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6183*7c568831SAndroid Build Coastguard Worker  *
6184*7c568831SAndroid Build Coastguard Worker  * Implement the unary - operation on an XPath object
6185*7c568831SAndroid Build Coastguard Worker  * The numeric operators convert their operands to numbers as if
6186*7c568831SAndroid Build Coastguard Worker  * by calling the number function.
6187*7c568831SAndroid Build Coastguard Worker  */
6188*7c568831SAndroid Build Coastguard Worker void
xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt)6189*7c568831SAndroid Build Coastguard Worker xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
6190*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return;
6191*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
6192*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
6193*7c568831SAndroid Build Coastguard Worker     ctxt->value->floatval = -ctxt->value->floatval;
6194*7c568831SAndroid Build Coastguard Worker }
6195*7c568831SAndroid Build Coastguard Worker 
6196*7c568831SAndroid Build Coastguard Worker /**
6197*7c568831SAndroid Build Coastguard Worker  * xmlXPathAddValues:
6198*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6199*7c568831SAndroid Build Coastguard Worker  *
6200*7c568831SAndroid Build Coastguard Worker  * Implement the add operation on XPath objects:
6201*7c568831SAndroid Build Coastguard Worker  * The numeric operators convert their operands to numbers as if
6202*7c568831SAndroid Build Coastguard Worker  * by calling the number function.
6203*7c568831SAndroid Build Coastguard Worker  */
6204*7c568831SAndroid Build Coastguard Worker void
xmlXPathAddValues(xmlXPathParserContextPtr ctxt)6205*7c568831SAndroid Build Coastguard Worker xmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
6206*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg;
6207*7c568831SAndroid Build Coastguard Worker     double val;
6208*7c568831SAndroid Build Coastguard Worker 
6209*7c568831SAndroid Build Coastguard Worker     arg = valuePop(ctxt);
6210*7c568831SAndroid Build Coastguard Worker     if (arg == NULL)
6211*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_OPERAND);
6212*7c568831SAndroid Build Coastguard Worker     val = xmlXPathCastToNumberInternal(ctxt, arg);
6213*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg);
6214*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
6215*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
6216*7c568831SAndroid Build Coastguard Worker     ctxt->value->floatval += val;
6217*7c568831SAndroid Build Coastguard Worker }
6218*7c568831SAndroid Build Coastguard Worker 
6219*7c568831SAndroid Build Coastguard Worker /**
6220*7c568831SAndroid Build Coastguard Worker  * xmlXPathSubValues:
6221*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6222*7c568831SAndroid Build Coastguard Worker  *
6223*7c568831SAndroid Build Coastguard Worker  * Implement the subtraction operation on XPath objects:
6224*7c568831SAndroid Build Coastguard Worker  * The numeric operators convert their operands to numbers as if
6225*7c568831SAndroid Build Coastguard Worker  * by calling the number function.
6226*7c568831SAndroid Build Coastguard Worker  */
6227*7c568831SAndroid Build Coastguard Worker void
xmlXPathSubValues(xmlXPathParserContextPtr ctxt)6228*7c568831SAndroid Build Coastguard Worker xmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
6229*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg;
6230*7c568831SAndroid Build Coastguard Worker     double val;
6231*7c568831SAndroid Build Coastguard Worker 
6232*7c568831SAndroid Build Coastguard Worker     arg = valuePop(ctxt);
6233*7c568831SAndroid Build Coastguard Worker     if (arg == NULL)
6234*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_OPERAND);
6235*7c568831SAndroid Build Coastguard Worker     val = xmlXPathCastToNumberInternal(ctxt, arg);
6236*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg);
6237*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
6238*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
6239*7c568831SAndroid Build Coastguard Worker     ctxt->value->floatval -= val;
6240*7c568831SAndroid Build Coastguard Worker }
6241*7c568831SAndroid Build Coastguard Worker 
6242*7c568831SAndroid Build Coastguard Worker /**
6243*7c568831SAndroid Build Coastguard Worker  * xmlXPathMultValues:
6244*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6245*7c568831SAndroid Build Coastguard Worker  *
6246*7c568831SAndroid Build Coastguard Worker  * Implement the multiply operation on XPath objects:
6247*7c568831SAndroid Build Coastguard Worker  * The numeric operators convert their operands to numbers as if
6248*7c568831SAndroid Build Coastguard Worker  * by calling the number function.
6249*7c568831SAndroid Build Coastguard Worker  */
6250*7c568831SAndroid Build Coastguard Worker void
xmlXPathMultValues(xmlXPathParserContextPtr ctxt)6251*7c568831SAndroid Build Coastguard Worker xmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
6252*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg;
6253*7c568831SAndroid Build Coastguard Worker     double val;
6254*7c568831SAndroid Build Coastguard Worker 
6255*7c568831SAndroid Build Coastguard Worker     arg = valuePop(ctxt);
6256*7c568831SAndroid Build Coastguard Worker     if (arg == NULL)
6257*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_OPERAND);
6258*7c568831SAndroid Build Coastguard Worker     val = xmlXPathCastToNumberInternal(ctxt, arg);
6259*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg);
6260*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
6261*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
6262*7c568831SAndroid Build Coastguard Worker     ctxt->value->floatval *= val;
6263*7c568831SAndroid Build Coastguard Worker }
6264*7c568831SAndroid Build Coastguard Worker 
6265*7c568831SAndroid Build Coastguard Worker /**
6266*7c568831SAndroid Build Coastguard Worker  * xmlXPathDivValues:
6267*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6268*7c568831SAndroid Build Coastguard Worker  *
6269*7c568831SAndroid Build Coastguard Worker  * Implement the div operation on XPath objects @arg1 / @arg2:
6270*7c568831SAndroid Build Coastguard Worker  * The numeric operators convert their operands to numbers as if
6271*7c568831SAndroid Build Coastguard Worker  * by calling the number function.
6272*7c568831SAndroid Build Coastguard Worker  */
6273*7c568831SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
6274*7c568831SAndroid Build Coastguard Worker void
xmlXPathDivValues(xmlXPathParserContextPtr ctxt)6275*7c568831SAndroid Build Coastguard Worker xmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
6276*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg;
6277*7c568831SAndroid Build Coastguard Worker     double val;
6278*7c568831SAndroid Build Coastguard Worker 
6279*7c568831SAndroid Build Coastguard Worker     arg = valuePop(ctxt);
6280*7c568831SAndroid Build Coastguard Worker     if (arg == NULL)
6281*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_OPERAND);
6282*7c568831SAndroid Build Coastguard Worker     val = xmlXPathCastToNumberInternal(ctxt, arg);
6283*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg);
6284*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
6285*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
6286*7c568831SAndroid Build Coastguard Worker     ctxt->value->floatval /= val;
6287*7c568831SAndroid Build Coastguard Worker }
6288*7c568831SAndroid Build Coastguard Worker 
6289*7c568831SAndroid Build Coastguard Worker /**
6290*7c568831SAndroid Build Coastguard Worker  * xmlXPathModValues:
6291*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6292*7c568831SAndroid Build Coastguard Worker  *
6293*7c568831SAndroid Build Coastguard Worker  * Implement the mod operation on XPath objects: @arg1 / @arg2
6294*7c568831SAndroid Build Coastguard Worker  * The numeric operators convert their operands to numbers as if
6295*7c568831SAndroid Build Coastguard Worker  * by calling the number function.
6296*7c568831SAndroid Build Coastguard Worker  */
6297*7c568831SAndroid Build Coastguard Worker void
xmlXPathModValues(xmlXPathParserContextPtr ctxt)6298*7c568831SAndroid Build Coastguard Worker xmlXPathModValues(xmlXPathParserContextPtr ctxt) {
6299*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg;
6300*7c568831SAndroid Build Coastguard Worker     double arg1, arg2;
6301*7c568831SAndroid Build Coastguard Worker 
6302*7c568831SAndroid Build Coastguard Worker     arg = valuePop(ctxt);
6303*7c568831SAndroid Build Coastguard Worker     if (arg == NULL)
6304*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_OPERAND);
6305*7c568831SAndroid Build Coastguard Worker     arg2 = xmlXPathCastToNumberInternal(ctxt, arg);
6306*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, arg);
6307*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
6308*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
6309*7c568831SAndroid Build Coastguard Worker     arg1 = ctxt->value->floatval;
6310*7c568831SAndroid Build Coastguard Worker     if (arg2 == 0)
6311*7c568831SAndroid Build Coastguard Worker 	ctxt->value->floatval = xmlXPathNAN;
6312*7c568831SAndroid Build Coastguard Worker     else {
6313*7c568831SAndroid Build Coastguard Worker 	ctxt->value->floatval = fmod(arg1, arg2);
6314*7c568831SAndroid Build Coastguard Worker     }
6315*7c568831SAndroid Build Coastguard Worker }
6316*7c568831SAndroid Build Coastguard Worker 
6317*7c568831SAndroid Build Coastguard Worker /************************************************************************
6318*7c568831SAndroid Build Coastguard Worker  *									*
6319*7c568831SAndroid Build Coastguard Worker  *		The traversal functions					*
6320*7c568831SAndroid Build Coastguard Worker  *									*
6321*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
6322*7c568831SAndroid Build Coastguard Worker 
6323*7c568831SAndroid Build Coastguard Worker /*
6324*7c568831SAndroid Build Coastguard Worker  * A traversal function enumerates nodes along an axis.
6325*7c568831SAndroid Build Coastguard Worker  * Initially it must be called with NULL, and it indicates
6326*7c568831SAndroid Build Coastguard Worker  * termination on the axis by returning NULL.
6327*7c568831SAndroid Build Coastguard Worker  */
6328*7c568831SAndroid Build Coastguard Worker typedef xmlNodePtr (*xmlXPathTraversalFunction)
6329*7c568831SAndroid Build Coastguard Worker                     (xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
6330*7c568831SAndroid Build Coastguard Worker 
6331*7c568831SAndroid Build Coastguard Worker /*
6332*7c568831SAndroid Build Coastguard Worker  * xmlXPathTraversalFunctionExt:
6333*7c568831SAndroid Build Coastguard Worker  * A traversal function enumerates nodes along an axis.
6334*7c568831SAndroid Build Coastguard Worker  * Initially it must be called with NULL, and it indicates
6335*7c568831SAndroid Build Coastguard Worker  * termination on the axis by returning NULL.
6336*7c568831SAndroid Build Coastguard Worker  * The context node of the traversal is specified via @contextNode.
6337*7c568831SAndroid Build Coastguard Worker  */
6338*7c568831SAndroid Build Coastguard Worker typedef xmlNodePtr (*xmlXPathTraversalFunctionExt)
6339*7c568831SAndroid Build Coastguard Worker                     (xmlNodePtr cur, xmlNodePtr contextNode);
6340*7c568831SAndroid Build Coastguard Worker 
6341*7c568831SAndroid Build Coastguard Worker /*
6342*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetMergeFunction:
6343*7c568831SAndroid Build Coastguard Worker  * Used for merging node sets in xmlXPathCollectAndTest().
6344*7c568831SAndroid Build Coastguard Worker  */
6345*7c568831SAndroid Build Coastguard Worker typedef xmlNodeSetPtr (*xmlXPathNodeSetMergeFunction)
6346*7c568831SAndroid Build Coastguard Worker 		    (xmlNodeSetPtr, xmlNodeSetPtr);
6347*7c568831SAndroid Build Coastguard Worker 
6348*7c568831SAndroid Build Coastguard Worker 
6349*7c568831SAndroid Build Coastguard Worker /**
6350*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextSelf:
6351*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6352*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6353*7c568831SAndroid Build Coastguard Worker  *
6354*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "self" direction
6355*7c568831SAndroid Build Coastguard Worker  * The self axis contains just the context node itself
6356*7c568831SAndroid Build Coastguard Worker  *
6357*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6358*7c568831SAndroid Build Coastguard Worker  */
6359*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6360*7c568831SAndroid Build Coastguard Worker xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6361*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6362*7c568831SAndroid Build Coastguard Worker     if (cur == NULL)
6363*7c568831SAndroid Build Coastguard Worker         return(ctxt->context->node);
6364*7c568831SAndroid Build Coastguard Worker     return(NULL);
6365*7c568831SAndroid Build Coastguard Worker }
6366*7c568831SAndroid Build Coastguard Worker 
6367*7c568831SAndroid Build Coastguard Worker /**
6368*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextChild:
6369*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6370*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6371*7c568831SAndroid Build Coastguard Worker  *
6372*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "child" direction
6373*7c568831SAndroid Build Coastguard Worker  * The child axis contains the children of the context node in document order.
6374*7c568831SAndroid Build Coastguard Worker  *
6375*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6376*7c568831SAndroid Build Coastguard Worker  */
6377*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextChild(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6378*7c568831SAndroid Build Coastguard Worker xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6379*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6380*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
6381*7c568831SAndroid Build Coastguard Worker 	if (ctxt->context->node == NULL) return(NULL);
6382*7c568831SAndroid Build Coastguard Worker 	switch (ctxt->context->node->type) {
6383*7c568831SAndroid Build Coastguard Worker             case XML_ELEMENT_NODE:
6384*7c568831SAndroid Build Coastguard Worker             case XML_TEXT_NODE:
6385*7c568831SAndroid Build Coastguard Worker             case XML_CDATA_SECTION_NODE:
6386*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_REF_NODE:
6387*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_NODE:
6388*7c568831SAndroid Build Coastguard Worker             case XML_PI_NODE:
6389*7c568831SAndroid Build Coastguard Worker             case XML_COMMENT_NODE:
6390*7c568831SAndroid Build Coastguard Worker             case XML_NOTATION_NODE:
6391*7c568831SAndroid Build Coastguard Worker             case XML_DTD_NODE:
6392*7c568831SAndroid Build Coastguard Worker 		return(ctxt->context->node->children);
6393*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_NODE:
6394*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_TYPE_NODE:
6395*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_FRAG_NODE:
6396*7c568831SAndroid Build Coastguard Worker             case XML_HTML_DOCUMENT_NODE:
6397*7c568831SAndroid Build Coastguard Worker 		return(((xmlDocPtr) ctxt->context->node)->children);
6398*7c568831SAndroid Build Coastguard Worker 	    case XML_ELEMENT_DECL:
6399*7c568831SAndroid Build Coastguard Worker 	    case XML_ATTRIBUTE_DECL:
6400*7c568831SAndroid Build Coastguard Worker 	    case XML_ENTITY_DECL:
6401*7c568831SAndroid Build Coastguard Worker             case XML_ATTRIBUTE_NODE:
6402*7c568831SAndroid Build Coastguard Worker 	    case XML_NAMESPACE_DECL:
6403*7c568831SAndroid Build Coastguard Worker 	    case XML_XINCLUDE_START:
6404*7c568831SAndroid Build Coastguard Worker 	    case XML_XINCLUDE_END:
6405*7c568831SAndroid Build Coastguard Worker 		return(NULL);
6406*7c568831SAndroid Build Coastguard Worker 	}
6407*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6408*7c568831SAndroid Build Coastguard Worker     }
6409*7c568831SAndroid Build Coastguard Worker     if ((cur->type == XML_DOCUMENT_NODE) ||
6410*7c568831SAndroid Build Coastguard Worker         (cur->type == XML_HTML_DOCUMENT_NODE))
6411*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6412*7c568831SAndroid Build Coastguard Worker     return(cur->next);
6413*7c568831SAndroid Build Coastguard Worker }
6414*7c568831SAndroid Build Coastguard Worker 
6415*7c568831SAndroid Build Coastguard Worker /**
6416*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextChildElement:
6417*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6418*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6419*7c568831SAndroid Build Coastguard Worker  *
6420*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "child" direction and nodes of type element.
6421*7c568831SAndroid Build Coastguard Worker  * The child axis contains the children of the context node in document order.
6422*7c568831SAndroid Build Coastguard Worker  *
6423*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6424*7c568831SAndroid Build Coastguard Worker  */
6425*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6426*7c568831SAndroid Build Coastguard Worker xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6427*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6428*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
6429*7c568831SAndroid Build Coastguard Worker 	cur = ctxt->context->node;
6430*7c568831SAndroid Build Coastguard Worker 	if (cur == NULL) return(NULL);
6431*7c568831SAndroid Build Coastguard Worker 	/*
6432*7c568831SAndroid Build Coastguard Worker 	* Get the first element child.
6433*7c568831SAndroid Build Coastguard Worker 	*/
6434*7c568831SAndroid Build Coastguard Worker 	switch (cur->type) {
6435*7c568831SAndroid Build Coastguard Worker             case XML_ELEMENT_NODE:
6436*7c568831SAndroid Build Coastguard Worker 	    case XML_DOCUMENT_FRAG_NODE:
6437*7c568831SAndroid Build Coastguard Worker 	    case XML_ENTITY_REF_NODE: /* URGENT TODO: entify-refs as well? */
6438*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_NODE:
6439*7c568831SAndroid Build Coastguard Worker 		cur = cur->children;
6440*7c568831SAndroid Build Coastguard Worker 		if (cur != NULL) {
6441*7c568831SAndroid Build Coastguard Worker 		    if (cur->type == XML_ELEMENT_NODE)
6442*7c568831SAndroid Build Coastguard Worker 			return(cur);
6443*7c568831SAndroid Build Coastguard Worker 		    do {
6444*7c568831SAndroid Build Coastguard Worker 			cur = cur->next;
6445*7c568831SAndroid Build Coastguard Worker 		    } while ((cur != NULL) &&
6446*7c568831SAndroid Build Coastguard Worker 			(cur->type != XML_ELEMENT_NODE));
6447*7c568831SAndroid Build Coastguard Worker 		    return(cur);
6448*7c568831SAndroid Build Coastguard Worker 		}
6449*7c568831SAndroid Build Coastguard Worker 		return(NULL);
6450*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_NODE:
6451*7c568831SAndroid Build Coastguard Worker             case XML_HTML_DOCUMENT_NODE:
6452*7c568831SAndroid Build Coastguard Worker 		return(xmlDocGetRootElement((xmlDocPtr) cur));
6453*7c568831SAndroid Build Coastguard Worker 	    default:
6454*7c568831SAndroid Build Coastguard Worker 		return(NULL);
6455*7c568831SAndroid Build Coastguard Worker 	}
6456*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6457*7c568831SAndroid Build Coastguard Worker     }
6458*7c568831SAndroid Build Coastguard Worker     /*
6459*7c568831SAndroid Build Coastguard Worker     * Get the next sibling element node.
6460*7c568831SAndroid Build Coastguard Worker     */
6461*7c568831SAndroid Build Coastguard Worker     switch (cur->type) {
6462*7c568831SAndroid Build Coastguard Worker 	case XML_ELEMENT_NODE:
6463*7c568831SAndroid Build Coastguard Worker 	case XML_TEXT_NODE:
6464*7c568831SAndroid Build Coastguard Worker 	case XML_ENTITY_REF_NODE:
6465*7c568831SAndroid Build Coastguard Worker 	case XML_ENTITY_NODE:
6466*7c568831SAndroid Build Coastguard Worker 	case XML_CDATA_SECTION_NODE:
6467*7c568831SAndroid Build Coastguard Worker 	case XML_PI_NODE:
6468*7c568831SAndroid Build Coastguard Worker 	case XML_COMMENT_NODE:
6469*7c568831SAndroid Build Coastguard Worker 	case XML_XINCLUDE_END:
6470*7c568831SAndroid Build Coastguard Worker 	    break;
6471*7c568831SAndroid Build Coastguard Worker 	/* case XML_DTD_NODE: */ /* URGENT TODO: DTD-node as well? */
6472*7c568831SAndroid Build Coastguard Worker 	default:
6473*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
6474*7c568831SAndroid Build Coastguard Worker     }
6475*7c568831SAndroid Build Coastguard Worker     if (cur->next != NULL) {
6476*7c568831SAndroid Build Coastguard Worker 	if (cur->next->type == XML_ELEMENT_NODE)
6477*7c568831SAndroid Build Coastguard Worker 	    return(cur->next);
6478*7c568831SAndroid Build Coastguard Worker 	cur = cur->next;
6479*7c568831SAndroid Build Coastguard Worker 	do {
6480*7c568831SAndroid Build Coastguard Worker 	    cur = cur->next;
6481*7c568831SAndroid Build Coastguard Worker 	} while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE));
6482*7c568831SAndroid Build Coastguard Worker 	return(cur);
6483*7c568831SAndroid Build Coastguard Worker     }
6484*7c568831SAndroid Build Coastguard Worker     return(NULL);
6485*7c568831SAndroid Build Coastguard Worker }
6486*7c568831SAndroid Build Coastguard Worker 
6487*7c568831SAndroid Build Coastguard Worker /**
6488*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextDescendant:
6489*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6490*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6491*7c568831SAndroid Build Coastguard Worker  *
6492*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "descendant" direction
6493*7c568831SAndroid Build Coastguard Worker  * the descendant axis contains the descendants of the context node in document
6494*7c568831SAndroid Build Coastguard Worker  * order; a descendant is a child or a child of a child and so on.
6495*7c568831SAndroid Build Coastguard Worker  *
6496*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6497*7c568831SAndroid Build Coastguard Worker  */
6498*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6499*7c568831SAndroid Build Coastguard Worker xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6500*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6501*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
6502*7c568831SAndroid Build Coastguard Worker 	if (ctxt->context->node == NULL)
6503*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
6504*7c568831SAndroid Build Coastguard Worker 	if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6505*7c568831SAndroid Build Coastguard Worker 	    (ctxt->context->node->type == XML_NAMESPACE_DECL))
6506*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
6507*7c568831SAndroid Build Coastguard Worker 
6508*7c568831SAndroid Build Coastguard Worker         if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
6509*7c568831SAndroid Build Coastguard Worker 	    return(ctxt->context->doc->children);
6510*7c568831SAndroid Build Coastguard Worker         return(ctxt->context->node->children);
6511*7c568831SAndroid Build Coastguard Worker     }
6512*7c568831SAndroid Build Coastguard Worker 
6513*7c568831SAndroid Build Coastguard Worker     if (cur->type == XML_NAMESPACE_DECL)
6514*7c568831SAndroid Build Coastguard Worker         return(NULL);
6515*7c568831SAndroid Build Coastguard Worker     if (cur->children != NULL) {
6516*7c568831SAndroid Build Coastguard Worker 	/*
6517*7c568831SAndroid Build Coastguard Worker 	 * Do not descend on entities declarations
6518*7c568831SAndroid Build Coastguard Worker 	 */
6519*7c568831SAndroid Build Coastguard Worker 	if (cur->children->type != XML_ENTITY_DECL) {
6520*7c568831SAndroid Build Coastguard Worker 	    cur = cur->children;
6521*7c568831SAndroid Build Coastguard Worker 	    /*
6522*7c568831SAndroid Build Coastguard Worker 	     * Skip DTDs
6523*7c568831SAndroid Build Coastguard Worker 	     */
6524*7c568831SAndroid Build Coastguard Worker 	    if (cur->type != XML_DTD_NODE)
6525*7c568831SAndroid Build Coastguard Worker 		return(cur);
6526*7c568831SAndroid Build Coastguard Worker 	}
6527*7c568831SAndroid Build Coastguard Worker     }
6528*7c568831SAndroid Build Coastguard Worker 
6529*7c568831SAndroid Build Coastguard Worker     if (cur == ctxt->context->node) return(NULL);
6530*7c568831SAndroid Build Coastguard Worker 
6531*7c568831SAndroid Build Coastguard Worker     while (cur->next != NULL) {
6532*7c568831SAndroid Build Coastguard Worker 	cur = cur->next;
6533*7c568831SAndroid Build Coastguard Worker 	if ((cur->type != XML_ENTITY_DECL) &&
6534*7c568831SAndroid Build Coastguard Worker 	    (cur->type != XML_DTD_NODE))
6535*7c568831SAndroid Build Coastguard Worker 	    return(cur);
6536*7c568831SAndroid Build Coastguard Worker     }
6537*7c568831SAndroid Build Coastguard Worker 
6538*7c568831SAndroid Build Coastguard Worker     do {
6539*7c568831SAndroid Build Coastguard Worker         cur = cur->parent;
6540*7c568831SAndroid Build Coastguard Worker 	if (cur == NULL) break;
6541*7c568831SAndroid Build Coastguard Worker 	if (cur == ctxt->context->node) return(NULL);
6542*7c568831SAndroid Build Coastguard Worker 	if (cur->next != NULL) {
6543*7c568831SAndroid Build Coastguard Worker 	    cur = cur->next;
6544*7c568831SAndroid Build Coastguard Worker 	    return(cur);
6545*7c568831SAndroid Build Coastguard Worker 	}
6546*7c568831SAndroid Build Coastguard Worker     } while (cur != NULL);
6547*7c568831SAndroid Build Coastguard Worker     return(cur);
6548*7c568831SAndroid Build Coastguard Worker }
6549*7c568831SAndroid Build Coastguard Worker 
6550*7c568831SAndroid Build Coastguard Worker /**
6551*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextDescendantOrSelf:
6552*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6553*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6554*7c568831SAndroid Build Coastguard Worker  *
6555*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "descendant-or-self" direction
6556*7c568831SAndroid Build Coastguard Worker  * the descendant-or-self axis contains the context node and the descendants
6557*7c568831SAndroid Build Coastguard Worker  * of the context node in document order; thus the context node is the first
6558*7c568831SAndroid Build Coastguard Worker  * node on the axis, and the first child of the context node is the second node
6559*7c568831SAndroid Build Coastguard Worker  * on the axis
6560*7c568831SAndroid Build Coastguard Worker  *
6561*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6562*7c568831SAndroid Build Coastguard Worker  */
6563*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6564*7c568831SAndroid Build Coastguard Worker xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6565*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6566*7c568831SAndroid Build Coastguard Worker     if (cur == NULL)
6567*7c568831SAndroid Build Coastguard Worker         return(ctxt->context->node);
6568*7c568831SAndroid Build Coastguard Worker 
6569*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->node == NULL)
6570*7c568831SAndroid Build Coastguard Worker         return(NULL);
6571*7c568831SAndroid Build Coastguard Worker     if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6572*7c568831SAndroid Build Coastguard Worker         (ctxt->context->node->type == XML_NAMESPACE_DECL))
6573*7c568831SAndroid Build Coastguard Worker         return(NULL);
6574*7c568831SAndroid Build Coastguard Worker 
6575*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNextDescendant(ctxt, cur));
6576*7c568831SAndroid Build Coastguard Worker }
6577*7c568831SAndroid Build Coastguard Worker 
6578*7c568831SAndroid Build Coastguard Worker /**
6579*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextParent:
6580*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6581*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6582*7c568831SAndroid Build Coastguard Worker  *
6583*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "parent" direction
6584*7c568831SAndroid Build Coastguard Worker  * The parent axis contains the parent of the context node, if there is one.
6585*7c568831SAndroid Build Coastguard Worker  *
6586*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6587*7c568831SAndroid Build Coastguard Worker  */
6588*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextParent(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6589*7c568831SAndroid Build Coastguard Worker xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6590*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6591*7c568831SAndroid Build Coastguard Worker     /*
6592*7c568831SAndroid Build Coastguard Worker      * the parent of an attribute or namespace node is the element
6593*7c568831SAndroid Build Coastguard Worker      * to which the attribute or namespace node is attached
6594*7c568831SAndroid Build Coastguard Worker      * Namespace handling !!!
6595*7c568831SAndroid Build Coastguard Worker      */
6596*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
6597*7c568831SAndroid Build Coastguard Worker 	if (ctxt->context->node == NULL) return(NULL);
6598*7c568831SAndroid Build Coastguard Worker 	switch (ctxt->context->node->type) {
6599*7c568831SAndroid Build Coastguard Worker             case XML_ELEMENT_NODE:
6600*7c568831SAndroid Build Coastguard Worker             case XML_TEXT_NODE:
6601*7c568831SAndroid Build Coastguard Worker             case XML_CDATA_SECTION_NODE:
6602*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_REF_NODE:
6603*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_NODE:
6604*7c568831SAndroid Build Coastguard Worker             case XML_PI_NODE:
6605*7c568831SAndroid Build Coastguard Worker             case XML_COMMENT_NODE:
6606*7c568831SAndroid Build Coastguard Worker             case XML_NOTATION_NODE:
6607*7c568831SAndroid Build Coastguard Worker             case XML_DTD_NODE:
6608*7c568831SAndroid Build Coastguard Worker 	    case XML_ELEMENT_DECL:
6609*7c568831SAndroid Build Coastguard Worker 	    case XML_ATTRIBUTE_DECL:
6610*7c568831SAndroid Build Coastguard Worker 	    case XML_XINCLUDE_START:
6611*7c568831SAndroid Build Coastguard Worker 	    case XML_XINCLUDE_END:
6612*7c568831SAndroid Build Coastguard Worker 	    case XML_ENTITY_DECL:
6613*7c568831SAndroid Build Coastguard Worker 		if (ctxt->context->node->parent == NULL)
6614*7c568831SAndroid Build Coastguard Worker 		    return((xmlNodePtr) ctxt->context->doc);
6615*7c568831SAndroid Build Coastguard Worker 		if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
6616*7c568831SAndroid Build Coastguard Worker 		    ((ctxt->context->node->parent->name[0] == ' ') ||
6617*7c568831SAndroid Build Coastguard Worker 		     (xmlStrEqual(ctxt->context->node->parent->name,
6618*7c568831SAndroid Build Coastguard Worker 				 BAD_CAST "fake node libxslt"))))
6619*7c568831SAndroid Build Coastguard Worker 		    return(NULL);
6620*7c568831SAndroid Build Coastguard Worker 		return(ctxt->context->node->parent);
6621*7c568831SAndroid Build Coastguard Worker             case XML_ATTRIBUTE_NODE: {
6622*7c568831SAndroid Build Coastguard Worker 		xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
6623*7c568831SAndroid Build Coastguard Worker 
6624*7c568831SAndroid Build Coastguard Worker 		return(att->parent);
6625*7c568831SAndroid Build Coastguard Worker 	    }
6626*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_NODE:
6627*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_TYPE_NODE:
6628*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_FRAG_NODE:
6629*7c568831SAndroid Build Coastguard Worker             case XML_HTML_DOCUMENT_NODE:
6630*7c568831SAndroid Build Coastguard Worker                 return(NULL);
6631*7c568831SAndroid Build Coastguard Worker 	    case XML_NAMESPACE_DECL: {
6632*7c568831SAndroid Build Coastguard Worker 		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
6633*7c568831SAndroid Build Coastguard Worker 
6634*7c568831SAndroid Build Coastguard Worker 		if ((ns->next != NULL) &&
6635*7c568831SAndroid Build Coastguard Worker 		    (ns->next->type != XML_NAMESPACE_DECL))
6636*7c568831SAndroid Build Coastguard Worker 		    return((xmlNodePtr) ns->next);
6637*7c568831SAndroid Build Coastguard Worker                 return(NULL);
6638*7c568831SAndroid Build Coastguard Worker 	    }
6639*7c568831SAndroid Build Coastguard Worker 	}
6640*7c568831SAndroid Build Coastguard Worker     }
6641*7c568831SAndroid Build Coastguard Worker     return(NULL);
6642*7c568831SAndroid Build Coastguard Worker }
6643*7c568831SAndroid Build Coastguard Worker 
6644*7c568831SAndroid Build Coastguard Worker /**
6645*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextAncestor:
6646*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6647*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6648*7c568831SAndroid Build Coastguard Worker  *
6649*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "ancestor" direction
6650*7c568831SAndroid Build Coastguard Worker  * the ancestor axis contains the ancestors of the context node; the ancestors
6651*7c568831SAndroid Build Coastguard Worker  * of the context node consist of the parent of context node and the parent's
6652*7c568831SAndroid Build Coastguard Worker  * parent and so on; the nodes are ordered in reverse document order; thus the
6653*7c568831SAndroid Build Coastguard Worker  * parent is the first node on the axis, and the parent's parent is the second
6654*7c568831SAndroid Build Coastguard Worker  * node on the axis
6655*7c568831SAndroid Build Coastguard Worker  *
6656*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6657*7c568831SAndroid Build Coastguard Worker  */
6658*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6659*7c568831SAndroid Build Coastguard Worker xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6660*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6661*7c568831SAndroid Build Coastguard Worker     /*
6662*7c568831SAndroid Build Coastguard Worker      * the parent of an attribute or namespace node is the element
6663*7c568831SAndroid Build Coastguard Worker      * to which the attribute or namespace node is attached
6664*7c568831SAndroid Build Coastguard Worker      * !!!!!!!!!!!!!
6665*7c568831SAndroid Build Coastguard Worker      */
6666*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
6667*7c568831SAndroid Build Coastguard Worker 	if (ctxt->context->node == NULL) return(NULL);
6668*7c568831SAndroid Build Coastguard Worker 	switch (ctxt->context->node->type) {
6669*7c568831SAndroid Build Coastguard Worker             case XML_ELEMENT_NODE:
6670*7c568831SAndroid Build Coastguard Worker             case XML_TEXT_NODE:
6671*7c568831SAndroid Build Coastguard Worker             case XML_CDATA_SECTION_NODE:
6672*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_REF_NODE:
6673*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_NODE:
6674*7c568831SAndroid Build Coastguard Worker             case XML_PI_NODE:
6675*7c568831SAndroid Build Coastguard Worker             case XML_COMMENT_NODE:
6676*7c568831SAndroid Build Coastguard Worker 	    case XML_DTD_NODE:
6677*7c568831SAndroid Build Coastguard Worker 	    case XML_ELEMENT_DECL:
6678*7c568831SAndroid Build Coastguard Worker 	    case XML_ATTRIBUTE_DECL:
6679*7c568831SAndroid Build Coastguard Worker 	    case XML_ENTITY_DECL:
6680*7c568831SAndroid Build Coastguard Worker             case XML_NOTATION_NODE:
6681*7c568831SAndroid Build Coastguard Worker 	    case XML_XINCLUDE_START:
6682*7c568831SAndroid Build Coastguard Worker 	    case XML_XINCLUDE_END:
6683*7c568831SAndroid Build Coastguard Worker 		if (ctxt->context->node->parent == NULL)
6684*7c568831SAndroid Build Coastguard Worker 		    return((xmlNodePtr) ctxt->context->doc);
6685*7c568831SAndroid Build Coastguard Worker 		if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
6686*7c568831SAndroid Build Coastguard Worker 		    ((ctxt->context->node->parent->name[0] == ' ') ||
6687*7c568831SAndroid Build Coastguard Worker 		     (xmlStrEqual(ctxt->context->node->parent->name,
6688*7c568831SAndroid Build Coastguard Worker 				 BAD_CAST "fake node libxslt"))))
6689*7c568831SAndroid Build Coastguard Worker 		    return(NULL);
6690*7c568831SAndroid Build Coastguard Worker 		return(ctxt->context->node->parent);
6691*7c568831SAndroid Build Coastguard Worker             case XML_ATTRIBUTE_NODE: {
6692*7c568831SAndroid Build Coastguard Worker 		xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node;
6693*7c568831SAndroid Build Coastguard Worker 
6694*7c568831SAndroid Build Coastguard Worker 		return(tmp->parent);
6695*7c568831SAndroid Build Coastguard Worker 	    }
6696*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_NODE:
6697*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_TYPE_NODE:
6698*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_FRAG_NODE:
6699*7c568831SAndroid Build Coastguard Worker             case XML_HTML_DOCUMENT_NODE:
6700*7c568831SAndroid Build Coastguard Worker                 return(NULL);
6701*7c568831SAndroid Build Coastguard Worker 	    case XML_NAMESPACE_DECL: {
6702*7c568831SAndroid Build Coastguard Worker 		xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
6703*7c568831SAndroid Build Coastguard Worker 
6704*7c568831SAndroid Build Coastguard Worker 		if ((ns->next != NULL) &&
6705*7c568831SAndroid Build Coastguard Worker 		    (ns->next->type != XML_NAMESPACE_DECL))
6706*7c568831SAndroid Build Coastguard Worker 		    return((xmlNodePtr) ns->next);
6707*7c568831SAndroid Build Coastguard Worker 		/* Bad, how did that namespace end up here ? */
6708*7c568831SAndroid Build Coastguard Worker                 return(NULL);
6709*7c568831SAndroid Build Coastguard Worker 	    }
6710*7c568831SAndroid Build Coastguard Worker 	}
6711*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6712*7c568831SAndroid Build Coastguard Worker     }
6713*7c568831SAndroid Build Coastguard Worker     if (cur == ctxt->context->doc->children)
6714*7c568831SAndroid Build Coastguard Worker 	return((xmlNodePtr) ctxt->context->doc);
6715*7c568831SAndroid Build Coastguard Worker     if (cur == (xmlNodePtr) ctxt->context->doc)
6716*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6717*7c568831SAndroid Build Coastguard Worker     switch (cur->type) {
6718*7c568831SAndroid Build Coastguard Worker 	case XML_ELEMENT_NODE:
6719*7c568831SAndroid Build Coastguard Worker 	case XML_TEXT_NODE:
6720*7c568831SAndroid Build Coastguard Worker 	case XML_CDATA_SECTION_NODE:
6721*7c568831SAndroid Build Coastguard Worker 	case XML_ENTITY_REF_NODE:
6722*7c568831SAndroid Build Coastguard Worker 	case XML_ENTITY_NODE:
6723*7c568831SAndroid Build Coastguard Worker 	case XML_PI_NODE:
6724*7c568831SAndroid Build Coastguard Worker 	case XML_COMMENT_NODE:
6725*7c568831SAndroid Build Coastguard Worker 	case XML_NOTATION_NODE:
6726*7c568831SAndroid Build Coastguard Worker 	case XML_DTD_NODE:
6727*7c568831SAndroid Build Coastguard Worker         case XML_ELEMENT_DECL:
6728*7c568831SAndroid Build Coastguard Worker         case XML_ATTRIBUTE_DECL:
6729*7c568831SAndroid Build Coastguard Worker         case XML_ENTITY_DECL:
6730*7c568831SAndroid Build Coastguard Worker 	case XML_XINCLUDE_START:
6731*7c568831SAndroid Build Coastguard Worker 	case XML_XINCLUDE_END:
6732*7c568831SAndroid Build Coastguard Worker 	    if (cur->parent == NULL)
6733*7c568831SAndroid Build Coastguard Worker 		return(NULL);
6734*7c568831SAndroid Build Coastguard Worker 	    if ((cur->parent->type == XML_ELEMENT_NODE) &&
6735*7c568831SAndroid Build Coastguard Worker 		((cur->parent->name[0] == ' ') ||
6736*7c568831SAndroid Build Coastguard Worker 		 (xmlStrEqual(cur->parent->name,
6737*7c568831SAndroid Build Coastguard Worker 			      BAD_CAST "fake node libxslt"))))
6738*7c568831SAndroid Build Coastguard Worker 		return(NULL);
6739*7c568831SAndroid Build Coastguard Worker 	    return(cur->parent);
6740*7c568831SAndroid Build Coastguard Worker 	case XML_ATTRIBUTE_NODE: {
6741*7c568831SAndroid Build Coastguard Worker 	    xmlAttrPtr att = (xmlAttrPtr) cur;
6742*7c568831SAndroid Build Coastguard Worker 
6743*7c568831SAndroid Build Coastguard Worker 	    return(att->parent);
6744*7c568831SAndroid Build Coastguard Worker 	}
6745*7c568831SAndroid Build Coastguard Worker 	case XML_NAMESPACE_DECL: {
6746*7c568831SAndroid Build Coastguard Worker 	    xmlNsPtr ns = (xmlNsPtr) cur;
6747*7c568831SAndroid Build Coastguard Worker 
6748*7c568831SAndroid Build Coastguard Worker 	    if ((ns->next != NULL) &&
6749*7c568831SAndroid Build Coastguard Worker 	        (ns->next->type != XML_NAMESPACE_DECL))
6750*7c568831SAndroid Build Coastguard Worker 	        return((xmlNodePtr) ns->next);
6751*7c568831SAndroid Build Coastguard Worker 	    /* Bad, how did that namespace end up here ? */
6752*7c568831SAndroid Build Coastguard Worker             return(NULL);
6753*7c568831SAndroid Build Coastguard Worker 	}
6754*7c568831SAndroid Build Coastguard Worker 	case XML_DOCUMENT_NODE:
6755*7c568831SAndroid Build Coastguard Worker 	case XML_DOCUMENT_TYPE_NODE:
6756*7c568831SAndroid Build Coastguard Worker 	case XML_DOCUMENT_FRAG_NODE:
6757*7c568831SAndroid Build Coastguard Worker 	case XML_HTML_DOCUMENT_NODE:
6758*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
6759*7c568831SAndroid Build Coastguard Worker     }
6760*7c568831SAndroid Build Coastguard Worker     return(NULL);
6761*7c568831SAndroid Build Coastguard Worker }
6762*7c568831SAndroid Build Coastguard Worker 
6763*7c568831SAndroid Build Coastguard Worker /**
6764*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextAncestorOrSelf:
6765*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6766*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6767*7c568831SAndroid Build Coastguard Worker  *
6768*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "ancestor-or-self" direction
6769*7c568831SAndroid Build Coastguard Worker  * he ancestor-or-self axis contains the context node and ancestors of
6770*7c568831SAndroid Build Coastguard Worker  * the context node in reverse document order; thus the context node is
6771*7c568831SAndroid Build Coastguard Worker  * the first node on the axis, and the context node's parent the second;
6772*7c568831SAndroid Build Coastguard Worker  * parent here is defined the same as with the parent axis.
6773*7c568831SAndroid Build Coastguard Worker  *
6774*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6775*7c568831SAndroid Build Coastguard Worker  */
6776*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6777*7c568831SAndroid Build Coastguard Worker xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6778*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6779*7c568831SAndroid Build Coastguard Worker     if (cur == NULL)
6780*7c568831SAndroid Build Coastguard Worker         return(ctxt->context->node);
6781*7c568831SAndroid Build Coastguard Worker     return(xmlXPathNextAncestor(ctxt, cur));
6782*7c568831SAndroid Build Coastguard Worker }
6783*7c568831SAndroid Build Coastguard Worker 
6784*7c568831SAndroid Build Coastguard Worker /**
6785*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextFollowingSibling:
6786*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6787*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6788*7c568831SAndroid Build Coastguard Worker  *
6789*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "following-sibling" direction
6790*7c568831SAndroid Build Coastguard Worker  * The following-sibling axis contains the following siblings of the context
6791*7c568831SAndroid Build Coastguard Worker  * node in document order.
6792*7c568831SAndroid Build Coastguard Worker  *
6793*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6794*7c568831SAndroid Build Coastguard Worker  */
6795*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6796*7c568831SAndroid Build Coastguard Worker xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6797*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6798*7c568831SAndroid Build Coastguard Worker     if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6799*7c568831SAndroid Build Coastguard Worker 	(ctxt->context->node->type == XML_NAMESPACE_DECL))
6800*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6801*7c568831SAndroid Build Coastguard Worker     if (cur == (xmlNodePtr) ctxt->context->doc)
6802*7c568831SAndroid Build Coastguard Worker         return(NULL);
6803*7c568831SAndroid Build Coastguard Worker     if (cur == NULL)
6804*7c568831SAndroid Build Coastguard Worker         return(ctxt->context->node->next);
6805*7c568831SAndroid Build Coastguard Worker     return(cur->next);
6806*7c568831SAndroid Build Coastguard Worker }
6807*7c568831SAndroid Build Coastguard Worker 
6808*7c568831SAndroid Build Coastguard Worker /**
6809*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextPrecedingSibling:
6810*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6811*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6812*7c568831SAndroid Build Coastguard Worker  *
6813*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "preceding-sibling" direction
6814*7c568831SAndroid Build Coastguard Worker  * The preceding-sibling axis contains the preceding siblings of the context
6815*7c568831SAndroid Build Coastguard Worker  * node in reverse document order; the first preceding sibling is first on the
6816*7c568831SAndroid Build Coastguard Worker  * axis; the sibling preceding that node is the second on the axis and so on.
6817*7c568831SAndroid Build Coastguard Worker  *
6818*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6819*7c568831SAndroid Build Coastguard Worker  */
6820*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6821*7c568831SAndroid Build Coastguard Worker xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6822*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6823*7c568831SAndroid Build Coastguard Worker     if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6824*7c568831SAndroid Build Coastguard Worker 	(ctxt->context->node->type == XML_NAMESPACE_DECL))
6825*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6826*7c568831SAndroid Build Coastguard Worker     if (cur == (xmlNodePtr) ctxt->context->doc)
6827*7c568831SAndroid Build Coastguard Worker         return(NULL);
6828*7c568831SAndroid Build Coastguard Worker     if (cur == NULL)
6829*7c568831SAndroid Build Coastguard Worker         return(ctxt->context->node->prev);
6830*7c568831SAndroid Build Coastguard Worker     if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
6831*7c568831SAndroid Build Coastguard Worker 	cur = cur->prev;
6832*7c568831SAndroid Build Coastguard Worker 	if (cur == NULL)
6833*7c568831SAndroid Build Coastguard Worker 	    return(ctxt->context->node->prev);
6834*7c568831SAndroid Build Coastguard Worker     }
6835*7c568831SAndroid Build Coastguard Worker     return(cur->prev);
6836*7c568831SAndroid Build Coastguard Worker }
6837*7c568831SAndroid Build Coastguard Worker 
6838*7c568831SAndroid Build Coastguard Worker /**
6839*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextFollowing:
6840*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6841*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6842*7c568831SAndroid Build Coastguard Worker  *
6843*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "following" direction
6844*7c568831SAndroid Build Coastguard Worker  * The following axis contains all nodes in the same document as the context
6845*7c568831SAndroid Build Coastguard Worker  * node that are after the context node in document order, excluding any
6846*7c568831SAndroid Build Coastguard Worker  * descendants and excluding attribute nodes and namespace nodes; the nodes
6847*7c568831SAndroid Build Coastguard Worker  * are ordered in document order
6848*7c568831SAndroid Build Coastguard Worker  *
6849*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6850*7c568831SAndroid Build Coastguard Worker  */
6851*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6852*7c568831SAndroid Build Coastguard Worker xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6853*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6854*7c568831SAndroid Build Coastguard Worker     if ((cur != NULL) && (cur->type  != XML_ATTRIBUTE_NODE) &&
6855*7c568831SAndroid Build Coastguard Worker         (cur->type != XML_NAMESPACE_DECL) && (cur->children != NULL))
6856*7c568831SAndroid Build Coastguard Worker         return(cur->children);
6857*7c568831SAndroid Build Coastguard Worker 
6858*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
6859*7c568831SAndroid Build Coastguard Worker         cur = ctxt->context->node;
6860*7c568831SAndroid Build Coastguard Worker         if (cur->type == XML_ATTRIBUTE_NODE) {
6861*7c568831SAndroid Build Coastguard Worker             cur = cur->parent;
6862*7c568831SAndroid Build Coastguard Worker         } else if (cur->type == XML_NAMESPACE_DECL) {
6863*7c568831SAndroid Build Coastguard Worker             xmlNsPtr ns = (xmlNsPtr) cur;
6864*7c568831SAndroid Build Coastguard Worker 
6865*7c568831SAndroid Build Coastguard Worker             if ((ns->next == NULL) ||
6866*7c568831SAndroid Build Coastguard Worker                 (ns->next->type == XML_NAMESPACE_DECL))
6867*7c568831SAndroid Build Coastguard Worker                 return (NULL);
6868*7c568831SAndroid Build Coastguard Worker             cur = (xmlNodePtr) ns->next;
6869*7c568831SAndroid Build Coastguard Worker         }
6870*7c568831SAndroid Build Coastguard Worker     }
6871*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) return(NULL) ; /* ERROR */
6872*7c568831SAndroid Build Coastguard Worker     if (cur->next != NULL) return(cur->next) ;
6873*7c568831SAndroid Build Coastguard Worker     do {
6874*7c568831SAndroid Build Coastguard Worker         cur = cur->parent;
6875*7c568831SAndroid Build Coastguard Worker         if (cur == NULL) break;
6876*7c568831SAndroid Build Coastguard Worker         if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
6877*7c568831SAndroid Build Coastguard Worker         if (cur->next != NULL) return(cur->next);
6878*7c568831SAndroid Build Coastguard Worker     } while (cur != NULL);
6879*7c568831SAndroid Build Coastguard Worker     return(cur);
6880*7c568831SAndroid Build Coastguard Worker }
6881*7c568831SAndroid Build Coastguard Worker 
6882*7c568831SAndroid Build Coastguard Worker /*
6883*7c568831SAndroid Build Coastguard Worker  * xmlXPathIsAncestor:
6884*7c568831SAndroid Build Coastguard Worker  * @ancestor:  the ancestor node
6885*7c568831SAndroid Build Coastguard Worker  * @node:  the current node
6886*7c568831SAndroid Build Coastguard Worker  *
6887*7c568831SAndroid Build Coastguard Worker  * Check that @ancestor is a @node's ancestor
6888*7c568831SAndroid Build Coastguard Worker  *
6889*7c568831SAndroid Build Coastguard Worker  * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
6890*7c568831SAndroid Build Coastguard Worker  */
6891*7c568831SAndroid Build Coastguard Worker static int
xmlXPathIsAncestor(xmlNodePtr ancestor,xmlNodePtr node)6892*7c568831SAndroid Build Coastguard Worker xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
6893*7c568831SAndroid Build Coastguard Worker     if ((ancestor == NULL) || (node == NULL)) return(0);
6894*7c568831SAndroid Build Coastguard Worker     if (node->type == XML_NAMESPACE_DECL)
6895*7c568831SAndroid Build Coastguard Worker         return(0);
6896*7c568831SAndroid Build Coastguard Worker     if (ancestor->type == XML_NAMESPACE_DECL)
6897*7c568831SAndroid Build Coastguard Worker         return(0);
6898*7c568831SAndroid Build Coastguard Worker     /* nodes need to be in the same document */
6899*7c568831SAndroid Build Coastguard Worker     if (ancestor->doc != node->doc) return(0);
6900*7c568831SAndroid Build Coastguard Worker     /* avoid searching if ancestor or node is the root node */
6901*7c568831SAndroid Build Coastguard Worker     if (ancestor == (xmlNodePtr) node->doc) return(1);
6902*7c568831SAndroid Build Coastguard Worker     if (node == (xmlNodePtr) ancestor->doc) return(0);
6903*7c568831SAndroid Build Coastguard Worker     while (node->parent != NULL) {
6904*7c568831SAndroid Build Coastguard Worker         if (node->parent == ancestor)
6905*7c568831SAndroid Build Coastguard Worker             return(1);
6906*7c568831SAndroid Build Coastguard Worker 	node = node->parent;
6907*7c568831SAndroid Build Coastguard Worker     }
6908*7c568831SAndroid Build Coastguard Worker     return(0);
6909*7c568831SAndroid Build Coastguard Worker }
6910*7c568831SAndroid Build Coastguard Worker 
6911*7c568831SAndroid Build Coastguard Worker /**
6912*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextPreceding:
6913*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6914*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6915*7c568831SAndroid Build Coastguard Worker  *
6916*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "preceding" direction
6917*7c568831SAndroid Build Coastguard Worker  * the preceding axis contains all nodes in the same document as the context
6918*7c568831SAndroid Build Coastguard Worker  * node that are before the context node in document order, excluding any
6919*7c568831SAndroid Build Coastguard Worker  * ancestors and excluding attribute nodes and namespace nodes; the nodes are
6920*7c568831SAndroid Build Coastguard Worker  * ordered in reverse document order
6921*7c568831SAndroid Build Coastguard Worker  *
6922*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6923*7c568831SAndroid Build Coastguard Worker  */
6924*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6925*7c568831SAndroid Build Coastguard Worker xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
6926*7c568831SAndroid Build Coastguard Worker {
6927*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6928*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
6929*7c568831SAndroid Build Coastguard Worker         cur = ctxt->context->node;
6930*7c568831SAndroid Build Coastguard Worker         if (cur->type == XML_ATTRIBUTE_NODE) {
6931*7c568831SAndroid Build Coastguard Worker             cur = cur->parent;
6932*7c568831SAndroid Build Coastguard Worker         } else if (cur->type == XML_NAMESPACE_DECL) {
6933*7c568831SAndroid Build Coastguard Worker             xmlNsPtr ns = (xmlNsPtr) cur;
6934*7c568831SAndroid Build Coastguard Worker 
6935*7c568831SAndroid Build Coastguard Worker             if ((ns->next == NULL) ||
6936*7c568831SAndroid Build Coastguard Worker                 (ns->next->type == XML_NAMESPACE_DECL))
6937*7c568831SAndroid Build Coastguard Worker                 return (NULL);
6938*7c568831SAndroid Build Coastguard Worker             cur = (xmlNodePtr) ns->next;
6939*7c568831SAndroid Build Coastguard Worker         }
6940*7c568831SAndroid Build Coastguard Worker     }
6941*7c568831SAndroid Build Coastguard Worker     if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
6942*7c568831SAndroid Build Coastguard Worker 	return (NULL);
6943*7c568831SAndroid Build Coastguard Worker     if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
6944*7c568831SAndroid Build Coastguard Worker 	cur = cur->prev;
6945*7c568831SAndroid Build Coastguard Worker     do {
6946*7c568831SAndroid Build Coastguard Worker         if (cur->prev != NULL) {
6947*7c568831SAndroid Build Coastguard Worker             for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
6948*7c568831SAndroid Build Coastguard Worker             return (cur);
6949*7c568831SAndroid Build Coastguard Worker         }
6950*7c568831SAndroid Build Coastguard Worker 
6951*7c568831SAndroid Build Coastguard Worker         cur = cur->parent;
6952*7c568831SAndroid Build Coastguard Worker         if (cur == NULL)
6953*7c568831SAndroid Build Coastguard Worker             return (NULL);
6954*7c568831SAndroid Build Coastguard Worker         if (cur == ctxt->context->doc->children)
6955*7c568831SAndroid Build Coastguard Worker             return (NULL);
6956*7c568831SAndroid Build Coastguard Worker     } while (xmlXPathIsAncestor(cur, ctxt->context->node));
6957*7c568831SAndroid Build Coastguard Worker     return (cur);
6958*7c568831SAndroid Build Coastguard Worker }
6959*7c568831SAndroid Build Coastguard Worker 
6960*7c568831SAndroid Build Coastguard Worker /**
6961*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextPrecedingInternal:
6962*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
6963*7c568831SAndroid Build Coastguard Worker  * @cur:  the current node in the traversal
6964*7c568831SAndroid Build Coastguard Worker  *
6965*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "preceding" direction
6966*7c568831SAndroid Build Coastguard Worker  * the preceding axis contains all nodes in the same document as the context
6967*7c568831SAndroid Build Coastguard Worker  * node that are before the context node in document order, excluding any
6968*7c568831SAndroid Build Coastguard Worker  * ancestors and excluding attribute nodes and namespace nodes; the nodes are
6969*7c568831SAndroid Build Coastguard Worker  * ordered in reverse document order
6970*7c568831SAndroid Build Coastguard Worker  * This is a faster implementation but internal only since it requires a
6971*7c568831SAndroid Build Coastguard Worker  * state kept in the parser context: ctxt->ancestor.
6972*7c568831SAndroid Build Coastguard Worker  *
6973*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
6974*7c568831SAndroid Build Coastguard Worker  */
6975*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6976*7c568831SAndroid Build Coastguard Worker xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
6977*7c568831SAndroid Build Coastguard Worker                               xmlNodePtr cur)
6978*7c568831SAndroid Build Coastguard Worker {
6979*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6980*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
6981*7c568831SAndroid Build Coastguard Worker         cur = ctxt->context->node;
6982*7c568831SAndroid Build Coastguard Worker         if (cur == NULL)
6983*7c568831SAndroid Build Coastguard Worker             return (NULL);
6984*7c568831SAndroid Build Coastguard Worker         if (cur->type == XML_ATTRIBUTE_NODE) {
6985*7c568831SAndroid Build Coastguard Worker             cur = cur->parent;
6986*7c568831SAndroid Build Coastguard Worker         } else if (cur->type == XML_NAMESPACE_DECL) {
6987*7c568831SAndroid Build Coastguard Worker             xmlNsPtr ns = (xmlNsPtr) cur;
6988*7c568831SAndroid Build Coastguard Worker 
6989*7c568831SAndroid Build Coastguard Worker             if ((ns->next == NULL) ||
6990*7c568831SAndroid Build Coastguard Worker                 (ns->next->type == XML_NAMESPACE_DECL))
6991*7c568831SAndroid Build Coastguard Worker                 return (NULL);
6992*7c568831SAndroid Build Coastguard Worker             cur = (xmlNodePtr) ns->next;
6993*7c568831SAndroid Build Coastguard Worker         }
6994*7c568831SAndroid Build Coastguard Worker         ctxt->ancestor = cur->parent;
6995*7c568831SAndroid Build Coastguard Worker     }
6996*7c568831SAndroid Build Coastguard Worker     if (cur->type == XML_NAMESPACE_DECL)
6997*7c568831SAndroid Build Coastguard Worker         return(NULL);
6998*7c568831SAndroid Build Coastguard Worker     if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
6999*7c568831SAndroid Build Coastguard Worker 	cur = cur->prev;
7000*7c568831SAndroid Build Coastguard Worker     while (cur->prev == NULL) {
7001*7c568831SAndroid Build Coastguard Worker         cur = cur->parent;
7002*7c568831SAndroid Build Coastguard Worker         if (cur == NULL)
7003*7c568831SAndroid Build Coastguard Worker             return (NULL);
7004*7c568831SAndroid Build Coastguard Worker         if (cur == ctxt->context->doc->children)
7005*7c568831SAndroid Build Coastguard Worker             return (NULL);
7006*7c568831SAndroid Build Coastguard Worker         if (cur != ctxt->ancestor)
7007*7c568831SAndroid Build Coastguard Worker             return (cur);
7008*7c568831SAndroid Build Coastguard Worker         ctxt->ancestor = cur->parent;
7009*7c568831SAndroid Build Coastguard Worker     }
7010*7c568831SAndroid Build Coastguard Worker     cur = cur->prev;
7011*7c568831SAndroid Build Coastguard Worker     while (cur->last != NULL)
7012*7c568831SAndroid Build Coastguard Worker         cur = cur->last;
7013*7c568831SAndroid Build Coastguard Worker     return (cur);
7014*7c568831SAndroid Build Coastguard Worker }
7015*7c568831SAndroid Build Coastguard Worker 
7016*7c568831SAndroid Build Coastguard Worker /**
7017*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextNamespace:
7018*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7019*7c568831SAndroid Build Coastguard Worker  * @cur:  the current attribute in the traversal
7020*7c568831SAndroid Build Coastguard Worker  *
7021*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "namespace" direction
7022*7c568831SAndroid Build Coastguard Worker  * the namespace axis contains the namespace nodes of the context node;
7023*7c568831SAndroid Build Coastguard Worker  * the order of nodes on this axis is implementation-defined; the axis will
7024*7c568831SAndroid Build Coastguard Worker  * be empty unless the context node is an element
7025*7c568831SAndroid Build Coastguard Worker  *
7026*7c568831SAndroid Build Coastguard Worker  * We keep the XML namespace node at the end of the list.
7027*7c568831SAndroid Build Coastguard Worker  *
7028*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
7029*7c568831SAndroid Build Coastguard Worker  */
7030*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7031*7c568831SAndroid Build Coastguard Worker xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7032*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7033*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
7034*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
7035*7c568831SAndroid Build Coastguard Worker         if (ctxt->context->tmpNsList != NULL)
7036*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ctxt->context->tmpNsList);
7037*7c568831SAndroid Build Coastguard Worker 	ctxt->context->tmpNsNr = 0;
7038*7c568831SAndroid Build Coastguard Worker         if (xmlGetNsListSafe(ctxt->context->doc, ctxt->context->node,
7039*7c568831SAndroid Build Coastguard Worker                              &ctxt->context->tmpNsList) < 0) {
7040*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
7041*7c568831SAndroid Build Coastguard Worker             return(NULL);
7042*7c568831SAndroid Build Coastguard Worker         }
7043*7c568831SAndroid Build Coastguard Worker         if (ctxt->context->tmpNsList != NULL) {
7044*7c568831SAndroid Build Coastguard Worker             while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
7045*7c568831SAndroid Build Coastguard Worker                 ctxt->context->tmpNsNr++;
7046*7c568831SAndroid Build Coastguard Worker             }
7047*7c568831SAndroid Build Coastguard Worker         }
7048*7c568831SAndroid Build Coastguard Worker 	return((xmlNodePtr) xmlXPathXMLNamespace);
7049*7c568831SAndroid Build Coastguard Worker     }
7050*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->tmpNsNr > 0) {
7051*7c568831SAndroid Build Coastguard Worker 	return (xmlNodePtr)ctxt->context->tmpNsList[--ctxt->context->tmpNsNr];
7052*7c568831SAndroid Build Coastguard Worker     } else {
7053*7c568831SAndroid Build Coastguard Worker 	if (ctxt->context->tmpNsList != NULL)
7054*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ctxt->context->tmpNsList);
7055*7c568831SAndroid Build Coastguard Worker 	ctxt->context->tmpNsList = NULL;
7056*7c568831SAndroid Build Coastguard Worker 	return(NULL);
7057*7c568831SAndroid Build Coastguard Worker     }
7058*7c568831SAndroid Build Coastguard Worker }
7059*7c568831SAndroid Build Coastguard Worker 
7060*7c568831SAndroid Build Coastguard Worker /**
7061*7c568831SAndroid Build Coastguard Worker  * xmlXPathNextAttribute:
7062*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7063*7c568831SAndroid Build Coastguard Worker  * @cur:  the current attribute in the traversal
7064*7c568831SAndroid Build Coastguard Worker  *
7065*7c568831SAndroid Build Coastguard Worker  * Traversal function for the "attribute" direction
7066*7c568831SAndroid Build Coastguard Worker  * TODO: support DTD inherited default attributes
7067*7c568831SAndroid Build Coastguard Worker  *
7068*7c568831SAndroid Build Coastguard Worker  * Returns the next element following that axis
7069*7c568831SAndroid Build Coastguard Worker  */
7070*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7071*7c568831SAndroid Build Coastguard Worker xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7072*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7073*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->node == NULL)
7074*7c568831SAndroid Build Coastguard Worker 	return(NULL);
7075*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->node->type != XML_ELEMENT_NODE)
7076*7c568831SAndroid Build Coastguard Worker 	return(NULL);
7077*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
7078*7c568831SAndroid Build Coastguard Worker         if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
7079*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7080*7c568831SAndroid Build Coastguard Worker         return((xmlNodePtr)ctxt->context->node->properties);
7081*7c568831SAndroid Build Coastguard Worker     }
7082*7c568831SAndroid Build Coastguard Worker     return((xmlNodePtr)cur->next);
7083*7c568831SAndroid Build Coastguard Worker }
7084*7c568831SAndroid Build Coastguard Worker 
7085*7c568831SAndroid Build Coastguard Worker /************************************************************************
7086*7c568831SAndroid Build Coastguard Worker  *									*
7087*7c568831SAndroid Build Coastguard Worker  *		NodeTest Functions					*
7088*7c568831SAndroid Build Coastguard Worker  *									*
7089*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
7090*7c568831SAndroid Build Coastguard Worker 
7091*7c568831SAndroid Build Coastguard Worker #define IS_FUNCTION			200
7092*7c568831SAndroid Build Coastguard Worker 
7093*7c568831SAndroid Build Coastguard Worker 
7094*7c568831SAndroid Build Coastguard Worker /************************************************************************
7095*7c568831SAndroid Build Coastguard Worker  *									*
7096*7c568831SAndroid Build Coastguard Worker  *		Implicit tree core function library			*
7097*7c568831SAndroid Build Coastguard Worker  *									*
7098*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
7099*7c568831SAndroid Build Coastguard Worker 
7100*7c568831SAndroid Build Coastguard Worker /**
7101*7c568831SAndroid Build Coastguard Worker  * xmlXPathRoot:
7102*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7103*7c568831SAndroid Build Coastguard Worker  *
7104*7c568831SAndroid Build Coastguard Worker  * Initialize the context to the root of the document
7105*7c568831SAndroid Build Coastguard Worker  */
7106*7c568831SAndroid Build Coastguard Worker void
xmlXPathRoot(xmlXPathParserContextPtr ctxt)7107*7c568831SAndroid Build Coastguard Worker xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
7108*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL))
7109*7c568831SAndroid Build Coastguard Worker 	return;
7110*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
7111*7c568831SAndroid Build Coastguard Worker                                             (xmlNodePtr) ctxt->context->doc));
7112*7c568831SAndroid Build Coastguard Worker }
7113*7c568831SAndroid Build Coastguard Worker 
7114*7c568831SAndroid Build Coastguard Worker /************************************************************************
7115*7c568831SAndroid Build Coastguard Worker  *									*
7116*7c568831SAndroid Build Coastguard Worker  *		The explicit core function library			*
7117*7c568831SAndroid Build Coastguard Worker  *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib	*
7118*7c568831SAndroid Build Coastguard Worker  *									*
7119*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
7120*7c568831SAndroid Build Coastguard Worker 
7121*7c568831SAndroid Build Coastguard Worker 
7122*7c568831SAndroid Build Coastguard Worker /**
7123*7c568831SAndroid Build Coastguard Worker  * xmlXPathLastFunction:
7124*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7125*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7126*7c568831SAndroid Build Coastguard Worker  *
7127*7c568831SAndroid Build Coastguard Worker  * Implement the last() XPath function
7128*7c568831SAndroid Build Coastguard Worker  *    number last()
7129*7c568831SAndroid Build Coastguard Worker  * The last function returns the number of nodes in the context node list.
7130*7c568831SAndroid Build Coastguard Worker  */
7131*7c568831SAndroid Build Coastguard Worker void
xmlXPathLastFunction(xmlXPathParserContextPtr ctxt,int nargs)7132*7c568831SAndroid Build Coastguard Worker xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7133*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(0);
7134*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->contextSize >= 0) {
7135*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt,
7136*7c568831SAndroid Build Coastguard Worker 	    xmlXPathCacheNewFloat(ctxt, (double) ctxt->context->contextSize));
7137*7c568831SAndroid Build Coastguard Worker     } else {
7138*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_CTXT_SIZE);
7139*7c568831SAndroid Build Coastguard Worker     }
7140*7c568831SAndroid Build Coastguard Worker }
7141*7c568831SAndroid Build Coastguard Worker 
7142*7c568831SAndroid Build Coastguard Worker /**
7143*7c568831SAndroid Build Coastguard Worker  * xmlXPathPositionFunction:
7144*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7145*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7146*7c568831SAndroid Build Coastguard Worker  *
7147*7c568831SAndroid Build Coastguard Worker  * Implement the position() XPath function
7148*7c568831SAndroid Build Coastguard Worker  *    number position()
7149*7c568831SAndroid Build Coastguard Worker  * The position function returns the position of the context node in the
7150*7c568831SAndroid Build Coastguard Worker  * context node list. The first position is 1, and so the last position
7151*7c568831SAndroid Build Coastguard Worker  * will be equal to last().
7152*7c568831SAndroid Build Coastguard Worker  */
7153*7c568831SAndroid Build Coastguard Worker void
xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt,int nargs)7154*7c568831SAndroid Build Coastguard Worker xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7155*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(0);
7156*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->proximityPosition >= 0) {
7157*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7158*7c568831SAndroid Build Coastguard Worker             (double) ctxt->context->proximityPosition));
7159*7c568831SAndroid Build Coastguard Worker     } else {
7160*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_CTXT_POSITION);
7161*7c568831SAndroid Build Coastguard Worker     }
7162*7c568831SAndroid Build Coastguard Worker }
7163*7c568831SAndroid Build Coastguard Worker 
7164*7c568831SAndroid Build Coastguard Worker /**
7165*7c568831SAndroid Build Coastguard Worker  * xmlXPathCountFunction:
7166*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7167*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7168*7c568831SAndroid Build Coastguard Worker  *
7169*7c568831SAndroid Build Coastguard Worker  * Implement the count() XPath function
7170*7c568831SAndroid Build Coastguard Worker  *    number count(node-set)
7171*7c568831SAndroid Build Coastguard Worker  */
7172*7c568831SAndroid Build Coastguard Worker void
xmlXPathCountFunction(xmlXPathParserContextPtr ctxt,int nargs)7173*7c568831SAndroid Build Coastguard Worker xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7174*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
7175*7c568831SAndroid Build Coastguard Worker 
7176*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
7177*7c568831SAndroid Build Coastguard Worker     if ((ctxt->value == NULL) ||
7178*7c568831SAndroid Build Coastguard Worker 	((ctxt->value->type != XPATH_NODESET) &&
7179*7c568831SAndroid Build Coastguard Worker 	 (ctxt->value->type != XPATH_XSLT_TREE)))
7180*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_TYPE);
7181*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
7182*7c568831SAndroid Build Coastguard Worker 
7183*7c568831SAndroid Build Coastguard Worker     if ((cur == NULL) || (cur->nodesetval == NULL))
7184*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0));
7185*7c568831SAndroid Build Coastguard Worker     else
7186*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7187*7c568831SAndroid Build Coastguard Worker 	    (double) cur->nodesetval->nodeNr));
7188*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, cur);
7189*7c568831SAndroid Build Coastguard Worker }
7190*7c568831SAndroid Build Coastguard Worker 
7191*7c568831SAndroid Build Coastguard Worker /**
7192*7c568831SAndroid Build Coastguard Worker  * xmlXPathGetElementsByIds:
7193*7c568831SAndroid Build Coastguard Worker  * @doc:  the document
7194*7c568831SAndroid Build Coastguard Worker  * @ids:  a whitespace separated list of IDs
7195*7c568831SAndroid Build Coastguard Worker  *
7196*7c568831SAndroid Build Coastguard Worker  * Selects elements by their unique ID.
7197*7c568831SAndroid Build Coastguard Worker  *
7198*7c568831SAndroid Build Coastguard Worker  * Returns a node-set of selected elements.
7199*7c568831SAndroid Build Coastguard Worker  */
7200*7c568831SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathGetElementsByIds(xmlDocPtr doc,const xmlChar * ids)7201*7c568831SAndroid Build Coastguard Worker xmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
7202*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret;
7203*7c568831SAndroid Build Coastguard Worker     const xmlChar *cur = ids;
7204*7c568831SAndroid Build Coastguard Worker     xmlChar *ID;
7205*7c568831SAndroid Build Coastguard Worker     xmlAttrPtr attr;
7206*7c568831SAndroid Build Coastguard Worker     xmlNodePtr elem = NULL;
7207*7c568831SAndroid Build Coastguard Worker 
7208*7c568831SAndroid Build Coastguard Worker     if (ids == NULL) return(NULL);
7209*7c568831SAndroid Build Coastguard Worker 
7210*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathNodeSetCreate(NULL);
7211*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
7212*7c568831SAndroid Build Coastguard Worker         return(ret);
7213*7c568831SAndroid Build Coastguard Worker 
7214*7c568831SAndroid Build Coastguard Worker     while (IS_BLANK_CH(*cur)) cur++;
7215*7c568831SAndroid Build Coastguard Worker     while (*cur != 0) {
7216*7c568831SAndroid Build Coastguard Worker 	while ((!IS_BLANK_CH(*cur)) && (*cur != 0))
7217*7c568831SAndroid Build Coastguard Worker 	    cur++;
7218*7c568831SAndroid Build Coastguard Worker 
7219*7c568831SAndroid Build Coastguard Worker         ID = xmlStrndup(ids, cur - ids);
7220*7c568831SAndroid Build Coastguard Worker 	if (ID == NULL) {
7221*7c568831SAndroid Build Coastguard Worker             xmlXPathFreeNodeSet(ret);
7222*7c568831SAndroid Build Coastguard Worker             return(NULL);
7223*7c568831SAndroid Build Coastguard Worker         }
7224*7c568831SAndroid Build Coastguard Worker         /*
7225*7c568831SAndroid Build Coastguard Worker          * We used to check the fact that the value passed
7226*7c568831SAndroid Build Coastguard Worker          * was an NCName, but this generated much troubles for
7227*7c568831SAndroid Build Coastguard Worker          * me and Aleksey Sanin, people blatantly violated that
7228*7c568831SAndroid Build Coastguard Worker          * constraint, like Visa3D spec.
7229*7c568831SAndroid Build Coastguard Worker          * if (xmlValidateNCName(ID, 1) == 0)
7230*7c568831SAndroid Build Coastguard Worker          */
7231*7c568831SAndroid Build Coastguard Worker         attr = xmlGetID(doc, ID);
7232*7c568831SAndroid Build Coastguard Worker         xmlFree(ID);
7233*7c568831SAndroid Build Coastguard Worker         if (attr != NULL) {
7234*7c568831SAndroid Build Coastguard Worker             if (attr->type == XML_ATTRIBUTE_NODE)
7235*7c568831SAndroid Build Coastguard Worker                 elem = attr->parent;
7236*7c568831SAndroid Build Coastguard Worker             else if (attr->type == XML_ELEMENT_NODE)
7237*7c568831SAndroid Build Coastguard Worker                 elem = (xmlNodePtr) attr;
7238*7c568831SAndroid Build Coastguard Worker             else
7239*7c568831SAndroid Build Coastguard Worker                 elem = NULL;
7240*7c568831SAndroid Build Coastguard Worker             if (elem != NULL) {
7241*7c568831SAndroid Build Coastguard Worker                 if (xmlXPathNodeSetAdd(ret, elem) < 0) {
7242*7c568831SAndroid Build Coastguard Worker                     xmlXPathFreeNodeSet(ret);
7243*7c568831SAndroid Build Coastguard Worker                     return(NULL);
7244*7c568831SAndroid Build Coastguard Worker                 }
7245*7c568831SAndroid Build Coastguard Worker             }
7246*7c568831SAndroid Build Coastguard Worker         }
7247*7c568831SAndroid Build Coastguard Worker 
7248*7c568831SAndroid Build Coastguard Worker 	while (IS_BLANK_CH(*cur)) cur++;
7249*7c568831SAndroid Build Coastguard Worker 	ids = cur;
7250*7c568831SAndroid Build Coastguard Worker     }
7251*7c568831SAndroid Build Coastguard Worker     return(ret);
7252*7c568831SAndroid Build Coastguard Worker }
7253*7c568831SAndroid Build Coastguard Worker 
7254*7c568831SAndroid Build Coastguard Worker /**
7255*7c568831SAndroid Build Coastguard Worker  * xmlXPathIdFunction:
7256*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7257*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7258*7c568831SAndroid Build Coastguard Worker  *
7259*7c568831SAndroid Build Coastguard Worker  * Implement the id() XPath function
7260*7c568831SAndroid Build Coastguard Worker  *    node-set id(object)
7261*7c568831SAndroid Build Coastguard Worker  * The id function selects elements by their unique ID
7262*7c568831SAndroid Build Coastguard Worker  * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set,
7263*7c568831SAndroid Build Coastguard Worker  * then the result is the union of the result of applying id to the
7264*7c568831SAndroid Build Coastguard Worker  * string value of each of the nodes in the argument node-set. When the
7265*7c568831SAndroid Build Coastguard Worker  * argument to id is of any other type, the argument is converted to a
7266*7c568831SAndroid Build Coastguard Worker  * string as if by a call to the string function; the string is split
7267*7c568831SAndroid Build Coastguard Worker  * into a whitespace-separated list of tokens (whitespace is any sequence
7268*7c568831SAndroid Build Coastguard Worker  * of characters matching the production S); the result is a node-set
7269*7c568831SAndroid Build Coastguard Worker  * containing the elements in the same document as the context node that
7270*7c568831SAndroid Build Coastguard Worker  * have a unique ID equal to any of the tokens in the list.
7271*7c568831SAndroid Build Coastguard Worker  */
7272*7c568831SAndroid Build Coastguard Worker void
xmlXPathIdFunction(xmlXPathParserContextPtr ctxt,int nargs)7273*7c568831SAndroid Build Coastguard Worker xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7274*7c568831SAndroid Build Coastguard Worker     xmlChar *tokens;
7275*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr ret;
7276*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr obj;
7277*7c568831SAndroid Build Coastguard Worker 
7278*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
7279*7c568831SAndroid Build Coastguard Worker     obj = valuePop(ctxt);
7280*7c568831SAndroid Build Coastguard Worker     if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
7281*7c568831SAndroid Build Coastguard Worker     if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
7282*7c568831SAndroid Build Coastguard Worker 	xmlNodeSetPtr ns;
7283*7c568831SAndroid Build Coastguard Worker 	int i;
7284*7c568831SAndroid Build Coastguard Worker 
7285*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathNodeSetCreate(NULL);
7286*7c568831SAndroid Build Coastguard Worker         if (ret == NULL)
7287*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
7288*7c568831SAndroid Build Coastguard Worker 
7289*7c568831SAndroid Build Coastguard Worker 	if (obj->nodesetval != NULL) {
7290*7c568831SAndroid Build Coastguard Worker 	    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
7291*7c568831SAndroid Build Coastguard Worker 		tokens =
7292*7c568831SAndroid Build Coastguard Worker 		    xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
7293*7c568831SAndroid Build Coastguard Worker                 if (tokens == NULL)
7294*7c568831SAndroid Build Coastguard Worker                     xmlXPathPErrMemory(ctxt);
7295*7c568831SAndroid Build Coastguard Worker 		ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
7296*7c568831SAndroid Build Coastguard Worker                 if (ns == NULL)
7297*7c568831SAndroid Build Coastguard Worker                     xmlXPathPErrMemory(ctxt);
7298*7c568831SAndroid Build Coastguard Worker 		ret = xmlXPathNodeSetMerge(ret, ns);
7299*7c568831SAndroid Build Coastguard Worker                 if (ret == NULL)
7300*7c568831SAndroid Build Coastguard Worker                     xmlXPathPErrMemory(ctxt);
7301*7c568831SAndroid Build Coastguard Worker 		xmlXPathFreeNodeSet(ns);
7302*7c568831SAndroid Build Coastguard Worker 		if (tokens != NULL)
7303*7c568831SAndroid Build Coastguard Worker 		    xmlFree(tokens);
7304*7c568831SAndroid Build Coastguard Worker 	    }
7305*7c568831SAndroid Build Coastguard Worker 	}
7306*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, obj);
7307*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret));
7308*7c568831SAndroid Build Coastguard Worker 	return;
7309*7c568831SAndroid Build Coastguard Worker     }
7310*7c568831SAndroid Build Coastguard Worker     tokens = xmlXPathCastToString(obj);
7311*7c568831SAndroid Build Coastguard Worker     if (tokens == NULL)
7312*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
7313*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, obj);
7314*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
7315*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
7316*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
7317*7c568831SAndroid Build Coastguard Worker     xmlFree(tokens);
7318*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret));
7319*7c568831SAndroid Build Coastguard Worker }
7320*7c568831SAndroid Build Coastguard Worker 
7321*7c568831SAndroid Build Coastguard Worker /**
7322*7c568831SAndroid Build Coastguard Worker  * xmlXPathLocalNameFunction:
7323*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7324*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7325*7c568831SAndroid Build Coastguard Worker  *
7326*7c568831SAndroid Build Coastguard Worker  * Implement the local-name() XPath function
7327*7c568831SAndroid Build Coastguard Worker  *    string local-name(node-set?)
7328*7c568831SAndroid Build Coastguard Worker  * The local-name function returns a string containing the local part
7329*7c568831SAndroid Build Coastguard Worker  * of the name of the node in the argument node-set that is first in
7330*7c568831SAndroid Build Coastguard Worker  * document order. If the node-set is empty or the first node has no
7331*7c568831SAndroid Build Coastguard Worker  * name, an empty string is returned. If the argument is omitted it
7332*7c568831SAndroid Build Coastguard Worker  * defaults to the context node.
7333*7c568831SAndroid Build Coastguard Worker  */
7334*7c568831SAndroid Build Coastguard Worker void
xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt,int nargs)7335*7c568831SAndroid Build Coastguard Worker xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7336*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
7337*7c568831SAndroid Build Coastguard Worker 
7338*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return;
7339*7c568831SAndroid Build Coastguard Worker 
7340*7c568831SAndroid Build Coastguard Worker     if (nargs == 0) {
7341*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7342*7c568831SAndroid Build Coastguard Worker 	nargs = 1;
7343*7c568831SAndroid Build Coastguard Worker     }
7344*7c568831SAndroid Build Coastguard Worker 
7345*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
7346*7c568831SAndroid Build Coastguard Worker     if ((ctxt->value == NULL) ||
7347*7c568831SAndroid Build Coastguard Worker 	((ctxt->value->type != XPATH_NODESET) &&
7348*7c568831SAndroid Build Coastguard Worker 	 (ctxt->value->type != XPATH_XSLT_TREE)))
7349*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_TYPE);
7350*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
7351*7c568831SAndroid Build Coastguard Worker 
7352*7c568831SAndroid Build Coastguard Worker     if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7353*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7354*7c568831SAndroid Build Coastguard Worker     } else {
7355*7c568831SAndroid Build Coastguard Worker 	int i = 0; /* Should be first in document order !!!!! */
7356*7c568831SAndroid Build Coastguard Worker 	switch (cur->nodesetval->nodeTab[i]->type) {
7357*7c568831SAndroid Build Coastguard Worker 	case XML_ELEMENT_NODE:
7358*7c568831SAndroid Build Coastguard Worker 	case XML_ATTRIBUTE_NODE:
7359*7c568831SAndroid Build Coastguard Worker 	case XML_PI_NODE:
7360*7c568831SAndroid Build Coastguard Worker 	    if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
7361*7c568831SAndroid Build Coastguard Worker 		valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7362*7c568831SAndroid Build Coastguard Worker 	    else
7363*7c568831SAndroid Build Coastguard Worker 		valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7364*7c568831SAndroid Build Coastguard Worker 			cur->nodesetval->nodeTab[i]->name));
7365*7c568831SAndroid Build Coastguard Worker 	    break;
7366*7c568831SAndroid Build Coastguard Worker 	case XML_NAMESPACE_DECL:
7367*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7368*7c568831SAndroid Build Coastguard Worker 			((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
7369*7c568831SAndroid Build Coastguard Worker 	    break;
7370*7c568831SAndroid Build Coastguard Worker 	default:
7371*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7372*7c568831SAndroid Build Coastguard Worker 	}
7373*7c568831SAndroid Build Coastguard Worker     }
7374*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, cur);
7375*7c568831SAndroid Build Coastguard Worker }
7376*7c568831SAndroid Build Coastguard Worker 
7377*7c568831SAndroid Build Coastguard Worker /**
7378*7c568831SAndroid Build Coastguard Worker  * xmlXPathNamespaceURIFunction:
7379*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7380*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7381*7c568831SAndroid Build Coastguard Worker  *
7382*7c568831SAndroid Build Coastguard Worker  * Implement the namespace-uri() XPath function
7383*7c568831SAndroid Build Coastguard Worker  *    string namespace-uri(node-set?)
7384*7c568831SAndroid Build Coastguard Worker  * The namespace-uri function returns a string containing the
7385*7c568831SAndroid Build Coastguard Worker  * namespace URI of the expanded name of the node in the argument
7386*7c568831SAndroid Build Coastguard Worker  * node-set that is first in document order. If the node-set is empty,
7387*7c568831SAndroid Build Coastguard Worker  * the first node has no name, or the expanded name has no namespace
7388*7c568831SAndroid Build Coastguard Worker  * URI, an empty string is returned. If the argument is omitted it
7389*7c568831SAndroid Build Coastguard Worker  * defaults to the context node.
7390*7c568831SAndroid Build Coastguard Worker  */
7391*7c568831SAndroid Build Coastguard Worker void
xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt,int nargs)7392*7c568831SAndroid Build Coastguard Worker xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7393*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
7394*7c568831SAndroid Build Coastguard Worker 
7395*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return;
7396*7c568831SAndroid Build Coastguard Worker 
7397*7c568831SAndroid Build Coastguard Worker     if (nargs == 0) {
7398*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7399*7c568831SAndroid Build Coastguard Worker 	nargs = 1;
7400*7c568831SAndroid Build Coastguard Worker     }
7401*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
7402*7c568831SAndroid Build Coastguard Worker     if ((ctxt->value == NULL) ||
7403*7c568831SAndroid Build Coastguard Worker 	((ctxt->value->type != XPATH_NODESET) &&
7404*7c568831SAndroid Build Coastguard Worker 	 (ctxt->value->type != XPATH_XSLT_TREE)))
7405*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_TYPE);
7406*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
7407*7c568831SAndroid Build Coastguard Worker 
7408*7c568831SAndroid Build Coastguard Worker     if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7409*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7410*7c568831SAndroid Build Coastguard Worker     } else {
7411*7c568831SAndroid Build Coastguard Worker 	int i = 0; /* Should be first in document order !!!!! */
7412*7c568831SAndroid Build Coastguard Worker 	switch (cur->nodesetval->nodeTab[i]->type) {
7413*7c568831SAndroid Build Coastguard Worker 	case XML_ELEMENT_NODE:
7414*7c568831SAndroid Build Coastguard Worker 	case XML_ATTRIBUTE_NODE:
7415*7c568831SAndroid Build Coastguard Worker 	    if (cur->nodesetval->nodeTab[i]->ns == NULL)
7416*7c568831SAndroid Build Coastguard Worker 		valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7417*7c568831SAndroid Build Coastguard Worker 	    else
7418*7c568831SAndroid Build Coastguard Worker 		valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7419*7c568831SAndroid Build Coastguard Worker 			  cur->nodesetval->nodeTab[i]->ns->href));
7420*7c568831SAndroid Build Coastguard Worker 	    break;
7421*7c568831SAndroid Build Coastguard Worker 	default:
7422*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7423*7c568831SAndroid Build Coastguard Worker 	}
7424*7c568831SAndroid Build Coastguard Worker     }
7425*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, cur);
7426*7c568831SAndroid Build Coastguard Worker }
7427*7c568831SAndroid Build Coastguard Worker 
7428*7c568831SAndroid Build Coastguard Worker /**
7429*7c568831SAndroid Build Coastguard Worker  * xmlXPathNameFunction:
7430*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7431*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7432*7c568831SAndroid Build Coastguard Worker  *
7433*7c568831SAndroid Build Coastguard Worker  * Implement the name() XPath function
7434*7c568831SAndroid Build Coastguard Worker  *    string name(node-set?)
7435*7c568831SAndroid Build Coastguard Worker  * The name function returns a string containing a QName representing
7436*7c568831SAndroid Build Coastguard Worker  * the name of the node in the argument node-set that is first in document
7437*7c568831SAndroid Build Coastguard Worker  * order. The QName must represent the name with respect to the namespace
7438*7c568831SAndroid Build Coastguard Worker  * declarations in effect on the node whose name is being represented.
7439*7c568831SAndroid Build Coastguard Worker  * Typically, this will be the form in which the name occurred in the XML
7440*7c568831SAndroid Build Coastguard Worker  * source. This need not be the case if there are namespace declarations
7441*7c568831SAndroid Build Coastguard Worker  * in effect on the node that associate multiple prefixes with the same
7442*7c568831SAndroid Build Coastguard Worker  * namespace. However, an implementation may include information about
7443*7c568831SAndroid Build Coastguard Worker  * the original prefix in its representation of nodes; in this case, an
7444*7c568831SAndroid Build Coastguard Worker  * implementation can ensure that the returned string is always the same
7445*7c568831SAndroid Build Coastguard Worker  * as the QName used in the XML source. If the argument it omitted it
7446*7c568831SAndroid Build Coastguard Worker  * defaults to the context node.
7447*7c568831SAndroid Build Coastguard Worker  * Libxml keep the original prefix so the "real qualified name" used is
7448*7c568831SAndroid Build Coastguard Worker  * returned.
7449*7c568831SAndroid Build Coastguard Worker  */
7450*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNameFunction(xmlXPathParserContextPtr ctxt,int nargs)7451*7c568831SAndroid Build Coastguard Worker xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
7452*7c568831SAndroid Build Coastguard Worker {
7453*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
7454*7c568831SAndroid Build Coastguard Worker 
7455*7c568831SAndroid Build Coastguard Worker     if (nargs == 0) {
7456*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7457*7c568831SAndroid Build Coastguard Worker         nargs = 1;
7458*7c568831SAndroid Build Coastguard Worker     }
7459*7c568831SAndroid Build Coastguard Worker 
7460*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
7461*7c568831SAndroid Build Coastguard Worker     if ((ctxt->value == NULL) ||
7462*7c568831SAndroid Build Coastguard Worker         ((ctxt->value->type != XPATH_NODESET) &&
7463*7c568831SAndroid Build Coastguard Worker          (ctxt->value->type != XPATH_XSLT_TREE)))
7464*7c568831SAndroid Build Coastguard Worker         XP_ERROR(XPATH_INVALID_TYPE);
7465*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
7466*7c568831SAndroid Build Coastguard Worker 
7467*7c568831SAndroid Build Coastguard Worker     if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7468*7c568831SAndroid Build Coastguard Worker         valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7469*7c568831SAndroid Build Coastguard Worker     } else {
7470*7c568831SAndroid Build Coastguard Worker         int i = 0;              /* Should be first in document order !!!!! */
7471*7c568831SAndroid Build Coastguard Worker 
7472*7c568831SAndroid Build Coastguard Worker         switch (cur->nodesetval->nodeTab[i]->type) {
7473*7c568831SAndroid Build Coastguard Worker             case XML_ELEMENT_NODE:
7474*7c568831SAndroid Build Coastguard Worker             case XML_ATTRIBUTE_NODE:
7475*7c568831SAndroid Build Coastguard Worker 		if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
7476*7c568831SAndroid Build Coastguard Worker 		    valuePush(ctxt,
7477*7c568831SAndroid Build Coastguard Worker 			xmlXPathCacheNewCString(ctxt, ""));
7478*7c568831SAndroid Build Coastguard Worker 		else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
7479*7c568831SAndroid Build Coastguard Worker                          (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
7480*7c568831SAndroid Build Coastguard Worker 		    valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7481*7c568831SAndroid Build Coastguard Worker 			    cur->nodesetval->nodeTab[i]->name));
7482*7c568831SAndroid Build Coastguard Worker 		} else {
7483*7c568831SAndroid Build Coastguard Worker 		    xmlChar *fullname;
7484*7c568831SAndroid Build Coastguard Worker 
7485*7c568831SAndroid Build Coastguard Worker 		    fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name,
7486*7c568831SAndroid Build Coastguard Worker 				     cur->nodesetval->nodeTab[i]->ns->prefix,
7487*7c568831SAndroid Build Coastguard Worker 				     NULL, 0);
7488*7c568831SAndroid Build Coastguard Worker 		    if (fullname == cur->nodesetval->nodeTab[i]->name)
7489*7c568831SAndroid Build Coastguard Worker 			fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
7490*7c568831SAndroid Build Coastguard Worker 		    if (fullname == NULL)
7491*7c568831SAndroid Build Coastguard Worker                         xmlXPathPErrMemory(ctxt);
7492*7c568831SAndroid Build Coastguard Worker 		    valuePush(ctxt, xmlXPathCacheWrapString(ctxt, fullname));
7493*7c568831SAndroid Build Coastguard Worker                 }
7494*7c568831SAndroid Build Coastguard Worker                 break;
7495*7c568831SAndroid Build Coastguard Worker             default:
7496*7c568831SAndroid Build Coastguard Worker 		valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
7497*7c568831SAndroid Build Coastguard Worker 		    cur->nodesetval->nodeTab[i]));
7498*7c568831SAndroid Build Coastguard Worker                 xmlXPathLocalNameFunction(ctxt, 1);
7499*7c568831SAndroid Build Coastguard Worker         }
7500*7c568831SAndroid Build Coastguard Worker     }
7501*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, cur);
7502*7c568831SAndroid Build Coastguard Worker }
7503*7c568831SAndroid Build Coastguard Worker 
7504*7c568831SAndroid Build Coastguard Worker 
7505*7c568831SAndroid Build Coastguard Worker /**
7506*7c568831SAndroid Build Coastguard Worker  * xmlXPathStringFunction:
7507*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7508*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7509*7c568831SAndroid Build Coastguard Worker  *
7510*7c568831SAndroid Build Coastguard Worker  * Implement the string() XPath function
7511*7c568831SAndroid Build Coastguard Worker  *    string string(object?)
7512*7c568831SAndroid Build Coastguard Worker  * The string function converts an object to a string as follows:
7513*7c568831SAndroid Build Coastguard Worker  *    - A node-set is converted to a string by returning the value of
7514*7c568831SAndroid Build Coastguard Worker  *      the node in the node-set that is first in document order.
7515*7c568831SAndroid Build Coastguard Worker  *      If the node-set is empty, an empty string is returned.
7516*7c568831SAndroid Build Coastguard Worker  *    - A number is converted to a string as follows
7517*7c568831SAndroid Build Coastguard Worker  *      + NaN is converted to the string NaN
7518*7c568831SAndroid Build Coastguard Worker  *      + positive zero is converted to the string 0
7519*7c568831SAndroid Build Coastguard Worker  *      + negative zero is converted to the string 0
7520*7c568831SAndroid Build Coastguard Worker  *      + positive infinity is converted to the string Infinity
7521*7c568831SAndroid Build Coastguard Worker  *      + negative infinity is converted to the string -Infinity
7522*7c568831SAndroid Build Coastguard Worker  *      + if the number is an integer, the number is represented in
7523*7c568831SAndroid Build Coastguard Worker  *        decimal form as a Number with no decimal point and no leading
7524*7c568831SAndroid Build Coastguard Worker  *        zeros, preceded by a minus sign (-) if the number is negative
7525*7c568831SAndroid Build Coastguard Worker  *      + otherwise, the number is represented in decimal form as a
7526*7c568831SAndroid Build Coastguard Worker  *        Number including a decimal point with at least one digit
7527*7c568831SAndroid Build Coastguard Worker  *        before the decimal point and at least one digit after the
7528*7c568831SAndroid Build Coastguard Worker  *        decimal point, preceded by a minus sign (-) if the number
7529*7c568831SAndroid Build Coastguard Worker  *        is negative; there must be no leading zeros before the decimal
7530*7c568831SAndroid Build Coastguard Worker  *        point apart possibly from the one required digit immediately
7531*7c568831SAndroid Build Coastguard Worker  *        before the decimal point; beyond the one required digit
7532*7c568831SAndroid Build Coastguard Worker  *        after the decimal point there must be as many, but only as
7533*7c568831SAndroid Build Coastguard Worker  *        many, more digits as are needed to uniquely distinguish the
7534*7c568831SAndroid Build Coastguard Worker  *        number from all other IEEE 754 numeric values.
7535*7c568831SAndroid Build Coastguard Worker  *    - The boolean false value is converted to the string false.
7536*7c568831SAndroid Build Coastguard Worker  *      The boolean true value is converted to the string true.
7537*7c568831SAndroid Build Coastguard Worker  *
7538*7c568831SAndroid Build Coastguard Worker  * If the argument is omitted, it defaults to a node-set with the
7539*7c568831SAndroid Build Coastguard Worker  * context node as its only member.
7540*7c568831SAndroid Build Coastguard Worker  */
7541*7c568831SAndroid Build Coastguard Worker void
xmlXPathStringFunction(xmlXPathParserContextPtr ctxt,int nargs)7542*7c568831SAndroid Build Coastguard Worker xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7543*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
7544*7c568831SAndroid Build Coastguard Worker     xmlChar *stringval;
7545*7c568831SAndroid Build Coastguard Worker 
7546*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return;
7547*7c568831SAndroid Build Coastguard Worker     if (nargs == 0) {
7548*7c568831SAndroid Build Coastguard Worker         stringval = xmlXPathCastNodeToString(ctxt->context->node);
7549*7c568831SAndroid Build Coastguard Worker         if (stringval == NULL)
7550*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
7551*7c568831SAndroid Build Coastguard Worker         valuePush(ctxt, xmlXPathCacheWrapString(ctxt, stringval));
7552*7c568831SAndroid Build Coastguard Worker 	return;
7553*7c568831SAndroid Build Coastguard Worker     }
7554*7c568831SAndroid Build Coastguard Worker 
7555*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
7556*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
7557*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
7558*7c568831SAndroid Build Coastguard Worker     if (cur->type != XPATH_STRING) {
7559*7c568831SAndroid Build Coastguard Worker         stringval = xmlXPathCastToString(cur);
7560*7c568831SAndroid Build Coastguard Worker         if (stringval == NULL)
7561*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
7562*7c568831SAndroid Build Coastguard Worker         xmlXPathReleaseObject(ctxt->context, cur);
7563*7c568831SAndroid Build Coastguard Worker         cur = xmlXPathCacheWrapString(ctxt, stringval);
7564*7c568831SAndroid Build Coastguard Worker     }
7565*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, cur);
7566*7c568831SAndroid Build Coastguard Worker }
7567*7c568831SAndroid Build Coastguard Worker 
7568*7c568831SAndroid Build Coastguard Worker /**
7569*7c568831SAndroid Build Coastguard Worker  * xmlXPathStringLengthFunction:
7570*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7571*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7572*7c568831SAndroid Build Coastguard Worker  *
7573*7c568831SAndroid Build Coastguard Worker  * Implement the string-length() XPath function
7574*7c568831SAndroid Build Coastguard Worker  *    number string-length(string?)
7575*7c568831SAndroid Build Coastguard Worker  * The string-length returns the number of characters in the string
7576*7c568831SAndroid Build Coastguard Worker  * (see [3.6 Strings]). If the argument is omitted, it defaults to
7577*7c568831SAndroid Build Coastguard Worker  * the context node converted to a string, in other words the value
7578*7c568831SAndroid Build Coastguard Worker  * of the context node.
7579*7c568831SAndroid Build Coastguard Worker  */
7580*7c568831SAndroid Build Coastguard Worker void
xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt,int nargs)7581*7c568831SAndroid Build Coastguard Worker xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7582*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
7583*7c568831SAndroid Build Coastguard Worker 
7584*7c568831SAndroid Build Coastguard Worker     if (nargs == 0) {
7585*7c568831SAndroid Build Coastguard Worker         if ((ctxt == NULL) || (ctxt->context == NULL))
7586*7c568831SAndroid Build Coastguard Worker 	    return;
7587*7c568831SAndroid Build Coastguard Worker 	if (ctxt->context->node == NULL) {
7588*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0));
7589*7c568831SAndroid Build Coastguard Worker 	} else {
7590*7c568831SAndroid Build Coastguard Worker 	    xmlChar *content;
7591*7c568831SAndroid Build Coastguard Worker 
7592*7c568831SAndroid Build Coastguard Worker 	    content = xmlXPathCastNodeToString(ctxt->context->node);
7593*7c568831SAndroid Build Coastguard Worker             if (content == NULL)
7594*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
7595*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7596*7c568831SAndroid Build Coastguard Worker 		xmlUTF8Strlen(content)));
7597*7c568831SAndroid Build Coastguard Worker 	    xmlFree(content);
7598*7c568831SAndroid Build Coastguard Worker 	}
7599*7c568831SAndroid Build Coastguard Worker 	return;
7600*7c568831SAndroid Build Coastguard Worker     }
7601*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
7602*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7603*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_STRING);
7604*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
7605*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7606*7c568831SAndroid Build Coastguard Worker 	xmlUTF8Strlen(cur->stringval)));
7607*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, cur);
7608*7c568831SAndroid Build Coastguard Worker }
7609*7c568831SAndroid Build Coastguard Worker 
7610*7c568831SAndroid Build Coastguard Worker /**
7611*7c568831SAndroid Build Coastguard Worker  * xmlXPathConcatFunction:
7612*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7613*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7614*7c568831SAndroid Build Coastguard Worker  *
7615*7c568831SAndroid Build Coastguard Worker  * Implement the concat() XPath function
7616*7c568831SAndroid Build Coastguard Worker  *    string concat(string, string, string*)
7617*7c568831SAndroid Build Coastguard Worker  * The concat function returns the concatenation of its arguments.
7618*7c568831SAndroid Build Coastguard Worker  */
7619*7c568831SAndroid Build Coastguard Worker void
xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt,int nargs)7620*7c568831SAndroid Build Coastguard Worker xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7621*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur, newobj;
7622*7c568831SAndroid Build Coastguard Worker     xmlChar *tmp;
7623*7c568831SAndroid Build Coastguard Worker 
7624*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return;
7625*7c568831SAndroid Build Coastguard Worker     if (nargs < 2) {
7626*7c568831SAndroid Build Coastguard Worker 	CHECK_ARITY(2);
7627*7c568831SAndroid Build Coastguard Worker     }
7628*7c568831SAndroid Build Coastguard Worker 
7629*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7630*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
7631*7c568831SAndroid Build Coastguard Worker     if ((cur == NULL) || (cur->type != XPATH_STRING)) {
7632*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, cur);
7633*7c568831SAndroid Build Coastguard Worker 	return;
7634*7c568831SAndroid Build Coastguard Worker     }
7635*7c568831SAndroid Build Coastguard Worker     nargs--;
7636*7c568831SAndroid Build Coastguard Worker 
7637*7c568831SAndroid Build Coastguard Worker     while (nargs > 0) {
7638*7c568831SAndroid Build Coastguard Worker 	CAST_TO_STRING;
7639*7c568831SAndroid Build Coastguard Worker 	newobj = valuePop(ctxt);
7640*7c568831SAndroid Build Coastguard Worker 	if ((newobj == NULL) || (newobj->type != XPATH_STRING)) {
7641*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, newobj);
7642*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, cur);
7643*7c568831SAndroid Build Coastguard Worker 	    XP_ERROR(XPATH_INVALID_TYPE);
7644*7c568831SAndroid Build Coastguard Worker 	}
7645*7c568831SAndroid Build Coastguard Worker 	tmp = xmlStrcat(newobj->stringval, cur->stringval);
7646*7c568831SAndroid Build Coastguard Worker         if (tmp == NULL)
7647*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
7648*7c568831SAndroid Build Coastguard Worker 	newobj->stringval = cur->stringval;
7649*7c568831SAndroid Build Coastguard Worker 	cur->stringval = tmp;
7650*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, newobj);
7651*7c568831SAndroid Build Coastguard Worker 	nargs--;
7652*7c568831SAndroid Build Coastguard Worker     }
7653*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, cur);
7654*7c568831SAndroid Build Coastguard Worker }
7655*7c568831SAndroid Build Coastguard Worker 
7656*7c568831SAndroid Build Coastguard Worker /**
7657*7c568831SAndroid Build Coastguard Worker  * xmlXPathContainsFunction:
7658*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7659*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7660*7c568831SAndroid Build Coastguard Worker  *
7661*7c568831SAndroid Build Coastguard Worker  * Implement the contains() XPath function
7662*7c568831SAndroid Build Coastguard Worker  *    boolean contains(string, string)
7663*7c568831SAndroid Build Coastguard Worker  * The contains function returns true if the first argument string
7664*7c568831SAndroid Build Coastguard Worker  * contains the second argument string, and otherwise returns false.
7665*7c568831SAndroid Build Coastguard Worker  */
7666*7c568831SAndroid Build Coastguard Worker void
xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt,int nargs)7667*7c568831SAndroid Build Coastguard Worker xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7668*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr hay, needle;
7669*7c568831SAndroid Build Coastguard Worker 
7670*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(2);
7671*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7672*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_STRING);
7673*7c568831SAndroid Build Coastguard Worker     needle = valuePop(ctxt);
7674*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7675*7c568831SAndroid Build Coastguard Worker     hay = valuePop(ctxt);
7676*7c568831SAndroid Build Coastguard Worker 
7677*7c568831SAndroid Build Coastguard Worker     if ((hay == NULL) || (hay->type != XPATH_STRING)) {
7678*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, hay);
7679*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, needle);
7680*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_TYPE);
7681*7c568831SAndroid Build Coastguard Worker     }
7682*7c568831SAndroid Build Coastguard Worker     if (xmlStrstr(hay->stringval, needle->stringval))
7683*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
7684*7c568831SAndroid Build Coastguard Worker     else
7685*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
7686*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, hay);
7687*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, needle);
7688*7c568831SAndroid Build Coastguard Worker }
7689*7c568831SAndroid Build Coastguard Worker 
7690*7c568831SAndroid Build Coastguard Worker /**
7691*7c568831SAndroid Build Coastguard Worker  * xmlXPathStartsWithFunction:
7692*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7693*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7694*7c568831SAndroid Build Coastguard Worker  *
7695*7c568831SAndroid Build Coastguard Worker  * Implement the starts-with() XPath function
7696*7c568831SAndroid Build Coastguard Worker  *    boolean starts-with(string, string)
7697*7c568831SAndroid Build Coastguard Worker  * The starts-with function returns true if the first argument string
7698*7c568831SAndroid Build Coastguard Worker  * starts with the second argument string, and otherwise returns false.
7699*7c568831SAndroid Build Coastguard Worker  */
7700*7c568831SAndroid Build Coastguard Worker void
xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt,int nargs)7701*7c568831SAndroid Build Coastguard Worker xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7702*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr hay, needle;
7703*7c568831SAndroid Build Coastguard Worker     int n;
7704*7c568831SAndroid Build Coastguard Worker 
7705*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(2);
7706*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7707*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_STRING);
7708*7c568831SAndroid Build Coastguard Worker     needle = valuePop(ctxt);
7709*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7710*7c568831SAndroid Build Coastguard Worker     hay = valuePop(ctxt);
7711*7c568831SAndroid Build Coastguard Worker 
7712*7c568831SAndroid Build Coastguard Worker     if ((hay == NULL) || (hay->type != XPATH_STRING)) {
7713*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, hay);
7714*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, needle);
7715*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_TYPE);
7716*7c568831SAndroid Build Coastguard Worker     }
7717*7c568831SAndroid Build Coastguard Worker     n = xmlStrlen(needle->stringval);
7718*7c568831SAndroid Build Coastguard Worker     if (xmlStrncmp(hay->stringval, needle->stringval, n))
7719*7c568831SAndroid Build Coastguard Worker         valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
7720*7c568831SAndroid Build Coastguard Worker     else
7721*7c568831SAndroid Build Coastguard Worker         valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
7722*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, hay);
7723*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, needle);
7724*7c568831SAndroid Build Coastguard Worker }
7725*7c568831SAndroid Build Coastguard Worker 
7726*7c568831SAndroid Build Coastguard Worker /**
7727*7c568831SAndroid Build Coastguard Worker  * xmlXPathSubstringFunction:
7728*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7729*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7730*7c568831SAndroid Build Coastguard Worker  *
7731*7c568831SAndroid Build Coastguard Worker  * Implement the substring() XPath function
7732*7c568831SAndroid Build Coastguard Worker  *    string substring(string, number, number?)
7733*7c568831SAndroid Build Coastguard Worker  * The substring function returns the substring of the first argument
7734*7c568831SAndroid Build Coastguard Worker  * starting at the position specified in the second argument with
7735*7c568831SAndroid Build Coastguard Worker  * length specified in the third argument. For example,
7736*7c568831SAndroid Build Coastguard Worker  * substring("12345",2,3) returns "234". If the third argument is not
7737*7c568831SAndroid Build Coastguard Worker  * specified, it returns the substring starting at the position specified
7738*7c568831SAndroid Build Coastguard Worker  * in the second argument and continuing to the end of the string. For
7739*7c568831SAndroid Build Coastguard Worker  * example, substring("12345",2) returns "2345".  More precisely, each
7740*7c568831SAndroid Build Coastguard Worker  * character in the string (see [3.6 Strings]) is considered to have a
7741*7c568831SAndroid Build Coastguard Worker  * numeric position: the position of the first character is 1, the position
7742*7c568831SAndroid Build Coastguard Worker  * of the second character is 2 and so on. The returned substring contains
7743*7c568831SAndroid Build Coastguard Worker  * those characters for which the position of the character is greater than
7744*7c568831SAndroid Build Coastguard Worker  * or equal to the second argument and, if the third argument is specified,
7745*7c568831SAndroid Build Coastguard Worker  * less than the sum of the second and third arguments; the comparisons
7746*7c568831SAndroid Build Coastguard Worker  * and addition used for the above follow the standard IEEE 754 rules. Thus:
7747*7c568831SAndroid Build Coastguard Worker  *  - substring("12345", 1.5, 2.6) returns "234"
7748*7c568831SAndroid Build Coastguard Worker  *  - substring("12345", 0, 3) returns "12"
7749*7c568831SAndroid Build Coastguard Worker  *  - substring("12345", 0 div 0, 3) returns ""
7750*7c568831SAndroid Build Coastguard Worker  *  - substring("12345", 1, 0 div 0) returns ""
7751*7c568831SAndroid Build Coastguard Worker  *  - substring("12345", -42, 1 div 0) returns "12345"
7752*7c568831SAndroid Build Coastguard Worker  *  - substring("12345", -1 div 0, 1 div 0) returns ""
7753*7c568831SAndroid Build Coastguard Worker  */
7754*7c568831SAndroid Build Coastguard Worker void
xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt,int nargs)7755*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7756*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr str, start, len;
7757*7c568831SAndroid Build Coastguard Worker     double le=0, in;
7758*7c568831SAndroid Build Coastguard Worker     int i = 1, j = INT_MAX;
7759*7c568831SAndroid Build Coastguard Worker 
7760*7c568831SAndroid Build Coastguard Worker     if (nargs < 2) {
7761*7c568831SAndroid Build Coastguard Worker 	CHECK_ARITY(2);
7762*7c568831SAndroid Build Coastguard Worker     }
7763*7c568831SAndroid Build Coastguard Worker     if (nargs > 3) {
7764*7c568831SAndroid Build Coastguard Worker 	CHECK_ARITY(3);
7765*7c568831SAndroid Build Coastguard Worker     }
7766*7c568831SAndroid Build Coastguard Worker     /*
7767*7c568831SAndroid Build Coastguard Worker      * take care of possible last (position) argument
7768*7c568831SAndroid Build Coastguard Worker     */
7769*7c568831SAndroid Build Coastguard Worker     if (nargs == 3) {
7770*7c568831SAndroid Build Coastguard Worker 	CAST_TO_NUMBER;
7771*7c568831SAndroid Build Coastguard Worker 	CHECK_TYPE(XPATH_NUMBER);
7772*7c568831SAndroid Build Coastguard Worker 	len = valuePop(ctxt);
7773*7c568831SAndroid Build Coastguard Worker 	le = len->floatval;
7774*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, len);
7775*7c568831SAndroid Build Coastguard Worker     }
7776*7c568831SAndroid Build Coastguard Worker 
7777*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
7778*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
7779*7c568831SAndroid Build Coastguard Worker     start = valuePop(ctxt);
7780*7c568831SAndroid Build Coastguard Worker     in = start->floatval;
7781*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, start);
7782*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7783*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_STRING);
7784*7c568831SAndroid Build Coastguard Worker     str = valuePop(ctxt);
7785*7c568831SAndroid Build Coastguard Worker 
7786*7c568831SAndroid Build Coastguard Worker     if (!(in < INT_MAX)) { /* Logical NOT to handle NaNs */
7787*7c568831SAndroid Build Coastguard Worker         i = INT_MAX;
7788*7c568831SAndroid Build Coastguard Worker     } else if (in >= 1.0) {
7789*7c568831SAndroid Build Coastguard Worker         i = (int)in;
7790*7c568831SAndroid Build Coastguard Worker         if (in - floor(in) >= 0.5)
7791*7c568831SAndroid Build Coastguard Worker             i += 1;
7792*7c568831SAndroid Build Coastguard Worker     }
7793*7c568831SAndroid Build Coastguard Worker 
7794*7c568831SAndroid Build Coastguard Worker     if (nargs == 3) {
7795*7c568831SAndroid Build Coastguard Worker         double rin, rle, end;
7796*7c568831SAndroid Build Coastguard Worker 
7797*7c568831SAndroid Build Coastguard Worker         rin = floor(in);
7798*7c568831SAndroid Build Coastguard Worker         if (in - rin >= 0.5)
7799*7c568831SAndroid Build Coastguard Worker             rin += 1.0;
7800*7c568831SAndroid Build Coastguard Worker 
7801*7c568831SAndroid Build Coastguard Worker         rle = floor(le);
7802*7c568831SAndroid Build Coastguard Worker         if (le - rle >= 0.5)
7803*7c568831SAndroid Build Coastguard Worker             rle += 1.0;
7804*7c568831SAndroid Build Coastguard Worker 
7805*7c568831SAndroid Build Coastguard Worker         end = rin + rle;
7806*7c568831SAndroid Build Coastguard Worker         if (!(end >= 1.0)) { /* Logical NOT to handle NaNs */
7807*7c568831SAndroid Build Coastguard Worker             j = 1;
7808*7c568831SAndroid Build Coastguard Worker         } else if (end < INT_MAX) {
7809*7c568831SAndroid Build Coastguard Worker             j = (int)end;
7810*7c568831SAndroid Build Coastguard Worker         }
7811*7c568831SAndroid Build Coastguard Worker     }
7812*7c568831SAndroid Build Coastguard Worker 
7813*7c568831SAndroid Build Coastguard Worker     i -= 1;
7814*7c568831SAndroid Build Coastguard Worker     j -= 1;
7815*7c568831SAndroid Build Coastguard Worker 
7816*7c568831SAndroid Build Coastguard Worker     if ((i < j) && (i < xmlUTF8Strlen(str->stringval))) {
7817*7c568831SAndroid Build Coastguard Worker         xmlChar *ret = xmlUTF8Strsub(str->stringval, i, j - i);
7818*7c568831SAndroid Build Coastguard Worker         if (ret == NULL)
7819*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
7820*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewString(ctxt, ret));
7821*7c568831SAndroid Build Coastguard Worker 	xmlFree(ret);
7822*7c568831SAndroid Build Coastguard Worker     } else {
7823*7c568831SAndroid Build Coastguard Worker 	valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7824*7c568831SAndroid Build Coastguard Worker     }
7825*7c568831SAndroid Build Coastguard Worker 
7826*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, str);
7827*7c568831SAndroid Build Coastguard Worker }
7828*7c568831SAndroid Build Coastguard Worker 
7829*7c568831SAndroid Build Coastguard Worker /**
7830*7c568831SAndroid Build Coastguard Worker  * xmlXPathSubstringBeforeFunction:
7831*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7832*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7833*7c568831SAndroid Build Coastguard Worker  *
7834*7c568831SAndroid Build Coastguard Worker  * Implement the substring-before() XPath function
7835*7c568831SAndroid Build Coastguard Worker  *    string substring-before(string, string)
7836*7c568831SAndroid Build Coastguard Worker  * The substring-before function returns the substring of the first
7837*7c568831SAndroid Build Coastguard Worker  * argument string that precedes the first occurrence of the second
7838*7c568831SAndroid Build Coastguard Worker  * argument string in the first argument string, or the empty string
7839*7c568831SAndroid Build Coastguard Worker  * if the first argument string does not contain the second argument
7840*7c568831SAndroid Build Coastguard Worker  * string. For example, substring-before("1999/04/01","/") returns 1999.
7841*7c568831SAndroid Build Coastguard Worker  */
7842*7c568831SAndroid Build Coastguard Worker void
xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt,int nargs)7843*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7844*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr str = NULL;
7845*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr find = NULL;
7846*7c568831SAndroid Build Coastguard Worker     const xmlChar *point;
7847*7c568831SAndroid Build Coastguard Worker     xmlChar *result;
7848*7c568831SAndroid Build Coastguard Worker 
7849*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(2);
7850*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7851*7c568831SAndroid Build Coastguard Worker     find = valuePop(ctxt);
7852*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7853*7c568831SAndroid Build Coastguard Worker     str = valuePop(ctxt);
7854*7c568831SAndroid Build Coastguard Worker     if (ctxt->error != 0)
7855*7c568831SAndroid Build Coastguard Worker         goto error;
7856*7c568831SAndroid Build Coastguard Worker 
7857*7c568831SAndroid Build Coastguard Worker     point = xmlStrstr(str->stringval, find->stringval);
7858*7c568831SAndroid Build Coastguard Worker     if (point == NULL) {
7859*7c568831SAndroid Build Coastguard Worker         result = xmlStrdup(BAD_CAST "");
7860*7c568831SAndroid Build Coastguard Worker     } else {
7861*7c568831SAndroid Build Coastguard Worker         result = xmlStrndup(str->stringval, point - str->stringval);
7862*7c568831SAndroid Build Coastguard Worker     }
7863*7c568831SAndroid Build Coastguard Worker     if (result == NULL) {
7864*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
7865*7c568831SAndroid Build Coastguard Worker         goto error;
7866*7c568831SAndroid Build Coastguard Worker     }
7867*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
7868*7c568831SAndroid Build Coastguard Worker 
7869*7c568831SAndroid Build Coastguard Worker error:
7870*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, str);
7871*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, find);
7872*7c568831SAndroid Build Coastguard Worker }
7873*7c568831SAndroid Build Coastguard Worker 
7874*7c568831SAndroid Build Coastguard Worker /**
7875*7c568831SAndroid Build Coastguard Worker  * xmlXPathSubstringAfterFunction:
7876*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7877*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7878*7c568831SAndroid Build Coastguard Worker  *
7879*7c568831SAndroid Build Coastguard Worker  * Implement the substring-after() XPath function
7880*7c568831SAndroid Build Coastguard Worker  *    string substring-after(string, string)
7881*7c568831SAndroid Build Coastguard Worker  * The substring-after function returns the substring of the first
7882*7c568831SAndroid Build Coastguard Worker  * argument string that follows the first occurrence of the second
7883*7c568831SAndroid Build Coastguard Worker  * argument string in the first argument string, or the empty string
7884*7c568831SAndroid Build Coastguard Worker  * if the first argument string does not contain the second argument
7885*7c568831SAndroid Build Coastguard Worker  * string. For example, substring-after("1999/04/01","/") returns 04/01,
7886*7c568831SAndroid Build Coastguard Worker  * and substring-after("1999/04/01","19") returns 99/04/01.
7887*7c568831SAndroid Build Coastguard Worker  */
7888*7c568831SAndroid Build Coastguard Worker void
xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt,int nargs)7889*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7890*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr str = NULL;
7891*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr find = NULL;
7892*7c568831SAndroid Build Coastguard Worker     const xmlChar *point;
7893*7c568831SAndroid Build Coastguard Worker     xmlChar *result;
7894*7c568831SAndroid Build Coastguard Worker 
7895*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(2);
7896*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7897*7c568831SAndroid Build Coastguard Worker     find = valuePop(ctxt);
7898*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7899*7c568831SAndroid Build Coastguard Worker     str = valuePop(ctxt);
7900*7c568831SAndroid Build Coastguard Worker     if (ctxt->error != 0)
7901*7c568831SAndroid Build Coastguard Worker         goto error;
7902*7c568831SAndroid Build Coastguard Worker 
7903*7c568831SAndroid Build Coastguard Worker     point = xmlStrstr(str->stringval, find->stringval);
7904*7c568831SAndroid Build Coastguard Worker     if (point == NULL) {
7905*7c568831SAndroid Build Coastguard Worker         result = xmlStrdup(BAD_CAST "");
7906*7c568831SAndroid Build Coastguard Worker     } else {
7907*7c568831SAndroid Build Coastguard Worker         result = xmlStrdup(point + xmlStrlen(find->stringval));
7908*7c568831SAndroid Build Coastguard Worker     }
7909*7c568831SAndroid Build Coastguard Worker     if (result == NULL) {
7910*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
7911*7c568831SAndroid Build Coastguard Worker         goto error;
7912*7c568831SAndroid Build Coastguard Worker     }
7913*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
7914*7c568831SAndroid Build Coastguard Worker 
7915*7c568831SAndroid Build Coastguard Worker error:
7916*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, str);
7917*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, find);
7918*7c568831SAndroid Build Coastguard Worker }
7919*7c568831SAndroid Build Coastguard Worker 
7920*7c568831SAndroid Build Coastguard Worker /**
7921*7c568831SAndroid Build Coastguard Worker  * xmlXPathNormalizeFunction:
7922*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7923*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7924*7c568831SAndroid Build Coastguard Worker  *
7925*7c568831SAndroid Build Coastguard Worker  * Implement the normalize-space() XPath function
7926*7c568831SAndroid Build Coastguard Worker  *    string normalize-space(string?)
7927*7c568831SAndroid Build Coastguard Worker  * The normalize-space function returns the argument string with white
7928*7c568831SAndroid Build Coastguard Worker  * space normalized by stripping leading and trailing whitespace
7929*7c568831SAndroid Build Coastguard Worker  * and replacing sequences of whitespace characters by a single
7930*7c568831SAndroid Build Coastguard Worker  * space. Whitespace characters are the same allowed by the S production
7931*7c568831SAndroid Build Coastguard Worker  * in XML. If the argument is omitted, it defaults to the context
7932*7c568831SAndroid Build Coastguard Worker  * node converted to a string, in other words the value of the context node.
7933*7c568831SAndroid Build Coastguard Worker  */
7934*7c568831SAndroid Build Coastguard Worker void
xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt,int nargs)7935*7c568831SAndroid Build Coastguard Worker xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7936*7c568831SAndroid Build Coastguard Worker     xmlChar *source, *target;
7937*7c568831SAndroid Build Coastguard Worker     int blank;
7938*7c568831SAndroid Build Coastguard Worker 
7939*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return;
7940*7c568831SAndroid Build Coastguard Worker     if (nargs == 0) {
7941*7c568831SAndroid Build Coastguard Worker         /* Use current context node */
7942*7c568831SAndroid Build Coastguard Worker         source = xmlXPathCastNodeToString(ctxt->context->node);
7943*7c568831SAndroid Build Coastguard Worker         if (source == NULL)
7944*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
7945*7c568831SAndroid Build Coastguard Worker         valuePush(ctxt, xmlXPathCacheWrapString(ctxt, source));
7946*7c568831SAndroid Build Coastguard Worker         nargs = 1;
7947*7c568831SAndroid Build Coastguard Worker     }
7948*7c568831SAndroid Build Coastguard Worker 
7949*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
7950*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
7951*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_STRING);
7952*7c568831SAndroid Build Coastguard Worker     source = ctxt->value->stringval;
7953*7c568831SAndroid Build Coastguard Worker     if (source == NULL)
7954*7c568831SAndroid Build Coastguard Worker         return;
7955*7c568831SAndroid Build Coastguard Worker     target = source;
7956*7c568831SAndroid Build Coastguard Worker 
7957*7c568831SAndroid Build Coastguard Worker     /* Skip leading whitespaces */
7958*7c568831SAndroid Build Coastguard Worker     while (IS_BLANK_CH(*source))
7959*7c568831SAndroid Build Coastguard Worker         source++;
7960*7c568831SAndroid Build Coastguard Worker 
7961*7c568831SAndroid Build Coastguard Worker     /* Collapse intermediate whitespaces, and skip trailing whitespaces */
7962*7c568831SAndroid Build Coastguard Worker     blank = 0;
7963*7c568831SAndroid Build Coastguard Worker     while (*source) {
7964*7c568831SAndroid Build Coastguard Worker         if (IS_BLANK_CH(*source)) {
7965*7c568831SAndroid Build Coastguard Worker 	    blank = 1;
7966*7c568831SAndroid Build Coastguard Worker         } else {
7967*7c568831SAndroid Build Coastguard Worker             if (blank) {
7968*7c568831SAndroid Build Coastguard Worker                 *target++ = 0x20;
7969*7c568831SAndroid Build Coastguard Worker                 blank = 0;
7970*7c568831SAndroid Build Coastguard Worker             }
7971*7c568831SAndroid Build Coastguard Worker             *target++ = *source;
7972*7c568831SAndroid Build Coastguard Worker         }
7973*7c568831SAndroid Build Coastguard Worker         source++;
7974*7c568831SAndroid Build Coastguard Worker     }
7975*7c568831SAndroid Build Coastguard Worker     *target = 0;
7976*7c568831SAndroid Build Coastguard Worker }
7977*7c568831SAndroid Build Coastguard Worker 
7978*7c568831SAndroid Build Coastguard Worker /**
7979*7c568831SAndroid Build Coastguard Worker  * xmlXPathTranslateFunction:
7980*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
7981*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
7982*7c568831SAndroid Build Coastguard Worker  *
7983*7c568831SAndroid Build Coastguard Worker  * Implement the translate() XPath function
7984*7c568831SAndroid Build Coastguard Worker  *    string translate(string, string, string)
7985*7c568831SAndroid Build Coastguard Worker  * The translate function returns the first argument string with
7986*7c568831SAndroid Build Coastguard Worker  * occurrences of characters in the second argument string replaced
7987*7c568831SAndroid Build Coastguard Worker  * by the character at the corresponding position in the third argument
7988*7c568831SAndroid Build Coastguard Worker  * string. For example, translate("bar","abc","ABC") returns the string
7989*7c568831SAndroid Build Coastguard Worker  * BAr. If there is a character in the second argument string with no
7990*7c568831SAndroid Build Coastguard Worker  * character at a corresponding position in the third argument string
7991*7c568831SAndroid Build Coastguard Worker  * (because the second argument string is longer than the third argument
7992*7c568831SAndroid Build Coastguard Worker  * string), then occurrences of that character in the first argument
7993*7c568831SAndroid Build Coastguard Worker  * string are removed. For example, translate("--aaa--","abc-","ABC")
7994*7c568831SAndroid Build Coastguard Worker  * returns "AAA". If a character occurs more than once in second
7995*7c568831SAndroid Build Coastguard Worker  * argument string, then the first occurrence determines the replacement
7996*7c568831SAndroid Build Coastguard Worker  * character. If the third argument string is longer than the second
7997*7c568831SAndroid Build Coastguard Worker  * argument string, then excess characters are ignored.
7998*7c568831SAndroid Build Coastguard Worker  */
7999*7c568831SAndroid Build Coastguard Worker void
xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt,int nargs)8000*7c568831SAndroid Build Coastguard Worker xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8001*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr str = NULL;
8002*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr from = NULL;
8003*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr to = NULL;
8004*7c568831SAndroid Build Coastguard Worker     xmlBufPtr target;
8005*7c568831SAndroid Build Coastguard Worker     int offset, max;
8006*7c568831SAndroid Build Coastguard Worker     int ch;
8007*7c568831SAndroid Build Coastguard Worker     const xmlChar *point;
8008*7c568831SAndroid Build Coastguard Worker     xmlChar *cptr, *content;
8009*7c568831SAndroid Build Coastguard Worker 
8010*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(3);
8011*7c568831SAndroid Build Coastguard Worker 
8012*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
8013*7c568831SAndroid Build Coastguard Worker     to = valuePop(ctxt);
8014*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
8015*7c568831SAndroid Build Coastguard Worker     from = valuePop(ctxt);
8016*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
8017*7c568831SAndroid Build Coastguard Worker     str = valuePop(ctxt);
8018*7c568831SAndroid Build Coastguard Worker     if (ctxt->error != 0)
8019*7c568831SAndroid Build Coastguard Worker         goto error;
8020*7c568831SAndroid Build Coastguard Worker 
8021*7c568831SAndroid Build Coastguard Worker     /*
8022*7c568831SAndroid Build Coastguard Worker      * Account for quadratic runtime
8023*7c568831SAndroid Build Coastguard Worker      */
8024*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->opLimit != 0) {
8025*7c568831SAndroid Build Coastguard Worker         unsigned long f1 = xmlStrlen(from->stringval);
8026*7c568831SAndroid Build Coastguard Worker         unsigned long f2 = xmlStrlen(str->stringval);
8027*7c568831SAndroid Build Coastguard Worker 
8028*7c568831SAndroid Build Coastguard Worker         if ((f1 > 0) && (f2 > 0)) {
8029*7c568831SAndroid Build Coastguard Worker             unsigned long p;
8030*7c568831SAndroid Build Coastguard Worker 
8031*7c568831SAndroid Build Coastguard Worker             f1 = f1 / 10 + 1;
8032*7c568831SAndroid Build Coastguard Worker             f2 = f2 / 10 + 1;
8033*7c568831SAndroid Build Coastguard Worker             p = f1 > ULONG_MAX / f2 ? ULONG_MAX : f1 * f2;
8034*7c568831SAndroid Build Coastguard Worker             if (xmlXPathCheckOpLimit(ctxt, p) < 0)
8035*7c568831SAndroid Build Coastguard Worker                 goto error;
8036*7c568831SAndroid Build Coastguard Worker         }
8037*7c568831SAndroid Build Coastguard Worker     }
8038*7c568831SAndroid Build Coastguard Worker 
8039*7c568831SAndroid Build Coastguard Worker     target = xmlBufCreate(50);
8040*7c568831SAndroid Build Coastguard Worker     if (target == NULL) {
8041*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
8042*7c568831SAndroid Build Coastguard Worker         goto error;
8043*7c568831SAndroid Build Coastguard Worker     }
8044*7c568831SAndroid Build Coastguard Worker 
8045*7c568831SAndroid Build Coastguard Worker     max = xmlUTF8Strlen(to->stringval);
8046*7c568831SAndroid Build Coastguard Worker     for (cptr = str->stringval; (ch=*cptr); ) {
8047*7c568831SAndroid Build Coastguard Worker         offset = xmlUTF8Strloc(from->stringval, cptr);
8048*7c568831SAndroid Build Coastguard Worker         if (offset >= 0) {
8049*7c568831SAndroid Build Coastguard Worker             if (offset < max) {
8050*7c568831SAndroid Build Coastguard Worker                 point = xmlUTF8Strpos(to->stringval, offset);
8051*7c568831SAndroid Build Coastguard Worker                 if (point)
8052*7c568831SAndroid Build Coastguard Worker                     xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
8053*7c568831SAndroid Build Coastguard Worker             }
8054*7c568831SAndroid Build Coastguard Worker         } else
8055*7c568831SAndroid Build Coastguard Worker             xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
8056*7c568831SAndroid Build Coastguard Worker 
8057*7c568831SAndroid Build Coastguard Worker         /* Step to next character in input */
8058*7c568831SAndroid Build Coastguard Worker         cptr++;
8059*7c568831SAndroid Build Coastguard Worker         if ( ch & 0x80 ) {
8060*7c568831SAndroid Build Coastguard Worker             /* if not simple ascii, verify proper format */
8061*7c568831SAndroid Build Coastguard Worker             if ( (ch & 0xc0) != 0xc0 ) {
8062*7c568831SAndroid Build Coastguard Worker                 xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR);
8063*7c568831SAndroid Build Coastguard Worker                 break;
8064*7c568831SAndroid Build Coastguard Worker             }
8065*7c568831SAndroid Build Coastguard Worker             /* then skip over remaining bytes for this char */
8066*7c568831SAndroid Build Coastguard Worker             while ( (ch <<= 1) & 0x80 )
8067*7c568831SAndroid Build Coastguard Worker                 if ( (*cptr++ & 0xc0) != 0x80 ) {
8068*7c568831SAndroid Build Coastguard Worker                     xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR);
8069*7c568831SAndroid Build Coastguard Worker                     break;
8070*7c568831SAndroid Build Coastguard Worker                 }
8071*7c568831SAndroid Build Coastguard Worker             if (ch & 0x80) /* must have had error encountered */
8072*7c568831SAndroid Build Coastguard Worker                 break;
8073*7c568831SAndroid Build Coastguard Worker         }
8074*7c568831SAndroid Build Coastguard Worker     }
8075*7c568831SAndroid Build Coastguard Worker 
8076*7c568831SAndroid Build Coastguard Worker     content = xmlBufDetach(target);
8077*7c568831SAndroid Build Coastguard Worker     if (content == NULL)
8078*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
8079*7c568831SAndroid Build Coastguard Worker     else
8080*7c568831SAndroid Build Coastguard Worker         valuePush(ctxt, xmlXPathCacheWrapString(ctxt, content));
8081*7c568831SAndroid Build Coastguard Worker     xmlBufFree(target);
8082*7c568831SAndroid Build Coastguard Worker error:
8083*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, str);
8084*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, from);
8085*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, to);
8086*7c568831SAndroid Build Coastguard Worker }
8087*7c568831SAndroid Build Coastguard Worker 
8088*7c568831SAndroid Build Coastguard Worker /**
8089*7c568831SAndroid Build Coastguard Worker  * xmlXPathBooleanFunction:
8090*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8091*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8092*7c568831SAndroid Build Coastguard Worker  *
8093*7c568831SAndroid Build Coastguard Worker  * Implement the boolean() XPath function
8094*7c568831SAndroid Build Coastguard Worker  *    boolean boolean(object)
8095*7c568831SAndroid Build Coastguard Worker  * The boolean function converts its argument to a boolean as follows:
8096*7c568831SAndroid Build Coastguard Worker  *    - a number is true if and only if it is neither positive or
8097*7c568831SAndroid Build Coastguard Worker  *      negative zero nor NaN
8098*7c568831SAndroid Build Coastguard Worker  *    - a node-set is true if and only if it is non-empty
8099*7c568831SAndroid Build Coastguard Worker  *    - a string is true if and only if its length is non-zero
8100*7c568831SAndroid Build Coastguard Worker  */
8101*7c568831SAndroid Build Coastguard Worker void
xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt,int nargs)8102*7c568831SAndroid Build Coastguard Worker xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8103*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
8104*7c568831SAndroid Build Coastguard Worker 
8105*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
8106*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
8107*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
8108*7c568831SAndroid Build Coastguard Worker     if (cur->type != XPATH_BOOLEAN) {
8109*7c568831SAndroid Build Coastguard Worker         int boolval = xmlXPathCastToBoolean(cur);
8110*7c568831SAndroid Build Coastguard Worker 
8111*7c568831SAndroid Build Coastguard Worker         xmlXPathReleaseObject(ctxt->context, cur);
8112*7c568831SAndroid Build Coastguard Worker         cur = xmlXPathCacheNewBoolean(ctxt, boolval);
8113*7c568831SAndroid Build Coastguard Worker     }
8114*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, cur);
8115*7c568831SAndroid Build Coastguard Worker }
8116*7c568831SAndroid Build Coastguard Worker 
8117*7c568831SAndroid Build Coastguard Worker /**
8118*7c568831SAndroid Build Coastguard Worker  * xmlXPathNotFunction:
8119*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8120*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8121*7c568831SAndroid Build Coastguard Worker  *
8122*7c568831SAndroid Build Coastguard Worker  * Implement the not() XPath function
8123*7c568831SAndroid Build Coastguard Worker  *    boolean not(boolean)
8124*7c568831SAndroid Build Coastguard Worker  * The not function returns true if its argument is false,
8125*7c568831SAndroid Build Coastguard Worker  * and false otherwise.
8126*7c568831SAndroid Build Coastguard Worker  */
8127*7c568831SAndroid Build Coastguard Worker void
xmlXPathNotFunction(xmlXPathParserContextPtr ctxt,int nargs)8128*7c568831SAndroid Build Coastguard Worker xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8129*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
8130*7c568831SAndroid Build Coastguard Worker     CAST_TO_BOOLEAN;
8131*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_BOOLEAN);
8132*7c568831SAndroid Build Coastguard Worker     ctxt->value->boolval = ! ctxt->value->boolval;
8133*7c568831SAndroid Build Coastguard Worker }
8134*7c568831SAndroid Build Coastguard Worker 
8135*7c568831SAndroid Build Coastguard Worker /**
8136*7c568831SAndroid Build Coastguard Worker  * xmlXPathTrueFunction:
8137*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8138*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8139*7c568831SAndroid Build Coastguard Worker  *
8140*7c568831SAndroid Build Coastguard Worker  * Implement the true() XPath function
8141*7c568831SAndroid Build Coastguard Worker  *    boolean true()
8142*7c568831SAndroid Build Coastguard Worker  */
8143*7c568831SAndroid Build Coastguard Worker void
xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt,int nargs)8144*7c568831SAndroid Build Coastguard Worker xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8145*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(0);
8146*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
8147*7c568831SAndroid Build Coastguard Worker }
8148*7c568831SAndroid Build Coastguard Worker 
8149*7c568831SAndroid Build Coastguard Worker /**
8150*7c568831SAndroid Build Coastguard Worker  * xmlXPathFalseFunction:
8151*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8152*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8153*7c568831SAndroid Build Coastguard Worker  *
8154*7c568831SAndroid Build Coastguard Worker  * Implement the false() XPath function
8155*7c568831SAndroid Build Coastguard Worker  *    boolean false()
8156*7c568831SAndroid Build Coastguard Worker  */
8157*7c568831SAndroid Build Coastguard Worker void
xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt,int nargs)8158*7c568831SAndroid Build Coastguard Worker xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8159*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(0);
8160*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
8161*7c568831SAndroid Build Coastguard Worker }
8162*7c568831SAndroid Build Coastguard Worker 
8163*7c568831SAndroid Build Coastguard Worker /**
8164*7c568831SAndroid Build Coastguard Worker  * xmlXPathLangFunction:
8165*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8166*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8167*7c568831SAndroid Build Coastguard Worker  *
8168*7c568831SAndroid Build Coastguard Worker  * Implement the lang() XPath function
8169*7c568831SAndroid Build Coastguard Worker  *    boolean lang(string)
8170*7c568831SAndroid Build Coastguard Worker  * The lang function returns true or false depending on whether the
8171*7c568831SAndroid Build Coastguard Worker  * language of the context node as specified by xml:lang attributes
8172*7c568831SAndroid Build Coastguard Worker  * is the same as or is a sublanguage of the language specified by
8173*7c568831SAndroid Build Coastguard Worker  * the argument string. The language of the context node is determined
8174*7c568831SAndroid Build Coastguard Worker  * by the value of the xml:lang attribute on the context node, or, if
8175*7c568831SAndroid Build Coastguard Worker  * the context node has no xml:lang attribute, by the value of the
8176*7c568831SAndroid Build Coastguard Worker  * xml:lang attribute on the nearest ancestor of the context node that
8177*7c568831SAndroid Build Coastguard Worker  * has an xml:lang attribute. If there is no such attribute, then lang
8178*7c568831SAndroid Build Coastguard Worker  * returns false. If there is such an attribute, then lang returns
8179*7c568831SAndroid Build Coastguard Worker  * true if the attribute value is equal to the argument ignoring case,
8180*7c568831SAndroid Build Coastguard Worker  * or if there is some suffix starting with - such that the attribute
8181*7c568831SAndroid Build Coastguard Worker  * value is equal to the argument ignoring that suffix of the attribute
8182*7c568831SAndroid Build Coastguard Worker  * value and ignoring case.
8183*7c568831SAndroid Build Coastguard Worker  */
8184*7c568831SAndroid Build Coastguard Worker void
xmlXPathLangFunction(xmlXPathParserContextPtr ctxt,int nargs)8185*7c568831SAndroid Build Coastguard Worker xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8186*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr val;
8187*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
8188*7c568831SAndroid Build Coastguard Worker     xmlChar *theLang;
8189*7c568831SAndroid Build Coastguard Worker     const xmlChar *lang;
8190*7c568831SAndroid Build Coastguard Worker     int ret = 0;
8191*7c568831SAndroid Build Coastguard Worker     int i;
8192*7c568831SAndroid Build Coastguard Worker 
8193*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
8194*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
8195*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_STRING);
8196*7c568831SAndroid Build Coastguard Worker     val = valuePop(ctxt);
8197*7c568831SAndroid Build Coastguard Worker     lang = val->stringval;
8198*7c568831SAndroid Build Coastguard Worker     cur = ctxt->context->node;
8199*7c568831SAndroid Build Coastguard Worker     while (cur != NULL) {
8200*7c568831SAndroid Build Coastguard Worker         if (xmlNodeGetAttrValue(cur, BAD_CAST "lang", XML_XML_NAMESPACE,
8201*7c568831SAndroid Build Coastguard Worker                                 &theLang) < 0)
8202*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
8203*7c568831SAndroid Build Coastguard Worker         if (theLang != NULL)
8204*7c568831SAndroid Build Coastguard Worker             break;
8205*7c568831SAndroid Build Coastguard Worker         cur = cur->parent;
8206*7c568831SAndroid Build Coastguard Worker     }
8207*7c568831SAndroid Build Coastguard Worker     if ((theLang != NULL) && (lang != NULL)) {
8208*7c568831SAndroid Build Coastguard Worker         for (i = 0;lang[i] != 0;i++)
8209*7c568831SAndroid Build Coastguard Worker             if (toupper(lang[i]) != toupper(theLang[i]))
8210*7c568831SAndroid Build Coastguard Worker                 goto not_equal;
8211*7c568831SAndroid Build Coastguard Worker         if ((theLang[i] == 0) || (theLang[i] == '-'))
8212*7c568831SAndroid Build Coastguard Worker             ret = 1;
8213*7c568831SAndroid Build Coastguard Worker     }
8214*7c568831SAndroid Build Coastguard Worker not_equal:
8215*7c568831SAndroid Build Coastguard Worker     if (theLang != NULL)
8216*7c568831SAndroid Build Coastguard Worker 	xmlFree((void *)theLang);
8217*7c568831SAndroid Build Coastguard Worker 
8218*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, val);
8219*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret));
8220*7c568831SAndroid Build Coastguard Worker }
8221*7c568831SAndroid Build Coastguard Worker 
8222*7c568831SAndroid Build Coastguard Worker /**
8223*7c568831SAndroid Build Coastguard Worker  * xmlXPathNumberFunction:
8224*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8225*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8226*7c568831SAndroid Build Coastguard Worker  *
8227*7c568831SAndroid Build Coastguard Worker  * Implement the number() XPath function
8228*7c568831SAndroid Build Coastguard Worker  *    number number(object?)
8229*7c568831SAndroid Build Coastguard Worker  */
8230*7c568831SAndroid Build Coastguard Worker void
xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt,int nargs)8231*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8232*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
8233*7c568831SAndroid Build Coastguard Worker     double res;
8234*7c568831SAndroid Build Coastguard Worker 
8235*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) return;
8236*7c568831SAndroid Build Coastguard Worker     if (nargs == 0) {
8237*7c568831SAndroid Build Coastguard Worker 	if (ctxt->context->node == NULL) {
8238*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0));
8239*7c568831SAndroid Build Coastguard Worker 	} else {
8240*7c568831SAndroid Build Coastguard Worker 	    xmlChar* content = xmlNodeGetContent(ctxt->context->node);
8241*7c568831SAndroid Build Coastguard Worker             if (content == NULL)
8242*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
8243*7c568831SAndroid Build Coastguard Worker 
8244*7c568831SAndroid Build Coastguard Worker 	    res = xmlXPathStringEvalNumber(content);
8245*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res));
8246*7c568831SAndroid Build Coastguard Worker 	    xmlFree(content);
8247*7c568831SAndroid Build Coastguard Worker 	}
8248*7c568831SAndroid Build Coastguard Worker 	return;
8249*7c568831SAndroid Build Coastguard Worker     }
8250*7c568831SAndroid Build Coastguard Worker 
8251*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
8252*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
8253*7c568831SAndroid Build Coastguard Worker     if (cur->type != XPATH_NUMBER) {
8254*7c568831SAndroid Build Coastguard Worker         double floatval;
8255*7c568831SAndroid Build Coastguard Worker 
8256*7c568831SAndroid Build Coastguard Worker         floatval = xmlXPathCastToNumberInternal(ctxt, cur);
8257*7c568831SAndroid Build Coastguard Worker         xmlXPathReleaseObject(ctxt->context, cur);
8258*7c568831SAndroid Build Coastguard Worker         cur = xmlXPathCacheNewFloat(ctxt, floatval);
8259*7c568831SAndroid Build Coastguard Worker     }
8260*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, cur);
8261*7c568831SAndroid Build Coastguard Worker }
8262*7c568831SAndroid Build Coastguard Worker 
8263*7c568831SAndroid Build Coastguard Worker /**
8264*7c568831SAndroid Build Coastguard Worker  * xmlXPathSumFunction:
8265*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8266*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8267*7c568831SAndroid Build Coastguard Worker  *
8268*7c568831SAndroid Build Coastguard Worker  * Implement the sum() XPath function
8269*7c568831SAndroid Build Coastguard Worker  *    number sum(node-set)
8270*7c568831SAndroid Build Coastguard Worker  * The sum function returns the sum of the values of the nodes in
8271*7c568831SAndroid Build Coastguard Worker  * the argument node-set.
8272*7c568831SAndroid Build Coastguard Worker  */
8273*7c568831SAndroid Build Coastguard Worker void
xmlXPathSumFunction(xmlXPathParserContextPtr ctxt,int nargs)8274*7c568831SAndroid Build Coastguard Worker xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8275*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr cur;
8276*7c568831SAndroid Build Coastguard Worker     int i;
8277*7c568831SAndroid Build Coastguard Worker     double res = 0.0;
8278*7c568831SAndroid Build Coastguard Worker 
8279*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
8280*7c568831SAndroid Build Coastguard Worker     if ((ctxt->value == NULL) ||
8281*7c568831SAndroid Build Coastguard Worker 	((ctxt->value->type != XPATH_NODESET) &&
8282*7c568831SAndroid Build Coastguard Worker 	 (ctxt->value->type != XPATH_XSLT_TREE)))
8283*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_TYPE);
8284*7c568831SAndroid Build Coastguard Worker     cur = valuePop(ctxt);
8285*7c568831SAndroid Build Coastguard Worker 
8286*7c568831SAndroid Build Coastguard Worker     if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
8287*7c568831SAndroid Build Coastguard Worker 	for (i = 0; i < cur->nodesetval->nodeNr; i++) {
8288*7c568831SAndroid Build Coastguard Worker 	    res += xmlXPathNodeToNumberInternal(ctxt,
8289*7c568831SAndroid Build Coastguard Worker                                                 cur->nodesetval->nodeTab[i]);
8290*7c568831SAndroid Build Coastguard Worker 	}
8291*7c568831SAndroid Build Coastguard Worker     }
8292*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res));
8293*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, cur);
8294*7c568831SAndroid Build Coastguard Worker }
8295*7c568831SAndroid Build Coastguard Worker 
8296*7c568831SAndroid Build Coastguard Worker /**
8297*7c568831SAndroid Build Coastguard Worker  * xmlXPathFloorFunction:
8298*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8299*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8300*7c568831SAndroid Build Coastguard Worker  *
8301*7c568831SAndroid Build Coastguard Worker  * Implement the floor() XPath function
8302*7c568831SAndroid Build Coastguard Worker  *    number floor(number)
8303*7c568831SAndroid Build Coastguard Worker  * The floor function returns the largest (closest to positive infinity)
8304*7c568831SAndroid Build Coastguard Worker  * number that is not greater than the argument and that is an integer.
8305*7c568831SAndroid Build Coastguard Worker  */
8306*7c568831SAndroid Build Coastguard Worker void
xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt,int nargs)8307*7c568831SAndroid Build Coastguard Worker xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8308*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
8309*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
8310*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
8311*7c568831SAndroid Build Coastguard Worker 
8312*7c568831SAndroid Build Coastguard Worker     ctxt->value->floatval = floor(ctxt->value->floatval);
8313*7c568831SAndroid Build Coastguard Worker }
8314*7c568831SAndroid Build Coastguard Worker 
8315*7c568831SAndroid Build Coastguard Worker /**
8316*7c568831SAndroid Build Coastguard Worker  * xmlXPathCeilingFunction:
8317*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8318*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8319*7c568831SAndroid Build Coastguard Worker  *
8320*7c568831SAndroid Build Coastguard Worker  * Implement the ceiling() XPath function
8321*7c568831SAndroid Build Coastguard Worker  *    number ceiling(number)
8322*7c568831SAndroid Build Coastguard Worker  * The ceiling function returns the smallest (closest to negative infinity)
8323*7c568831SAndroid Build Coastguard Worker  * number that is not less than the argument and that is an integer.
8324*7c568831SAndroid Build Coastguard Worker  */
8325*7c568831SAndroid Build Coastguard Worker void
xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt,int nargs)8326*7c568831SAndroid Build Coastguard Worker xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8327*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
8328*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
8329*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
8330*7c568831SAndroid Build Coastguard Worker 
8331*7c568831SAndroid Build Coastguard Worker #ifdef _AIX
8332*7c568831SAndroid Build Coastguard Worker     /* Work around buggy ceil() function on AIX */
8333*7c568831SAndroid Build Coastguard Worker     ctxt->value->floatval = copysign(ceil(ctxt->value->floatval), ctxt->value->floatval);
8334*7c568831SAndroid Build Coastguard Worker #else
8335*7c568831SAndroid Build Coastguard Worker     ctxt->value->floatval = ceil(ctxt->value->floatval);
8336*7c568831SAndroid Build Coastguard Worker #endif
8337*7c568831SAndroid Build Coastguard Worker }
8338*7c568831SAndroid Build Coastguard Worker 
8339*7c568831SAndroid Build Coastguard Worker /**
8340*7c568831SAndroid Build Coastguard Worker  * xmlXPathRoundFunction:
8341*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8342*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
8343*7c568831SAndroid Build Coastguard Worker  *
8344*7c568831SAndroid Build Coastguard Worker  * Implement the round() XPath function
8345*7c568831SAndroid Build Coastguard Worker  *    number round(number)
8346*7c568831SAndroid Build Coastguard Worker  * The round function returns the number that is closest to the
8347*7c568831SAndroid Build Coastguard Worker  * argument and that is an integer. If there are two such numbers,
8348*7c568831SAndroid Build Coastguard Worker  * then the one that is closest to positive infinity is returned.
8349*7c568831SAndroid Build Coastguard Worker  */
8350*7c568831SAndroid Build Coastguard Worker void
xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt,int nargs)8351*7c568831SAndroid Build Coastguard Worker xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8352*7c568831SAndroid Build Coastguard Worker     double f;
8353*7c568831SAndroid Build Coastguard Worker 
8354*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(1);
8355*7c568831SAndroid Build Coastguard Worker     CAST_TO_NUMBER;
8356*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE(XPATH_NUMBER);
8357*7c568831SAndroid Build Coastguard Worker 
8358*7c568831SAndroid Build Coastguard Worker     f = ctxt->value->floatval;
8359*7c568831SAndroid Build Coastguard Worker 
8360*7c568831SAndroid Build Coastguard Worker     if ((f >= -0.5) && (f < 0.5)) {
8361*7c568831SAndroid Build Coastguard Worker         /* Handles negative zero. */
8362*7c568831SAndroid Build Coastguard Worker         ctxt->value->floatval *= 0.0;
8363*7c568831SAndroid Build Coastguard Worker     }
8364*7c568831SAndroid Build Coastguard Worker     else {
8365*7c568831SAndroid Build Coastguard Worker         double rounded = floor(f);
8366*7c568831SAndroid Build Coastguard Worker         if (f - rounded >= 0.5)
8367*7c568831SAndroid Build Coastguard Worker             rounded += 1.0;
8368*7c568831SAndroid Build Coastguard Worker         ctxt->value->floatval = rounded;
8369*7c568831SAndroid Build Coastguard Worker     }
8370*7c568831SAndroid Build Coastguard Worker }
8371*7c568831SAndroid Build Coastguard Worker 
8372*7c568831SAndroid Build Coastguard Worker /************************************************************************
8373*7c568831SAndroid Build Coastguard Worker  *									*
8374*7c568831SAndroid Build Coastguard Worker  *			The Parser					*
8375*7c568831SAndroid Build Coastguard Worker  *									*
8376*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
8377*7c568831SAndroid Build Coastguard Worker 
8378*7c568831SAndroid Build Coastguard Worker /*
8379*7c568831SAndroid Build Coastguard Worker  * a few forward declarations since we use a recursive call based
8380*7c568831SAndroid Build Coastguard Worker  * implementation.
8381*7c568831SAndroid Build Coastguard Worker  */
8382*7c568831SAndroid Build Coastguard Worker static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort);
8383*7c568831SAndroid Build Coastguard Worker static void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
8384*7c568831SAndroid Build Coastguard Worker static void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
8385*7c568831SAndroid Build Coastguard Worker static void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt);
8386*7c568831SAndroid Build Coastguard Worker static xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,
8387*7c568831SAndroid Build Coastguard Worker 	                                  int qualified);
8388*7c568831SAndroid Build Coastguard Worker 
8389*7c568831SAndroid Build Coastguard Worker /**
8390*7c568831SAndroid Build Coastguard Worker  * xmlXPathCurrentChar:
8391*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath parser context
8392*7c568831SAndroid Build Coastguard Worker  * @cur:  pointer to the beginning of the char
8393*7c568831SAndroid Build Coastguard Worker  * @len:  pointer to the length of the char read
8394*7c568831SAndroid Build Coastguard Worker  *
8395*7c568831SAndroid Build Coastguard Worker  * The current char value, if using UTF-8 this may actually span multiple
8396*7c568831SAndroid Build Coastguard Worker  * bytes in the input buffer.
8397*7c568831SAndroid Build Coastguard Worker  *
8398*7c568831SAndroid Build Coastguard Worker  * Returns the current char value and its length
8399*7c568831SAndroid Build Coastguard Worker  */
8400*7c568831SAndroid Build Coastguard Worker 
8401*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt,int * len)8402*7c568831SAndroid Build Coastguard Worker xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
8403*7c568831SAndroid Build Coastguard Worker     unsigned char c;
8404*7c568831SAndroid Build Coastguard Worker     unsigned int val;
8405*7c568831SAndroid Build Coastguard Worker     const xmlChar *cur;
8406*7c568831SAndroid Build Coastguard Worker 
8407*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
8408*7c568831SAndroid Build Coastguard Worker 	return(0);
8409*7c568831SAndroid Build Coastguard Worker     cur = ctxt->cur;
8410*7c568831SAndroid Build Coastguard Worker 
8411*7c568831SAndroid Build Coastguard Worker     /*
8412*7c568831SAndroid Build Coastguard Worker      * We are supposed to handle UTF8, check it's valid
8413*7c568831SAndroid Build Coastguard Worker      * From rfc2044: encoding of the Unicode values on UTF-8:
8414*7c568831SAndroid Build Coastguard Worker      *
8415*7c568831SAndroid Build Coastguard Worker      * UCS-4 range (hex.)           UTF-8 octet sequence (binary)
8416*7c568831SAndroid Build Coastguard Worker      * 0000 0000-0000 007F   0xxxxxxx
8417*7c568831SAndroid Build Coastguard Worker      * 0000 0080-0000 07FF   110xxxxx 10xxxxxx
8418*7c568831SAndroid Build Coastguard Worker      * 0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
8419*7c568831SAndroid Build Coastguard Worker      *
8420*7c568831SAndroid Build Coastguard Worker      * Check for the 0x110000 limit too
8421*7c568831SAndroid Build Coastguard Worker      */
8422*7c568831SAndroid Build Coastguard Worker     c = *cur;
8423*7c568831SAndroid Build Coastguard Worker     if (c & 0x80) {
8424*7c568831SAndroid Build Coastguard Worker 	if ((cur[1] & 0xc0) != 0x80)
8425*7c568831SAndroid Build Coastguard Worker 	    goto encoding_error;
8426*7c568831SAndroid Build Coastguard Worker 	if ((c & 0xe0) == 0xe0) {
8427*7c568831SAndroid Build Coastguard Worker 
8428*7c568831SAndroid Build Coastguard Worker 	    if ((cur[2] & 0xc0) != 0x80)
8429*7c568831SAndroid Build Coastguard Worker 		goto encoding_error;
8430*7c568831SAndroid Build Coastguard Worker 	    if ((c & 0xf0) == 0xf0) {
8431*7c568831SAndroid Build Coastguard Worker 		if (((c & 0xf8) != 0xf0) ||
8432*7c568831SAndroid Build Coastguard Worker 		    ((cur[3] & 0xc0) != 0x80))
8433*7c568831SAndroid Build Coastguard Worker 		    goto encoding_error;
8434*7c568831SAndroid Build Coastguard Worker 		/* 4-byte code */
8435*7c568831SAndroid Build Coastguard Worker 		*len = 4;
8436*7c568831SAndroid Build Coastguard Worker 		val = (cur[0] & 0x7) << 18;
8437*7c568831SAndroid Build Coastguard Worker 		val |= (cur[1] & 0x3f) << 12;
8438*7c568831SAndroid Build Coastguard Worker 		val |= (cur[2] & 0x3f) << 6;
8439*7c568831SAndroid Build Coastguard Worker 		val |= cur[3] & 0x3f;
8440*7c568831SAndroid Build Coastguard Worker 	    } else {
8441*7c568831SAndroid Build Coastguard Worker 	      /* 3-byte code */
8442*7c568831SAndroid Build Coastguard Worker 		*len = 3;
8443*7c568831SAndroid Build Coastguard Worker 		val = (cur[0] & 0xf) << 12;
8444*7c568831SAndroid Build Coastguard Worker 		val |= (cur[1] & 0x3f) << 6;
8445*7c568831SAndroid Build Coastguard Worker 		val |= cur[2] & 0x3f;
8446*7c568831SAndroid Build Coastguard Worker 	    }
8447*7c568831SAndroid Build Coastguard Worker 	} else {
8448*7c568831SAndroid Build Coastguard Worker 	  /* 2-byte code */
8449*7c568831SAndroid Build Coastguard Worker 	    *len = 2;
8450*7c568831SAndroid Build Coastguard Worker 	    val = (cur[0] & 0x1f) << 6;
8451*7c568831SAndroid Build Coastguard Worker 	    val |= cur[1] & 0x3f;
8452*7c568831SAndroid Build Coastguard Worker 	}
8453*7c568831SAndroid Build Coastguard Worker 	if (!IS_CHAR(val)) {
8454*7c568831SAndroid Build Coastguard Worker 	    XP_ERROR0(XPATH_INVALID_CHAR_ERROR);
8455*7c568831SAndroid Build Coastguard Worker 	}
8456*7c568831SAndroid Build Coastguard Worker 	return(val);
8457*7c568831SAndroid Build Coastguard Worker     } else {
8458*7c568831SAndroid Build Coastguard Worker 	/* 1-byte code */
8459*7c568831SAndroid Build Coastguard Worker 	*len = 1;
8460*7c568831SAndroid Build Coastguard Worker 	return(*cur);
8461*7c568831SAndroid Build Coastguard Worker     }
8462*7c568831SAndroid Build Coastguard Worker encoding_error:
8463*7c568831SAndroid Build Coastguard Worker     /*
8464*7c568831SAndroid Build Coastguard Worker      * If we detect an UTF8 error that probably means that the
8465*7c568831SAndroid Build Coastguard Worker      * input encoding didn't get properly advertised in the
8466*7c568831SAndroid Build Coastguard Worker      * declaration header. Report the error and switch the encoding
8467*7c568831SAndroid Build Coastguard Worker      * to ISO-Latin-1 (if you don't like this policy, just declare the
8468*7c568831SAndroid Build Coastguard Worker      * encoding !)
8469*7c568831SAndroid Build Coastguard Worker      */
8470*7c568831SAndroid Build Coastguard Worker     *len = 0;
8471*7c568831SAndroid Build Coastguard Worker     XP_ERROR0(XPATH_ENCODING_ERROR);
8472*7c568831SAndroid Build Coastguard Worker }
8473*7c568831SAndroid Build Coastguard Worker 
8474*7c568831SAndroid Build Coastguard Worker /**
8475*7c568831SAndroid Build Coastguard Worker  * xmlXPathParseNCName:
8476*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8477*7c568831SAndroid Build Coastguard Worker  *
8478*7c568831SAndroid Build Coastguard Worker  * parse an XML namespace non qualified name.
8479*7c568831SAndroid Build Coastguard Worker  *
8480*7c568831SAndroid Build Coastguard Worker  * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
8481*7c568831SAndroid Build Coastguard Worker  *
8482*7c568831SAndroid Build Coastguard Worker  * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
8483*7c568831SAndroid Build Coastguard Worker  *                       CombiningChar | Extender
8484*7c568831SAndroid Build Coastguard Worker  *
8485*7c568831SAndroid Build Coastguard Worker  * Returns the namespace name or NULL
8486*7c568831SAndroid Build Coastguard Worker  */
8487*7c568831SAndroid Build Coastguard Worker 
8488*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathParseNCName(xmlXPathParserContextPtr ctxt)8489*7c568831SAndroid Build Coastguard Worker xmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
8490*7c568831SAndroid Build Coastguard Worker     const xmlChar *in;
8491*7c568831SAndroid Build Coastguard Worker     xmlChar *ret;
8492*7c568831SAndroid Build Coastguard Worker     int count = 0;
8493*7c568831SAndroid Build Coastguard Worker 
8494*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
8495*7c568831SAndroid Build Coastguard Worker     /*
8496*7c568831SAndroid Build Coastguard Worker      * Accelerator for simple ASCII names
8497*7c568831SAndroid Build Coastguard Worker      */
8498*7c568831SAndroid Build Coastguard Worker     in = ctxt->cur;
8499*7c568831SAndroid Build Coastguard Worker     if (((*in >= 0x61) && (*in <= 0x7A)) ||
8500*7c568831SAndroid Build Coastguard Worker 	((*in >= 0x41) && (*in <= 0x5A)) ||
8501*7c568831SAndroid Build Coastguard Worker 	(*in == '_')) {
8502*7c568831SAndroid Build Coastguard Worker 	in++;
8503*7c568831SAndroid Build Coastguard Worker 	while (((*in >= 0x61) && (*in <= 0x7A)) ||
8504*7c568831SAndroid Build Coastguard Worker 	       ((*in >= 0x41) && (*in <= 0x5A)) ||
8505*7c568831SAndroid Build Coastguard Worker 	       ((*in >= 0x30) && (*in <= 0x39)) ||
8506*7c568831SAndroid Build Coastguard Worker 	       (*in == '_') || (*in == '.') ||
8507*7c568831SAndroid Build Coastguard Worker 	       (*in == '-'))
8508*7c568831SAndroid Build Coastguard Worker 	    in++;
8509*7c568831SAndroid Build Coastguard Worker 	if ((*in == ' ') || (*in == '>') || (*in == '/') ||
8510*7c568831SAndroid Build Coastguard Worker             (*in == '[') || (*in == ']') || (*in == ':') ||
8511*7c568831SAndroid Build Coastguard Worker             (*in == '@') || (*in == '*')) {
8512*7c568831SAndroid Build Coastguard Worker 	    count = in - ctxt->cur;
8513*7c568831SAndroid Build Coastguard Worker 	    if (count == 0)
8514*7c568831SAndroid Build Coastguard Worker 		return(NULL);
8515*7c568831SAndroid Build Coastguard Worker 	    ret = xmlStrndup(ctxt->cur, count);
8516*7c568831SAndroid Build Coastguard Worker             if (ret == NULL)
8517*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
8518*7c568831SAndroid Build Coastguard Worker 	    ctxt->cur = in;
8519*7c568831SAndroid Build Coastguard Worker 	    return(ret);
8520*7c568831SAndroid Build Coastguard Worker 	}
8521*7c568831SAndroid Build Coastguard Worker     }
8522*7c568831SAndroid Build Coastguard Worker     return(xmlXPathParseNameComplex(ctxt, 0));
8523*7c568831SAndroid Build Coastguard Worker }
8524*7c568831SAndroid Build Coastguard Worker 
8525*7c568831SAndroid Build Coastguard Worker 
8526*7c568831SAndroid Build Coastguard Worker /**
8527*7c568831SAndroid Build Coastguard Worker  * xmlXPathParseQName:
8528*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8529*7c568831SAndroid Build Coastguard Worker  * @prefix:  a xmlChar **
8530*7c568831SAndroid Build Coastguard Worker  *
8531*7c568831SAndroid Build Coastguard Worker  * parse an XML qualified name
8532*7c568831SAndroid Build Coastguard Worker  *
8533*7c568831SAndroid Build Coastguard Worker  * [NS 5] QName ::= (Prefix ':')? LocalPart
8534*7c568831SAndroid Build Coastguard Worker  *
8535*7c568831SAndroid Build Coastguard Worker  * [NS 6] Prefix ::= NCName
8536*7c568831SAndroid Build Coastguard Worker  *
8537*7c568831SAndroid Build Coastguard Worker  * [NS 7] LocalPart ::= NCName
8538*7c568831SAndroid Build Coastguard Worker  *
8539*7c568831SAndroid Build Coastguard Worker  * Returns the function returns the local part, and prefix is updated
8540*7c568831SAndroid Build Coastguard Worker  *   to get the Prefix if any.
8541*7c568831SAndroid Build Coastguard Worker  */
8542*7c568831SAndroid Build Coastguard Worker 
8543*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseQName(xmlXPathParserContextPtr ctxt,xmlChar ** prefix)8544*7c568831SAndroid Build Coastguard Worker xmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
8545*7c568831SAndroid Build Coastguard Worker     xmlChar *ret = NULL;
8546*7c568831SAndroid Build Coastguard Worker 
8547*7c568831SAndroid Build Coastguard Worker     *prefix = NULL;
8548*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathParseNCName(ctxt);
8549*7c568831SAndroid Build Coastguard Worker     if (ret && CUR == ':') {
8550*7c568831SAndroid Build Coastguard Worker         *prefix = ret;
8551*7c568831SAndroid Build Coastguard Worker 	NEXT;
8552*7c568831SAndroid Build Coastguard Worker 	ret = xmlXPathParseNCName(ctxt);
8553*7c568831SAndroid Build Coastguard Worker     }
8554*7c568831SAndroid Build Coastguard Worker     return(ret);
8555*7c568831SAndroid Build Coastguard Worker }
8556*7c568831SAndroid Build Coastguard Worker 
8557*7c568831SAndroid Build Coastguard Worker /**
8558*7c568831SAndroid Build Coastguard Worker  * xmlXPathParseName:
8559*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8560*7c568831SAndroid Build Coastguard Worker  *
8561*7c568831SAndroid Build Coastguard Worker  * parse an XML name
8562*7c568831SAndroid Build Coastguard Worker  *
8563*7c568831SAndroid Build Coastguard Worker  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
8564*7c568831SAndroid Build Coastguard Worker  *                  CombiningChar | Extender
8565*7c568831SAndroid Build Coastguard Worker  *
8566*7c568831SAndroid Build Coastguard Worker  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
8567*7c568831SAndroid Build Coastguard Worker  *
8568*7c568831SAndroid Build Coastguard Worker  * Returns the namespace name or NULL
8569*7c568831SAndroid Build Coastguard Worker  */
8570*7c568831SAndroid Build Coastguard Worker 
8571*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathParseName(xmlXPathParserContextPtr ctxt)8572*7c568831SAndroid Build Coastguard Worker xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
8573*7c568831SAndroid Build Coastguard Worker     const xmlChar *in;
8574*7c568831SAndroid Build Coastguard Worker     xmlChar *ret;
8575*7c568831SAndroid Build Coastguard Worker     size_t count = 0;
8576*7c568831SAndroid Build Coastguard Worker 
8577*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
8578*7c568831SAndroid Build Coastguard Worker     /*
8579*7c568831SAndroid Build Coastguard Worker      * Accelerator for simple ASCII names
8580*7c568831SAndroid Build Coastguard Worker      */
8581*7c568831SAndroid Build Coastguard Worker     in = ctxt->cur;
8582*7c568831SAndroid Build Coastguard Worker     if (((*in >= 0x61) && (*in <= 0x7A)) ||
8583*7c568831SAndroid Build Coastguard Worker 	((*in >= 0x41) && (*in <= 0x5A)) ||
8584*7c568831SAndroid Build Coastguard Worker 	(*in == '_') || (*in == ':')) {
8585*7c568831SAndroid Build Coastguard Worker 	in++;
8586*7c568831SAndroid Build Coastguard Worker 	while (((*in >= 0x61) && (*in <= 0x7A)) ||
8587*7c568831SAndroid Build Coastguard Worker 	       ((*in >= 0x41) && (*in <= 0x5A)) ||
8588*7c568831SAndroid Build Coastguard Worker 	       ((*in >= 0x30) && (*in <= 0x39)) ||
8589*7c568831SAndroid Build Coastguard Worker 	       (*in == '_') || (*in == '-') ||
8590*7c568831SAndroid Build Coastguard Worker 	       (*in == ':') || (*in == '.'))
8591*7c568831SAndroid Build Coastguard Worker 	    in++;
8592*7c568831SAndroid Build Coastguard Worker 	if ((*in > 0) && (*in < 0x80)) {
8593*7c568831SAndroid Build Coastguard Worker 	    count = in - ctxt->cur;
8594*7c568831SAndroid Build Coastguard Worker             if (count > XML_MAX_NAME_LENGTH) {
8595*7c568831SAndroid Build Coastguard Worker                 ctxt->cur = in;
8596*7c568831SAndroid Build Coastguard Worker                 XP_ERRORNULL(XPATH_EXPR_ERROR);
8597*7c568831SAndroid Build Coastguard Worker             }
8598*7c568831SAndroid Build Coastguard Worker 	    ret = xmlStrndup(ctxt->cur, count);
8599*7c568831SAndroid Build Coastguard Worker             if (ret == NULL)
8600*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
8601*7c568831SAndroid Build Coastguard Worker 	    ctxt->cur = in;
8602*7c568831SAndroid Build Coastguard Worker 	    return(ret);
8603*7c568831SAndroid Build Coastguard Worker 	}
8604*7c568831SAndroid Build Coastguard Worker     }
8605*7c568831SAndroid Build Coastguard Worker     return(xmlXPathParseNameComplex(ctxt, 1));
8606*7c568831SAndroid Build Coastguard Worker }
8607*7c568831SAndroid Build Coastguard Worker 
8608*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,int qualified)8609*7c568831SAndroid Build Coastguard Worker xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
8610*7c568831SAndroid Build Coastguard Worker     xmlChar *ret;
8611*7c568831SAndroid Build Coastguard Worker     xmlChar buf[XML_MAX_NAMELEN + 5];
8612*7c568831SAndroid Build Coastguard Worker     int len = 0, l;
8613*7c568831SAndroid Build Coastguard Worker     int c;
8614*7c568831SAndroid Build Coastguard Worker 
8615*7c568831SAndroid Build Coastguard Worker     /*
8616*7c568831SAndroid Build Coastguard Worker      * Handler for more complex cases
8617*7c568831SAndroid Build Coastguard Worker      */
8618*7c568831SAndroid Build Coastguard Worker     c = CUR_CHAR(l);
8619*7c568831SAndroid Build Coastguard Worker     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
8620*7c568831SAndroid Build Coastguard Worker         (c == '[') || (c == ']') || (c == '@') || /* accelerators */
8621*7c568831SAndroid Build Coastguard Worker         (c == '*') || /* accelerators */
8622*7c568831SAndroid Build Coastguard Worker 	(!IS_LETTER(c) && (c != '_') &&
8623*7c568831SAndroid Build Coastguard Worker          ((!qualified) || (c != ':')))) {
8624*7c568831SAndroid Build Coastguard Worker 	return(NULL);
8625*7c568831SAndroid Build Coastguard Worker     }
8626*7c568831SAndroid Build Coastguard Worker 
8627*7c568831SAndroid Build Coastguard Worker     while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
8628*7c568831SAndroid Build Coastguard Worker 	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
8629*7c568831SAndroid Build Coastguard Worker             (c == '.') || (c == '-') ||
8630*7c568831SAndroid Build Coastguard Worker 	    (c == '_') || ((qualified) && (c == ':')) ||
8631*7c568831SAndroid Build Coastguard Worker 	    (IS_COMBINING(c)) ||
8632*7c568831SAndroid Build Coastguard Worker 	    (IS_EXTENDER(c)))) {
8633*7c568831SAndroid Build Coastguard Worker 	COPY_BUF(buf,len,c);
8634*7c568831SAndroid Build Coastguard Worker 	NEXTL(l);
8635*7c568831SAndroid Build Coastguard Worker 	c = CUR_CHAR(l);
8636*7c568831SAndroid Build Coastguard Worker 	if (len >= XML_MAX_NAMELEN) {
8637*7c568831SAndroid Build Coastguard Worker 	    /*
8638*7c568831SAndroid Build Coastguard Worker 	     * Okay someone managed to make a huge name, so he's ready to pay
8639*7c568831SAndroid Build Coastguard Worker 	     * for the processing speed.
8640*7c568831SAndroid Build Coastguard Worker 	     */
8641*7c568831SAndroid Build Coastguard Worker 	    xmlChar *buffer;
8642*7c568831SAndroid Build Coastguard Worker 	    int max = len * 2;
8643*7c568831SAndroid Build Coastguard Worker 
8644*7c568831SAndroid Build Coastguard Worker             if (len > XML_MAX_NAME_LENGTH) {
8645*7c568831SAndroid Build Coastguard Worker                 XP_ERRORNULL(XPATH_EXPR_ERROR);
8646*7c568831SAndroid Build Coastguard Worker             }
8647*7c568831SAndroid Build Coastguard Worker 	    buffer = xmlMalloc(max);
8648*7c568831SAndroid Build Coastguard Worker 	    if (buffer == NULL) {
8649*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
8650*7c568831SAndroid Build Coastguard Worker                 return(NULL);
8651*7c568831SAndroid Build Coastguard Worker 	    }
8652*7c568831SAndroid Build Coastguard Worker 	    memcpy(buffer, buf, len);
8653*7c568831SAndroid Build Coastguard Worker 	    while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
8654*7c568831SAndroid Build Coastguard Worker 		   (c == '.') || (c == '-') ||
8655*7c568831SAndroid Build Coastguard Worker 		   (c == '_') || ((qualified) && (c == ':')) ||
8656*7c568831SAndroid Build Coastguard Worker 		   (IS_COMBINING(c)) ||
8657*7c568831SAndroid Build Coastguard Worker 		   (IS_EXTENDER(c))) {
8658*7c568831SAndroid Build Coastguard Worker 		if (len + 10 > max) {
8659*7c568831SAndroid Build Coastguard Worker                     xmlChar *tmp;
8660*7c568831SAndroid Build Coastguard Worker                     if (max > XML_MAX_NAME_LENGTH) {
8661*7c568831SAndroid Build Coastguard Worker                         xmlFree(buffer);
8662*7c568831SAndroid Build Coastguard Worker                         XP_ERRORNULL(XPATH_EXPR_ERROR);
8663*7c568831SAndroid Build Coastguard Worker                     }
8664*7c568831SAndroid Build Coastguard Worker 		    max *= 2;
8665*7c568831SAndroid Build Coastguard Worker 		    tmp = (xmlChar *) xmlRealloc(buffer, max);
8666*7c568831SAndroid Build Coastguard Worker 		    if (tmp == NULL) {
8667*7c568831SAndroid Build Coastguard Worker                         xmlFree(buffer);
8668*7c568831SAndroid Build Coastguard Worker                         xmlXPathPErrMemory(ctxt);
8669*7c568831SAndroid Build Coastguard Worker                         return(NULL);
8670*7c568831SAndroid Build Coastguard Worker 		    }
8671*7c568831SAndroid Build Coastguard Worker                     buffer = tmp;
8672*7c568831SAndroid Build Coastguard Worker 		}
8673*7c568831SAndroid Build Coastguard Worker 		COPY_BUF(buffer,len,c);
8674*7c568831SAndroid Build Coastguard Worker 		NEXTL(l);
8675*7c568831SAndroid Build Coastguard Worker 		c = CUR_CHAR(l);
8676*7c568831SAndroid Build Coastguard Worker 	    }
8677*7c568831SAndroid Build Coastguard Worker 	    buffer[len] = 0;
8678*7c568831SAndroid Build Coastguard Worker 	    return(buffer);
8679*7c568831SAndroid Build Coastguard Worker 	}
8680*7c568831SAndroid Build Coastguard Worker     }
8681*7c568831SAndroid Build Coastguard Worker     if (len == 0)
8682*7c568831SAndroid Build Coastguard Worker 	return(NULL);
8683*7c568831SAndroid Build Coastguard Worker     ret = xmlStrndup(buf, len);
8684*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
8685*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
8686*7c568831SAndroid Build Coastguard Worker     return(ret);
8687*7c568831SAndroid Build Coastguard Worker }
8688*7c568831SAndroid Build Coastguard Worker 
8689*7c568831SAndroid Build Coastguard Worker #define MAX_FRAC 20
8690*7c568831SAndroid Build Coastguard Worker 
8691*7c568831SAndroid Build Coastguard Worker /**
8692*7c568831SAndroid Build Coastguard Worker  * xmlXPathStringEvalNumber:
8693*7c568831SAndroid Build Coastguard Worker  * @str:  A string to scan
8694*7c568831SAndroid Build Coastguard Worker  *
8695*7c568831SAndroid Build Coastguard Worker  *  [30a]  Float  ::= Number ('e' Digits?)?
8696*7c568831SAndroid Build Coastguard Worker  *
8697*7c568831SAndroid Build Coastguard Worker  *  [30]   Number ::=   Digits ('.' Digits?)?
8698*7c568831SAndroid Build Coastguard Worker  *                    | '.' Digits
8699*7c568831SAndroid Build Coastguard Worker  *  [31]   Digits ::=   [0-9]+
8700*7c568831SAndroid Build Coastguard Worker  *
8701*7c568831SAndroid Build Coastguard Worker  * Compile a Number in the string
8702*7c568831SAndroid Build Coastguard Worker  * In complement of the Number expression, this function also handles
8703*7c568831SAndroid Build Coastguard Worker  * negative values : '-' Number.
8704*7c568831SAndroid Build Coastguard Worker  *
8705*7c568831SAndroid Build Coastguard Worker  * Returns the double value.
8706*7c568831SAndroid Build Coastguard Worker  */
8707*7c568831SAndroid Build Coastguard Worker double
xmlXPathStringEvalNumber(const xmlChar * str)8708*7c568831SAndroid Build Coastguard Worker xmlXPathStringEvalNumber(const xmlChar *str) {
8709*7c568831SAndroid Build Coastguard Worker     const xmlChar *cur = str;
8710*7c568831SAndroid Build Coastguard Worker     double ret;
8711*7c568831SAndroid Build Coastguard Worker     int ok = 0;
8712*7c568831SAndroid Build Coastguard Worker     int isneg = 0;
8713*7c568831SAndroid Build Coastguard Worker     int exponent = 0;
8714*7c568831SAndroid Build Coastguard Worker     int is_exponent_negative = 0;
8715*7c568831SAndroid Build Coastguard Worker #ifdef __GNUC__
8716*7c568831SAndroid Build Coastguard Worker     unsigned long tmp = 0;
8717*7c568831SAndroid Build Coastguard Worker     double temp;
8718*7c568831SAndroid Build Coastguard Worker #endif
8719*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) return(0);
8720*7c568831SAndroid Build Coastguard Worker     while (IS_BLANK_CH(*cur)) cur++;
8721*7c568831SAndroid Build Coastguard Worker     if (*cur == '-') {
8722*7c568831SAndroid Build Coastguard Worker 	isneg = 1;
8723*7c568831SAndroid Build Coastguard Worker 	cur++;
8724*7c568831SAndroid Build Coastguard Worker     }
8725*7c568831SAndroid Build Coastguard Worker     if ((*cur != '.') && ((*cur < '0') || (*cur > '9'))) {
8726*7c568831SAndroid Build Coastguard Worker         return(xmlXPathNAN);
8727*7c568831SAndroid Build Coastguard Worker     }
8728*7c568831SAndroid Build Coastguard Worker 
8729*7c568831SAndroid Build Coastguard Worker #ifdef __GNUC__
8730*7c568831SAndroid Build Coastguard Worker     /*
8731*7c568831SAndroid Build Coastguard Worker      * tmp/temp is a workaround against a gcc compiler bug
8732*7c568831SAndroid Build Coastguard Worker      * http://veillard.com/gcc.bug
8733*7c568831SAndroid Build Coastguard Worker      */
8734*7c568831SAndroid Build Coastguard Worker     ret = 0;
8735*7c568831SAndroid Build Coastguard Worker     while ((*cur >= '0') && (*cur <= '9')) {
8736*7c568831SAndroid Build Coastguard Worker 	ret = ret * 10;
8737*7c568831SAndroid Build Coastguard Worker 	tmp = (*cur - '0');
8738*7c568831SAndroid Build Coastguard Worker 	ok = 1;
8739*7c568831SAndroid Build Coastguard Worker 	cur++;
8740*7c568831SAndroid Build Coastguard Worker 	temp = (double) tmp;
8741*7c568831SAndroid Build Coastguard Worker 	ret = ret + temp;
8742*7c568831SAndroid Build Coastguard Worker     }
8743*7c568831SAndroid Build Coastguard Worker #else
8744*7c568831SAndroid Build Coastguard Worker     ret = 0;
8745*7c568831SAndroid Build Coastguard Worker     while ((*cur >= '0') && (*cur <= '9')) {
8746*7c568831SAndroid Build Coastguard Worker 	ret = ret * 10 + (*cur - '0');
8747*7c568831SAndroid Build Coastguard Worker 	ok = 1;
8748*7c568831SAndroid Build Coastguard Worker 	cur++;
8749*7c568831SAndroid Build Coastguard Worker     }
8750*7c568831SAndroid Build Coastguard Worker #endif
8751*7c568831SAndroid Build Coastguard Worker 
8752*7c568831SAndroid Build Coastguard Worker     if (*cur == '.') {
8753*7c568831SAndroid Build Coastguard Worker 	int v, frac = 0, max;
8754*7c568831SAndroid Build Coastguard Worker 	double fraction = 0;
8755*7c568831SAndroid Build Coastguard Worker 
8756*7c568831SAndroid Build Coastguard Worker         cur++;
8757*7c568831SAndroid Build Coastguard Worker 	if (((*cur < '0') || (*cur > '9')) && (!ok)) {
8758*7c568831SAndroid Build Coastguard Worker 	    return(xmlXPathNAN);
8759*7c568831SAndroid Build Coastguard Worker 	}
8760*7c568831SAndroid Build Coastguard Worker         while (*cur == '0') {
8761*7c568831SAndroid Build Coastguard Worker 	    frac = frac + 1;
8762*7c568831SAndroid Build Coastguard Worker 	    cur++;
8763*7c568831SAndroid Build Coastguard Worker         }
8764*7c568831SAndroid Build Coastguard Worker         max = frac + MAX_FRAC;
8765*7c568831SAndroid Build Coastguard Worker 	while (((*cur >= '0') && (*cur <= '9')) && (frac < max)) {
8766*7c568831SAndroid Build Coastguard Worker 	    v = (*cur - '0');
8767*7c568831SAndroid Build Coastguard Worker 	    fraction = fraction * 10 + v;
8768*7c568831SAndroid Build Coastguard Worker 	    frac = frac + 1;
8769*7c568831SAndroid Build Coastguard Worker 	    cur++;
8770*7c568831SAndroid Build Coastguard Worker 	}
8771*7c568831SAndroid Build Coastguard Worker 	fraction /= pow(10.0, frac);
8772*7c568831SAndroid Build Coastguard Worker 	ret = ret + fraction;
8773*7c568831SAndroid Build Coastguard Worker 	while ((*cur >= '0') && (*cur <= '9'))
8774*7c568831SAndroid Build Coastguard Worker 	    cur++;
8775*7c568831SAndroid Build Coastguard Worker     }
8776*7c568831SAndroid Build Coastguard Worker     if ((*cur == 'e') || (*cur == 'E')) {
8777*7c568831SAndroid Build Coastguard Worker       cur++;
8778*7c568831SAndroid Build Coastguard Worker       if (*cur == '-') {
8779*7c568831SAndroid Build Coastguard Worker 	is_exponent_negative = 1;
8780*7c568831SAndroid Build Coastguard Worker 	cur++;
8781*7c568831SAndroid Build Coastguard Worker       } else if (*cur == '+') {
8782*7c568831SAndroid Build Coastguard Worker         cur++;
8783*7c568831SAndroid Build Coastguard Worker       }
8784*7c568831SAndroid Build Coastguard Worker       while ((*cur >= '0') && (*cur <= '9')) {
8785*7c568831SAndroid Build Coastguard Worker         if (exponent < 1000000)
8786*7c568831SAndroid Build Coastguard Worker 	  exponent = exponent * 10 + (*cur - '0');
8787*7c568831SAndroid Build Coastguard Worker 	cur++;
8788*7c568831SAndroid Build Coastguard Worker       }
8789*7c568831SAndroid Build Coastguard Worker     }
8790*7c568831SAndroid Build Coastguard Worker     while (IS_BLANK_CH(*cur)) cur++;
8791*7c568831SAndroid Build Coastguard Worker     if (*cur != 0) return(xmlXPathNAN);
8792*7c568831SAndroid Build Coastguard Worker     if (isneg) ret = -ret;
8793*7c568831SAndroid Build Coastguard Worker     if (is_exponent_negative) exponent = -exponent;
8794*7c568831SAndroid Build Coastguard Worker     ret *= pow(10.0, (double)exponent);
8795*7c568831SAndroid Build Coastguard Worker     return(ret);
8796*7c568831SAndroid Build Coastguard Worker }
8797*7c568831SAndroid Build Coastguard Worker 
8798*7c568831SAndroid Build Coastguard Worker /**
8799*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompNumber:
8800*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8801*7c568831SAndroid Build Coastguard Worker  *
8802*7c568831SAndroid Build Coastguard Worker  *  [30]   Number ::=   Digits ('.' Digits?)?
8803*7c568831SAndroid Build Coastguard Worker  *                    | '.' Digits
8804*7c568831SAndroid Build Coastguard Worker  *  [31]   Digits ::=   [0-9]+
8805*7c568831SAndroid Build Coastguard Worker  *
8806*7c568831SAndroid Build Coastguard Worker  * Compile a Number, then push it on the stack
8807*7c568831SAndroid Build Coastguard Worker  *
8808*7c568831SAndroid Build Coastguard Worker  */
8809*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)8810*7c568831SAndroid Build Coastguard Worker xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
8811*7c568831SAndroid Build Coastguard Worker {
8812*7c568831SAndroid Build Coastguard Worker     double ret = 0.0;
8813*7c568831SAndroid Build Coastguard Worker     int ok = 0;
8814*7c568831SAndroid Build Coastguard Worker     int exponent = 0;
8815*7c568831SAndroid Build Coastguard Worker     int is_exponent_negative = 0;
8816*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr num;
8817*7c568831SAndroid Build Coastguard Worker #ifdef __GNUC__
8818*7c568831SAndroid Build Coastguard Worker     unsigned long tmp = 0;
8819*7c568831SAndroid Build Coastguard Worker     double temp;
8820*7c568831SAndroid Build Coastguard Worker #endif
8821*7c568831SAndroid Build Coastguard Worker 
8822*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
8823*7c568831SAndroid Build Coastguard Worker     if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
8824*7c568831SAndroid Build Coastguard Worker         XP_ERROR(XPATH_NUMBER_ERROR);
8825*7c568831SAndroid Build Coastguard Worker     }
8826*7c568831SAndroid Build Coastguard Worker #ifdef __GNUC__
8827*7c568831SAndroid Build Coastguard Worker     /*
8828*7c568831SAndroid Build Coastguard Worker      * tmp/temp is a workaround against a gcc compiler bug
8829*7c568831SAndroid Build Coastguard Worker      * http://veillard.com/gcc.bug
8830*7c568831SAndroid Build Coastguard Worker      */
8831*7c568831SAndroid Build Coastguard Worker     ret = 0;
8832*7c568831SAndroid Build Coastguard Worker     while ((CUR >= '0') && (CUR <= '9')) {
8833*7c568831SAndroid Build Coastguard Worker 	ret = ret * 10;
8834*7c568831SAndroid Build Coastguard Worker 	tmp = (CUR - '0');
8835*7c568831SAndroid Build Coastguard Worker         ok = 1;
8836*7c568831SAndroid Build Coastguard Worker         NEXT;
8837*7c568831SAndroid Build Coastguard Worker 	temp = (double) tmp;
8838*7c568831SAndroid Build Coastguard Worker 	ret = ret + temp;
8839*7c568831SAndroid Build Coastguard Worker     }
8840*7c568831SAndroid Build Coastguard Worker #else
8841*7c568831SAndroid Build Coastguard Worker     ret = 0;
8842*7c568831SAndroid Build Coastguard Worker     while ((CUR >= '0') && (CUR <= '9')) {
8843*7c568831SAndroid Build Coastguard Worker 	ret = ret * 10 + (CUR - '0');
8844*7c568831SAndroid Build Coastguard Worker 	ok = 1;
8845*7c568831SAndroid Build Coastguard Worker 	NEXT;
8846*7c568831SAndroid Build Coastguard Worker     }
8847*7c568831SAndroid Build Coastguard Worker #endif
8848*7c568831SAndroid Build Coastguard Worker     if (CUR == '.') {
8849*7c568831SAndroid Build Coastguard Worker 	int v, frac = 0, max;
8850*7c568831SAndroid Build Coastguard Worker 	double fraction = 0;
8851*7c568831SAndroid Build Coastguard Worker 
8852*7c568831SAndroid Build Coastguard Worker         NEXT;
8853*7c568831SAndroid Build Coastguard Worker         if (((CUR < '0') || (CUR > '9')) && (!ok)) {
8854*7c568831SAndroid Build Coastguard Worker             XP_ERROR(XPATH_NUMBER_ERROR);
8855*7c568831SAndroid Build Coastguard Worker         }
8856*7c568831SAndroid Build Coastguard Worker         while (CUR == '0') {
8857*7c568831SAndroid Build Coastguard Worker             frac = frac + 1;
8858*7c568831SAndroid Build Coastguard Worker             NEXT;
8859*7c568831SAndroid Build Coastguard Worker         }
8860*7c568831SAndroid Build Coastguard Worker         max = frac + MAX_FRAC;
8861*7c568831SAndroid Build Coastguard Worker         while ((CUR >= '0') && (CUR <= '9') && (frac < max)) {
8862*7c568831SAndroid Build Coastguard Worker 	    v = (CUR - '0');
8863*7c568831SAndroid Build Coastguard Worker 	    fraction = fraction * 10 + v;
8864*7c568831SAndroid Build Coastguard Worker 	    frac = frac + 1;
8865*7c568831SAndroid Build Coastguard Worker             NEXT;
8866*7c568831SAndroid Build Coastguard Worker         }
8867*7c568831SAndroid Build Coastguard Worker         fraction /= pow(10.0, frac);
8868*7c568831SAndroid Build Coastguard Worker         ret = ret + fraction;
8869*7c568831SAndroid Build Coastguard Worker         while ((CUR >= '0') && (CUR <= '9'))
8870*7c568831SAndroid Build Coastguard Worker             NEXT;
8871*7c568831SAndroid Build Coastguard Worker     }
8872*7c568831SAndroid Build Coastguard Worker     if ((CUR == 'e') || (CUR == 'E')) {
8873*7c568831SAndroid Build Coastguard Worker         NEXT;
8874*7c568831SAndroid Build Coastguard Worker         if (CUR == '-') {
8875*7c568831SAndroid Build Coastguard Worker             is_exponent_negative = 1;
8876*7c568831SAndroid Build Coastguard Worker             NEXT;
8877*7c568831SAndroid Build Coastguard Worker         } else if (CUR == '+') {
8878*7c568831SAndroid Build Coastguard Worker 	    NEXT;
8879*7c568831SAndroid Build Coastguard Worker 	}
8880*7c568831SAndroid Build Coastguard Worker         while ((CUR >= '0') && (CUR <= '9')) {
8881*7c568831SAndroid Build Coastguard Worker             if (exponent < 1000000)
8882*7c568831SAndroid Build Coastguard Worker                 exponent = exponent * 10 + (CUR - '0');
8883*7c568831SAndroid Build Coastguard Worker             NEXT;
8884*7c568831SAndroid Build Coastguard Worker         }
8885*7c568831SAndroid Build Coastguard Worker         if (is_exponent_negative)
8886*7c568831SAndroid Build Coastguard Worker             exponent = -exponent;
8887*7c568831SAndroid Build Coastguard Worker         ret *= pow(10.0, (double) exponent);
8888*7c568831SAndroid Build Coastguard Worker     }
8889*7c568831SAndroid Build Coastguard Worker     num = xmlXPathCacheNewFloat(ctxt, ret);
8890*7c568831SAndroid Build Coastguard Worker     if (num == NULL) {
8891*7c568831SAndroid Build Coastguard Worker 	ctxt->error = XPATH_MEMORY_ERROR;
8892*7c568831SAndroid Build Coastguard Worker     } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, num,
8893*7c568831SAndroid Build Coastguard Worker                               NULL) == -1) {
8894*7c568831SAndroid Build Coastguard Worker         xmlXPathReleaseObject(ctxt->context, num);
8895*7c568831SAndroid Build Coastguard Worker     }
8896*7c568831SAndroid Build Coastguard Worker }
8897*7c568831SAndroid Build Coastguard Worker 
8898*7c568831SAndroid Build Coastguard Worker /**
8899*7c568831SAndroid Build Coastguard Worker  * xmlXPathParseLiteral:
8900*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8901*7c568831SAndroid Build Coastguard Worker  *
8902*7c568831SAndroid Build Coastguard Worker  * Parse a Literal
8903*7c568831SAndroid Build Coastguard Worker  *
8904*7c568831SAndroid Build Coastguard Worker  *  [29]   Literal ::=   '"' [^"]* '"'
8905*7c568831SAndroid Build Coastguard Worker  *                    | "'" [^']* "'"
8906*7c568831SAndroid Build Coastguard Worker  *
8907*7c568831SAndroid Build Coastguard Worker  * Returns the value found or NULL in case of error
8908*7c568831SAndroid Build Coastguard Worker  */
8909*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt)8910*7c568831SAndroid Build Coastguard Worker xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
8911*7c568831SAndroid Build Coastguard Worker     const xmlChar *q;
8912*7c568831SAndroid Build Coastguard Worker     xmlChar *ret = NULL;
8913*7c568831SAndroid Build Coastguard Worker     int quote;
8914*7c568831SAndroid Build Coastguard Worker 
8915*7c568831SAndroid Build Coastguard Worker     if (CUR == '"') {
8916*7c568831SAndroid Build Coastguard Worker         quote = '"';
8917*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '\'') {
8918*7c568831SAndroid Build Coastguard Worker         quote = '\'';
8919*7c568831SAndroid Build Coastguard Worker     } else {
8920*7c568831SAndroid Build Coastguard Worker 	XP_ERRORNULL(XPATH_START_LITERAL_ERROR);
8921*7c568831SAndroid Build Coastguard Worker     }
8922*7c568831SAndroid Build Coastguard Worker 
8923*7c568831SAndroid Build Coastguard Worker     NEXT;
8924*7c568831SAndroid Build Coastguard Worker     q = CUR_PTR;
8925*7c568831SAndroid Build Coastguard Worker     while (CUR != quote) {
8926*7c568831SAndroid Build Coastguard Worker         int ch;
8927*7c568831SAndroid Build Coastguard Worker         int len = 4;
8928*7c568831SAndroid Build Coastguard Worker 
8929*7c568831SAndroid Build Coastguard Worker         if (CUR == 0)
8930*7c568831SAndroid Build Coastguard Worker             XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
8931*7c568831SAndroid Build Coastguard Worker         ch = xmlGetUTF8Char(CUR_PTR, &len);
8932*7c568831SAndroid Build Coastguard Worker         if ((ch < 0) || (IS_CHAR(ch) == 0))
8933*7c568831SAndroid Build Coastguard Worker             XP_ERRORNULL(XPATH_INVALID_CHAR_ERROR);
8934*7c568831SAndroid Build Coastguard Worker         CUR_PTR += len;
8935*7c568831SAndroid Build Coastguard Worker     }
8936*7c568831SAndroid Build Coastguard Worker     ret = xmlStrndup(q, CUR_PTR - q);
8937*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
8938*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
8939*7c568831SAndroid Build Coastguard Worker     NEXT;
8940*7c568831SAndroid Build Coastguard Worker     return(ret);
8941*7c568831SAndroid Build Coastguard Worker }
8942*7c568831SAndroid Build Coastguard Worker 
8943*7c568831SAndroid Build Coastguard Worker /**
8944*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompLiteral:
8945*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8946*7c568831SAndroid Build Coastguard Worker  *
8947*7c568831SAndroid Build Coastguard Worker  * Parse a Literal and push it on the stack.
8948*7c568831SAndroid Build Coastguard Worker  *
8949*7c568831SAndroid Build Coastguard Worker  *  [29]   Literal ::=   '"' [^"]* '"'
8950*7c568831SAndroid Build Coastguard Worker  *                    | "'" [^']* "'"
8951*7c568831SAndroid Build Coastguard Worker  *
8952*7c568831SAndroid Build Coastguard Worker  * TODO: xmlXPathCompLiteral memory allocation could be improved.
8953*7c568831SAndroid Build Coastguard Worker  */
8954*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt)8955*7c568831SAndroid Build Coastguard Worker xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
8956*7c568831SAndroid Build Coastguard Worker     xmlChar *ret = NULL;
8957*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr lit;
8958*7c568831SAndroid Build Coastguard Worker 
8959*7c568831SAndroid Build Coastguard Worker     ret = xmlXPathParseLiteral(ctxt);
8960*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
8961*7c568831SAndroid Build Coastguard Worker         return;
8962*7c568831SAndroid Build Coastguard Worker     lit = xmlXPathCacheNewString(ctxt, ret);
8963*7c568831SAndroid Build Coastguard Worker     if (lit == NULL) {
8964*7c568831SAndroid Build Coastguard Worker         ctxt->error = XPATH_MEMORY_ERROR;
8965*7c568831SAndroid Build Coastguard Worker     } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, lit,
8966*7c568831SAndroid Build Coastguard Worker                               NULL) == -1) {
8967*7c568831SAndroid Build Coastguard Worker         xmlXPathReleaseObject(ctxt->context, lit);
8968*7c568831SAndroid Build Coastguard Worker     }
8969*7c568831SAndroid Build Coastguard Worker     xmlFree(ret);
8970*7c568831SAndroid Build Coastguard Worker }
8971*7c568831SAndroid Build Coastguard Worker 
8972*7c568831SAndroid Build Coastguard Worker /**
8973*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompVariableReference:
8974*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
8975*7c568831SAndroid Build Coastguard Worker  *
8976*7c568831SAndroid Build Coastguard Worker  * Parse a VariableReference, evaluate it and push it on the stack.
8977*7c568831SAndroid Build Coastguard Worker  *
8978*7c568831SAndroid Build Coastguard Worker  * The variable bindings consist of a mapping from variable names
8979*7c568831SAndroid Build Coastguard Worker  * to variable values. The value of a variable is an object, which can be
8980*7c568831SAndroid Build Coastguard Worker  * of any of the types that are possible for the value of an expression,
8981*7c568831SAndroid Build Coastguard Worker  * and may also be of additional types not specified here.
8982*7c568831SAndroid Build Coastguard Worker  *
8983*7c568831SAndroid Build Coastguard Worker  * Early evaluation is possible since:
8984*7c568831SAndroid Build Coastguard Worker  * The variable bindings [...] used to evaluate a subexpression are
8985*7c568831SAndroid Build Coastguard Worker  * always the same as those used to evaluate the containing expression.
8986*7c568831SAndroid Build Coastguard Worker  *
8987*7c568831SAndroid Build Coastguard Worker  *  [36]   VariableReference ::=   '$' QName
8988*7c568831SAndroid Build Coastguard Worker  */
8989*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt)8990*7c568831SAndroid Build Coastguard Worker xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
8991*7c568831SAndroid Build Coastguard Worker     xmlChar *name;
8992*7c568831SAndroid Build Coastguard Worker     xmlChar *prefix;
8993*7c568831SAndroid Build Coastguard Worker 
8994*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
8995*7c568831SAndroid Build Coastguard Worker     if (CUR != '$') {
8996*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
8997*7c568831SAndroid Build Coastguard Worker     }
8998*7c568831SAndroid Build Coastguard Worker     NEXT;
8999*7c568831SAndroid Build Coastguard Worker     name = xmlXPathParseQName(ctxt, &prefix);
9000*7c568831SAndroid Build Coastguard Worker     if (name == NULL) {
9001*7c568831SAndroid Build Coastguard Worker         xmlFree(prefix);
9002*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_VARIABLE_REF_ERROR);
9003*7c568831SAndroid Build Coastguard Worker     }
9004*7c568831SAndroid Build Coastguard Worker     ctxt->comp->last = -1;
9005*7c568831SAndroid Build Coastguard Worker     if (PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, name, prefix) == -1) {
9006*7c568831SAndroid Build Coastguard Worker         xmlFree(prefix);
9007*7c568831SAndroid Build Coastguard Worker         xmlFree(name);
9008*7c568831SAndroid Build Coastguard Worker     }
9009*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9010*7c568831SAndroid Build Coastguard Worker     if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
9011*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
9012*7c568831SAndroid Build Coastguard Worker     }
9013*7c568831SAndroid Build Coastguard Worker }
9014*7c568831SAndroid Build Coastguard Worker 
9015*7c568831SAndroid Build Coastguard Worker /**
9016*7c568831SAndroid Build Coastguard Worker  * xmlXPathIsNodeType:
9017*7c568831SAndroid Build Coastguard Worker  * @name:  a name string
9018*7c568831SAndroid Build Coastguard Worker  *
9019*7c568831SAndroid Build Coastguard Worker  * Is the name given a NodeType one.
9020*7c568831SAndroid Build Coastguard Worker  *
9021*7c568831SAndroid Build Coastguard Worker  *  [38]   NodeType ::=   'comment'
9022*7c568831SAndroid Build Coastguard Worker  *                    | 'text'
9023*7c568831SAndroid Build Coastguard Worker  *                    | 'processing-instruction'
9024*7c568831SAndroid Build Coastguard Worker  *                    | 'node'
9025*7c568831SAndroid Build Coastguard Worker  *
9026*7c568831SAndroid Build Coastguard Worker  * Returns 1 if true 0 otherwise
9027*7c568831SAndroid Build Coastguard Worker  */
9028*7c568831SAndroid Build Coastguard Worker int
xmlXPathIsNodeType(const xmlChar * name)9029*7c568831SAndroid Build Coastguard Worker xmlXPathIsNodeType(const xmlChar *name) {
9030*7c568831SAndroid Build Coastguard Worker     if (name == NULL)
9031*7c568831SAndroid Build Coastguard Worker 	return(0);
9032*7c568831SAndroid Build Coastguard Worker 
9033*7c568831SAndroid Build Coastguard Worker     if (xmlStrEqual(name, BAD_CAST "node"))
9034*7c568831SAndroid Build Coastguard Worker 	return(1);
9035*7c568831SAndroid Build Coastguard Worker     if (xmlStrEqual(name, BAD_CAST "text"))
9036*7c568831SAndroid Build Coastguard Worker 	return(1);
9037*7c568831SAndroid Build Coastguard Worker     if (xmlStrEqual(name, BAD_CAST "comment"))
9038*7c568831SAndroid Build Coastguard Worker 	return(1);
9039*7c568831SAndroid Build Coastguard Worker     if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
9040*7c568831SAndroid Build Coastguard Worker 	return(1);
9041*7c568831SAndroid Build Coastguard Worker     return(0);
9042*7c568831SAndroid Build Coastguard Worker }
9043*7c568831SAndroid Build Coastguard Worker 
9044*7c568831SAndroid Build Coastguard Worker /**
9045*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompFunctionCall:
9046*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9047*7c568831SAndroid Build Coastguard Worker  *
9048*7c568831SAndroid Build Coastguard Worker  *  [16]   FunctionCall ::=   FunctionName '(' ( Argument ( ',' Argument)*)? ')'
9049*7c568831SAndroid Build Coastguard Worker  *  [17]   Argument ::=   Expr
9050*7c568831SAndroid Build Coastguard Worker  *
9051*7c568831SAndroid Build Coastguard Worker  * Compile a function call, the evaluation of all arguments are
9052*7c568831SAndroid Build Coastguard Worker  * pushed on the stack
9053*7c568831SAndroid Build Coastguard Worker  */
9054*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt)9055*7c568831SAndroid Build Coastguard Worker xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
9056*7c568831SAndroid Build Coastguard Worker     xmlChar *name;
9057*7c568831SAndroid Build Coastguard Worker     xmlChar *prefix;
9058*7c568831SAndroid Build Coastguard Worker     int nbargs = 0;
9059*7c568831SAndroid Build Coastguard Worker     int sort = 1;
9060*7c568831SAndroid Build Coastguard Worker 
9061*7c568831SAndroid Build Coastguard Worker     name = xmlXPathParseQName(ctxt, &prefix);
9062*7c568831SAndroid Build Coastguard Worker     if (name == NULL) {
9063*7c568831SAndroid Build Coastguard Worker 	xmlFree(prefix);
9064*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_EXPR_ERROR);
9065*7c568831SAndroid Build Coastguard Worker     }
9066*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9067*7c568831SAndroid Build Coastguard Worker 
9068*7c568831SAndroid Build Coastguard Worker     if (CUR != '(') {
9069*7c568831SAndroid Build Coastguard Worker 	xmlFree(name);
9070*7c568831SAndroid Build Coastguard Worker 	xmlFree(prefix);
9071*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_EXPR_ERROR);
9072*7c568831SAndroid Build Coastguard Worker     }
9073*7c568831SAndroid Build Coastguard Worker     NEXT;
9074*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9075*7c568831SAndroid Build Coastguard Worker 
9076*7c568831SAndroid Build Coastguard Worker     /*
9077*7c568831SAndroid Build Coastguard Worker     * Optimization for count(): we don't need the node-set to be sorted.
9078*7c568831SAndroid Build Coastguard Worker     */
9079*7c568831SAndroid Build Coastguard Worker     if ((prefix == NULL) && (name[0] == 'c') &&
9080*7c568831SAndroid Build Coastguard Worker 	xmlStrEqual(name, BAD_CAST "count"))
9081*7c568831SAndroid Build Coastguard Worker     {
9082*7c568831SAndroid Build Coastguard Worker 	sort = 0;
9083*7c568831SAndroid Build Coastguard Worker     }
9084*7c568831SAndroid Build Coastguard Worker     ctxt->comp->last = -1;
9085*7c568831SAndroid Build Coastguard Worker     if (CUR != ')') {
9086*7c568831SAndroid Build Coastguard Worker 	while (CUR != 0) {
9087*7c568831SAndroid Build Coastguard Worker 	    int op1 = ctxt->comp->last;
9088*7c568831SAndroid Build Coastguard Worker 	    ctxt->comp->last = -1;
9089*7c568831SAndroid Build Coastguard Worker 	    xmlXPathCompileExpr(ctxt, sort);
9090*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->error != XPATH_EXPRESSION_OK) {
9091*7c568831SAndroid Build Coastguard Worker 		xmlFree(name);
9092*7c568831SAndroid Build Coastguard Worker 		xmlFree(prefix);
9093*7c568831SAndroid Build Coastguard Worker 		return;
9094*7c568831SAndroid Build Coastguard Worker 	    }
9095*7c568831SAndroid Build Coastguard Worker 	    PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
9096*7c568831SAndroid Build Coastguard Worker 	    nbargs++;
9097*7c568831SAndroid Build Coastguard Worker 	    if (CUR == ')') break;
9098*7c568831SAndroid Build Coastguard Worker 	    if (CUR != ',') {
9099*7c568831SAndroid Build Coastguard Worker 		xmlFree(name);
9100*7c568831SAndroid Build Coastguard Worker 		xmlFree(prefix);
9101*7c568831SAndroid Build Coastguard Worker 		XP_ERROR(XPATH_EXPR_ERROR);
9102*7c568831SAndroid Build Coastguard Worker 	    }
9103*7c568831SAndroid Build Coastguard Worker 	    NEXT;
9104*7c568831SAndroid Build Coastguard Worker 	    SKIP_BLANKS;
9105*7c568831SAndroid Build Coastguard Worker 	}
9106*7c568831SAndroid Build Coastguard Worker     }
9107*7c568831SAndroid Build Coastguard Worker     if (PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, name, prefix) == -1) {
9108*7c568831SAndroid Build Coastguard Worker         xmlFree(prefix);
9109*7c568831SAndroid Build Coastguard Worker         xmlFree(name);
9110*7c568831SAndroid Build Coastguard Worker     }
9111*7c568831SAndroid Build Coastguard Worker     NEXT;
9112*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9113*7c568831SAndroid Build Coastguard Worker }
9114*7c568831SAndroid Build Coastguard Worker 
9115*7c568831SAndroid Build Coastguard Worker /**
9116*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompPrimaryExpr:
9117*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9118*7c568831SAndroid Build Coastguard Worker  *
9119*7c568831SAndroid Build Coastguard Worker  *  [15]   PrimaryExpr ::=   VariableReference
9120*7c568831SAndroid Build Coastguard Worker  *                | '(' Expr ')'
9121*7c568831SAndroid Build Coastguard Worker  *                | Literal
9122*7c568831SAndroid Build Coastguard Worker  *                | Number
9123*7c568831SAndroid Build Coastguard Worker  *                | FunctionCall
9124*7c568831SAndroid Build Coastguard Worker  *
9125*7c568831SAndroid Build Coastguard Worker  * Compile a primary expression.
9126*7c568831SAndroid Build Coastguard Worker  */
9127*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt)9128*7c568831SAndroid Build Coastguard Worker xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) {
9129*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9130*7c568831SAndroid Build Coastguard Worker     if (CUR == '$') xmlXPathCompVariableReference(ctxt);
9131*7c568831SAndroid Build Coastguard Worker     else if (CUR == '(') {
9132*7c568831SAndroid Build Coastguard Worker 	NEXT;
9133*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9134*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompileExpr(ctxt, 1);
9135*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
9136*7c568831SAndroid Build Coastguard Worker 	if (CUR != ')') {
9137*7c568831SAndroid Build Coastguard Worker 	    XP_ERROR(XPATH_EXPR_ERROR);
9138*7c568831SAndroid Build Coastguard Worker 	}
9139*7c568831SAndroid Build Coastguard Worker 	NEXT;
9140*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9141*7c568831SAndroid Build Coastguard Worker     } else if (IS_ASCII_DIGIT(CUR) || (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
9142*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompNumber(ctxt);
9143*7c568831SAndroid Build Coastguard Worker     } else if ((CUR == '\'') || (CUR == '"')) {
9144*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompLiteral(ctxt);
9145*7c568831SAndroid Build Coastguard Worker     } else {
9146*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompFunctionCall(ctxt);
9147*7c568831SAndroid Build Coastguard Worker     }
9148*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9149*7c568831SAndroid Build Coastguard Worker }
9150*7c568831SAndroid Build Coastguard Worker 
9151*7c568831SAndroid Build Coastguard Worker /**
9152*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompFilterExpr:
9153*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9154*7c568831SAndroid Build Coastguard Worker  *
9155*7c568831SAndroid Build Coastguard Worker  *  [20]   FilterExpr ::=   PrimaryExpr
9156*7c568831SAndroid Build Coastguard Worker  *               | FilterExpr Predicate
9157*7c568831SAndroid Build Coastguard Worker  *
9158*7c568831SAndroid Build Coastguard Worker  * Compile a filter expression.
9159*7c568831SAndroid Build Coastguard Worker  * Square brackets are used to filter expressions in the same way that
9160*7c568831SAndroid Build Coastguard Worker  * they are used in location paths. It is an error if the expression to
9161*7c568831SAndroid Build Coastguard Worker  * be filtered does not evaluate to a node-set. The context node list
9162*7c568831SAndroid Build Coastguard Worker  * used for evaluating the expression in square brackets is the node-set
9163*7c568831SAndroid Build Coastguard Worker  * to be filtered listed in document order.
9164*7c568831SAndroid Build Coastguard Worker  */
9165*7c568831SAndroid Build Coastguard Worker 
9166*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt)9167*7c568831SAndroid Build Coastguard Worker xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
9168*7c568831SAndroid Build Coastguard Worker     xmlXPathCompPrimaryExpr(ctxt);
9169*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9170*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9171*7c568831SAndroid Build Coastguard Worker 
9172*7c568831SAndroid Build Coastguard Worker     while (CUR == '[') {
9173*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompPredicate(ctxt, 1);
9174*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9175*7c568831SAndroid Build Coastguard Worker     }
9176*7c568831SAndroid Build Coastguard Worker 
9177*7c568831SAndroid Build Coastguard Worker 
9178*7c568831SAndroid Build Coastguard Worker }
9179*7c568831SAndroid Build Coastguard Worker 
9180*7c568831SAndroid Build Coastguard Worker /**
9181*7c568831SAndroid Build Coastguard Worker  * xmlXPathScanName:
9182*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9183*7c568831SAndroid Build Coastguard Worker  *
9184*7c568831SAndroid Build Coastguard Worker  * Trickery: parse an XML name but without consuming the input flow
9185*7c568831SAndroid Build Coastguard Worker  * Needed to avoid insanity in the parser state.
9186*7c568831SAndroid Build Coastguard Worker  *
9187*7c568831SAndroid Build Coastguard Worker  * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
9188*7c568831SAndroid Build Coastguard Worker  *                  CombiningChar | Extender
9189*7c568831SAndroid Build Coastguard Worker  *
9190*7c568831SAndroid Build Coastguard Worker  * [5] Name ::= (Letter | '_' | ':') (NameChar)*
9191*7c568831SAndroid Build Coastguard Worker  *
9192*7c568831SAndroid Build Coastguard Worker  * [6] Names ::= Name (S Name)*
9193*7c568831SAndroid Build Coastguard Worker  *
9194*7c568831SAndroid Build Coastguard Worker  * Returns the Name parsed or NULL
9195*7c568831SAndroid Build Coastguard Worker  */
9196*7c568831SAndroid Build Coastguard Worker 
9197*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathScanName(xmlXPathParserContextPtr ctxt)9198*7c568831SAndroid Build Coastguard Worker xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
9199*7c568831SAndroid Build Coastguard Worker     int l;
9200*7c568831SAndroid Build Coastguard Worker     int c;
9201*7c568831SAndroid Build Coastguard Worker     const xmlChar *cur;
9202*7c568831SAndroid Build Coastguard Worker     xmlChar *ret;
9203*7c568831SAndroid Build Coastguard Worker 
9204*7c568831SAndroid Build Coastguard Worker     cur = ctxt->cur;
9205*7c568831SAndroid Build Coastguard Worker 
9206*7c568831SAndroid Build Coastguard Worker     c = CUR_CHAR(l);
9207*7c568831SAndroid Build Coastguard Worker     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
9208*7c568831SAndroid Build Coastguard Worker 	(!IS_LETTER(c) && (c != '_') &&
9209*7c568831SAndroid Build Coastguard Worker          (c != ':'))) {
9210*7c568831SAndroid Build Coastguard Worker 	return(NULL);
9211*7c568831SAndroid Build Coastguard Worker     }
9212*7c568831SAndroid Build Coastguard Worker 
9213*7c568831SAndroid Build Coastguard Worker     while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
9214*7c568831SAndroid Build Coastguard Worker 	   ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
9215*7c568831SAndroid Build Coastguard Worker             (c == '.') || (c == '-') ||
9216*7c568831SAndroid Build Coastguard Worker 	    (c == '_') || (c == ':') ||
9217*7c568831SAndroid Build Coastguard Worker 	    (IS_COMBINING(c)) ||
9218*7c568831SAndroid Build Coastguard Worker 	    (IS_EXTENDER(c)))) {
9219*7c568831SAndroid Build Coastguard Worker 	NEXTL(l);
9220*7c568831SAndroid Build Coastguard Worker 	c = CUR_CHAR(l);
9221*7c568831SAndroid Build Coastguard Worker     }
9222*7c568831SAndroid Build Coastguard Worker     ret = xmlStrndup(cur, ctxt->cur - cur);
9223*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
9224*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
9225*7c568831SAndroid Build Coastguard Worker     ctxt->cur = cur;
9226*7c568831SAndroid Build Coastguard Worker     return(ret);
9227*7c568831SAndroid Build Coastguard Worker }
9228*7c568831SAndroid Build Coastguard Worker 
9229*7c568831SAndroid Build Coastguard Worker /**
9230*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompPathExpr:
9231*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9232*7c568831SAndroid Build Coastguard Worker  *
9233*7c568831SAndroid Build Coastguard Worker  *  [19]   PathExpr ::=   LocationPath
9234*7c568831SAndroid Build Coastguard Worker  *               | FilterExpr
9235*7c568831SAndroid Build Coastguard Worker  *               | FilterExpr '/' RelativeLocationPath
9236*7c568831SAndroid Build Coastguard Worker  *               | FilterExpr '//' RelativeLocationPath
9237*7c568831SAndroid Build Coastguard Worker  *
9238*7c568831SAndroid Build Coastguard Worker  * Compile a path expression.
9239*7c568831SAndroid Build Coastguard Worker  * The / operator and // operators combine an arbitrary expression
9240*7c568831SAndroid Build Coastguard Worker  * and a relative location path. It is an error if the expression
9241*7c568831SAndroid Build Coastguard Worker  * does not evaluate to a node-set.
9242*7c568831SAndroid Build Coastguard Worker  * The / operator does composition in the same way as when / is
9243*7c568831SAndroid Build Coastguard Worker  * used in a location path. As in location paths, // is short for
9244*7c568831SAndroid Build Coastguard Worker  * /descendant-or-self::node()/.
9245*7c568831SAndroid Build Coastguard Worker  */
9246*7c568831SAndroid Build Coastguard Worker 
9247*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt)9248*7c568831SAndroid Build Coastguard Worker xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
9249*7c568831SAndroid Build Coastguard Worker     int lc = 1;           /* Should we branch to LocationPath ?         */
9250*7c568831SAndroid Build Coastguard Worker     xmlChar *name = NULL; /* we may have to preparse a name to find out */
9251*7c568831SAndroid Build Coastguard Worker 
9252*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9253*7c568831SAndroid Build Coastguard Worker     if ((CUR == '$') || (CUR == '(') ||
9254*7c568831SAndroid Build Coastguard Worker 	(IS_ASCII_DIGIT(CUR)) ||
9255*7c568831SAndroid Build Coastguard Worker         (CUR == '\'') || (CUR == '"') ||
9256*7c568831SAndroid Build Coastguard Worker 	(CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
9257*7c568831SAndroid Build Coastguard Worker 	lc = 0;
9258*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '*') {
9259*7c568831SAndroid Build Coastguard Worker 	/* relative or absolute location path */
9260*7c568831SAndroid Build Coastguard Worker 	lc = 1;
9261*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '/') {
9262*7c568831SAndroid Build Coastguard Worker 	/* relative or absolute location path */
9263*7c568831SAndroid Build Coastguard Worker 	lc = 1;
9264*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '@') {
9265*7c568831SAndroid Build Coastguard Worker 	/* relative abbreviated attribute location path */
9266*7c568831SAndroid Build Coastguard Worker 	lc = 1;
9267*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '.') {
9268*7c568831SAndroid Build Coastguard Worker 	/* relative abbreviated attribute location path */
9269*7c568831SAndroid Build Coastguard Worker 	lc = 1;
9270*7c568831SAndroid Build Coastguard Worker     } else {
9271*7c568831SAndroid Build Coastguard Worker 	/*
9272*7c568831SAndroid Build Coastguard Worker 	 * Problem is finding if we have a name here whether it's:
9273*7c568831SAndroid Build Coastguard Worker 	 *   - a nodetype
9274*7c568831SAndroid Build Coastguard Worker 	 *   - a function call in which case it's followed by '('
9275*7c568831SAndroid Build Coastguard Worker 	 *   - an axis in which case it's followed by ':'
9276*7c568831SAndroid Build Coastguard Worker 	 *   - a element name
9277*7c568831SAndroid Build Coastguard Worker 	 * We do an a priori analysis here rather than having to
9278*7c568831SAndroid Build Coastguard Worker 	 * maintain parsed token content through the recursive function
9279*7c568831SAndroid Build Coastguard Worker 	 * calls. This looks uglier but makes the code easier to
9280*7c568831SAndroid Build Coastguard Worker 	 * read/write/debug.
9281*7c568831SAndroid Build Coastguard Worker 	 */
9282*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9283*7c568831SAndroid Build Coastguard Worker 	name = xmlXPathScanName(ctxt);
9284*7c568831SAndroid Build Coastguard Worker 	if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
9285*7c568831SAndroid Build Coastguard Worker 	    lc = 1;
9286*7c568831SAndroid Build Coastguard Worker 	    xmlFree(name);
9287*7c568831SAndroid Build Coastguard Worker 	} else if (name != NULL) {
9288*7c568831SAndroid Build Coastguard Worker 	    int len =xmlStrlen(name);
9289*7c568831SAndroid Build Coastguard Worker 
9290*7c568831SAndroid Build Coastguard Worker 
9291*7c568831SAndroid Build Coastguard Worker 	    while (NXT(len) != 0) {
9292*7c568831SAndroid Build Coastguard Worker 		if (NXT(len) == '/') {
9293*7c568831SAndroid Build Coastguard Worker 		    /* element name */
9294*7c568831SAndroid Build Coastguard Worker 		    lc = 1;
9295*7c568831SAndroid Build Coastguard Worker 		    break;
9296*7c568831SAndroid Build Coastguard Worker 		} else if (IS_BLANK_CH(NXT(len))) {
9297*7c568831SAndroid Build Coastguard Worker 		    /* ignore blanks */
9298*7c568831SAndroid Build Coastguard Worker 		    ;
9299*7c568831SAndroid Build Coastguard Worker 		} else if (NXT(len) == ':') {
9300*7c568831SAndroid Build Coastguard Worker 		    lc = 1;
9301*7c568831SAndroid Build Coastguard Worker 		    break;
9302*7c568831SAndroid Build Coastguard Worker 		} else if ((NXT(len) == '(')) {
9303*7c568831SAndroid Build Coastguard Worker 		    /* Node Type or Function */
9304*7c568831SAndroid Build Coastguard Worker 		    if (xmlXPathIsNodeType(name)) {
9305*7c568831SAndroid Build Coastguard Worker 			lc = 1;
9306*7c568831SAndroid Build Coastguard Worker 		    } else {
9307*7c568831SAndroid Build Coastguard Worker 			lc = 0;
9308*7c568831SAndroid Build Coastguard Worker 		    }
9309*7c568831SAndroid Build Coastguard Worker                     break;
9310*7c568831SAndroid Build Coastguard Worker 		} else if ((NXT(len) == '[')) {
9311*7c568831SAndroid Build Coastguard Worker 		    /* element name */
9312*7c568831SAndroid Build Coastguard Worker 		    lc = 1;
9313*7c568831SAndroid Build Coastguard Worker 		    break;
9314*7c568831SAndroid Build Coastguard Worker 		} else if ((NXT(len) == '<') || (NXT(len) == '>') ||
9315*7c568831SAndroid Build Coastguard Worker 			   (NXT(len) == '=')) {
9316*7c568831SAndroid Build Coastguard Worker 		    lc = 1;
9317*7c568831SAndroid Build Coastguard Worker 		    break;
9318*7c568831SAndroid Build Coastguard Worker 		} else {
9319*7c568831SAndroid Build Coastguard Worker 		    lc = 1;
9320*7c568831SAndroid Build Coastguard Worker 		    break;
9321*7c568831SAndroid Build Coastguard Worker 		}
9322*7c568831SAndroid Build Coastguard Worker 		len++;
9323*7c568831SAndroid Build Coastguard Worker 	    }
9324*7c568831SAndroid Build Coastguard Worker 	    if (NXT(len) == 0) {
9325*7c568831SAndroid Build Coastguard Worker 		/* element name */
9326*7c568831SAndroid Build Coastguard Worker 		lc = 1;
9327*7c568831SAndroid Build Coastguard Worker 	    }
9328*7c568831SAndroid Build Coastguard Worker 	    xmlFree(name);
9329*7c568831SAndroid Build Coastguard Worker 	} else {
9330*7c568831SAndroid Build Coastguard Worker 	    /* make sure all cases are covered explicitly */
9331*7c568831SAndroid Build Coastguard Worker 	    XP_ERROR(XPATH_EXPR_ERROR);
9332*7c568831SAndroid Build Coastguard Worker 	}
9333*7c568831SAndroid Build Coastguard Worker     }
9334*7c568831SAndroid Build Coastguard Worker 
9335*7c568831SAndroid Build Coastguard Worker     if (lc) {
9336*7c568831SAndroid Build Coastguard Worker 	if (CUR == '/') {
9337*7c568831SAndroid Build Coastguard Worker 	    PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0);
9338*7c568831SAndroid Build Coastguard Worker 	} else {
9339*7c568831SAndroid Build Coastguard Worker 	    PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
9340*7c568831SAndroid Build Coastguard Worker 	}
9341*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompLocationPath(ctxt);
9342*7c568831SAndroid Build Coastguard Worker     } else {
9343*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompFilterExpr(ctxt);
9344*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
9345*7c568831SAndroid Build Coastguard Worker 	if ((CUR == '/') && (NXT(1) == '/')) {
9346*7c568831SAndroid Build Coastguard Worker 	    SKIP(2);
9347*7c568831SAndroid Build Coastguard Worker 	    SKIP_BLANKS;
9348*7c568831SAndroid Build Coastguard Worker 
9349*7c568831SAndroid Build Coastguard Worker 	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
9350*7c568831SAndroid Build Coastguard Worker 		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9351*7c568831SAndroid Build Coastguard Worker 
9352*7c568831SAndroid Build Coastguard Worker 	    xmlXPathCompRelativeLocationPath(ctxt);
9353*7c568831SAndroid Build Coastguard Worker 	} else if (CUR == '/') {
9354*7c568831SAndroid Build Coastguard Worker 	    xmlXPathCompRelativeLocationPath(ctxt);
9355*7c568831SAndroid Build Coastguard Worker 	}
9356*7c568831SAndroid Build Coastguard Worker     }
9357*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9358*7c568831SAndroid Build Coastguard Worker }
9359*7c568831SAndroid Build Coastguard Worker 
9360*7c568831SAndroid Build Coastguard Worker /**
9361*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompUnionExpr:
9362*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9363*7c568831SAndroid Build Coastguard Worker  *
9364*7c568831SAndroid Build Coastguard Worker  *  [18]   UnionExpr ::=   PathExpr
9365*7c568831SAndroid Build Coastguard Worker  *               | UnionExpr '|' PathExpr
9366*7c568831SAndroid Build Coastguard Worker  *
9367*7c568831SAndroid Build Coastguard Worker  * Compile an union expression.
9368*7c568831SAndroid Build Coastguard Worker  */
9369*7c568831SAndroid Build Coastguard Worker 
9370*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt)9371*7c568831SAndroid Build Coastguard Worker xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) {
9372*7c568831SAndroid Build Coastguard Worker     xmlXPathCompPathExpr(ctxt);
9373*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9374*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9375*7c568831SAndroid Build Coastguard Worker     while (CUR == '|') {
9376*7c568831SAndroid Build Coastguard Worker 	int op1 = ctxt->comp->last;
9377*7c568831SAndroid Build Coastguard Worker 	PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
9378*7c568831SAndroid Build Coastguard Worker 
9379*7c568831SAndroid Build Coastguard Worker 	NEXT;
9380*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9381*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompPathExpr(ctxt);
9382*7c568831SAndroid Build Coastguard Worker 
9383*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0);
9384*7c568831SAndroid Build Coastguard Worker 
9385*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9386*7c568831SAndroid Build Coastguard Worker     }
9387*7c568831SAndroid Build Coastguard Worker }
9388*7c568831SAndroid Build Coastguard Worker 
9389*7c568831SAndroid Build Coastguard Worker /**
9390*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompUnaryExpr:
9391*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9392*7c568831SAndroid Build Coastguard Worker  *
9393*7c568831SAndroid Build Coastguard Worker  *  [27]   UnaryExpr ::=   UnionExpr
9394*7c568831SAndroid Build Coastguard Worker  *                   | '-' UnaryExpr
9395*7c568831SAndroid Build Coastguard Worker  *
9396*7c568831SAndroid Build Coastguard Worker  * Compile an unary expression.
9397*7c568831SAndroid Build Coastguard Worker  */
9398*7c568831SAndroid Build Coastguard Worker 
9399*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt)9400*7c568831SAndroid Build Coastguard Worker xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) {
9401*7c568831SAndroid Build Coastguard Worker     int minus = 0;
9402*7c568831SAndroid Build Coastguard Worker     int found = 0;
9403*7c568831SAndroid Build Coastguard Worker 
9404*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9405*7c568831SAndroid Build Coastguard Worker     while (CUR == '-') {
9406*7c568831SAndroid Build Coastguard Worker         minus = 1 - minus;
9407*7c568831SAndroid Build Coastguard Worker 	found = 1;
9408*7c568831SAndroid Build Coastguard Worker 	NEXT;
9409*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9410*7c568831SAndroid Build Coastguard Worker     }
9411*7c568831SAndroid Build Coastguard Worker 
9412*7c568831SAndroid Build Coastguard Worker     xmlXPathCompUnionExpr(ctxt);
9413*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9414*7c568831SAndroid Build Coastguard Worker     if (found) {
9415*7c568831SAndroid Build Coastguard Worker 	if (minus)
9416*7c568831SAndroid Build Coastguard Worker 	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0);
9417*7c568831SAndroid Build Coastguard Worker 	else
9418*7c568831SAndroid Build Coastguard Worker 	    PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0);
9419*7c568831SAndroid Build Coastguard Worker     }
9420*7c568831SAndroid Build Coastguard Worker }
9421*7c568831SAndroid Build Coastguard Worker 
9422*7c568831SAndroid Build Coastguard Worker /**
9423*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompMultiplicativeExpr:
9424*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9425*7c568831SAndroid Build Coastguard Worker  *
9426*7c568831SAndroid Build Coastguard Worker  *  [26]   MultiplicativeExpr ::=   UnaryExpr
9427*7c568831SAndroid Build Coastguard Worker  *                   | MultiplicativeExpr MultiplyOperator UnaryExpr
9428*7c568831SAndroid Build Coastguard Worker  *                   | MultiplicativeExpr 'div' UnaryExpr
9429*7c568831SAndroid Build Coastguard Worker  *                   | MultiplicativeExpr 'mod' UnaryExpr
9430*7c568831SAndroid Build Coastguard Worker  *  [34]   MultiplyOperator ::=   '*'
9431*7c568831SAndroid Build Coastguard Worker  *
9432*7c568831SAndroid Build Coastguard Worker  * Compile an Additive expression.
9433*7c568831SAndroid Build Coastguard Worker  */
9434*7c568831SAndroid Build Coastguard Worker 
9435*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt)9436*7c568831SAndroid Build Coastguard Worker xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) {
9437*7c568831SAndroid Build Coastguard Worker     xmlXPathCompUnaryExpr(ctxt);
9438*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9439*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9440*7c568831SAndroid Build Coastguard Worker     while ((CUR == '*') ||
9441*7c568831SAndroid Build Coastguard Worker            ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) ||
9442*7c568831SAndroid Build Coastguard Worker            ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) {
9443*7c568831SAndroid Build Coastguard Worker 	int op = -1;
9444*7c568831SAndroid Build Coastguard Worker 	int op1 = ctxt->comp->last;
9445*7c568831SAndroid Build Coastguard Worker 
9446*7c568831SAndroid Build Coastguard Worker         if (CUR == '*') {
9447*7c568831SAndroid Build Coastguard Worker 	    op = 0;
9448*7c568831SAndroid Build Coastguard Worker 	    NEXT;
9449*7c568831SAndroid Build Coastguard Worker 	} else if (CUR == 'd') {
9450*7c568831SAndroid Build Coastguard Worker 	    op = 1;
9451*7c568831SAndroid Build Coastguard Worker 	    SKIP(3);
9452*7c568831SAndroid Build Coastguard Worker 	} else if (CUR == 'm') {
9453*7c568831SAndroid Build Coastguard Worker 	    op = 2;
9454*7c568831SAndroid Build Coastguard Worker 	    SKIP(3);
9455*7c568831SAndroid Build Coastguard Worker 	}
9456*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9457*7c568831SAndroid Build Coastguard Worker         xmlXPathCompUnaryExpr(ctxt);
9458*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
9459*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0);
9460*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9461*7c568831SAndroid Build Coastguard Worker     }
9462*7c568831SAndroid Build Coastguard Worker }
9463*7c568831SAndroid Build Coastguard Worker 
9464*7c568831SAndroid Build Coastguard Worker /**
9465*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompAdditiveExpr:
9466*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9467*7c568831SAndroid Build Coastguard Worker  *
9468*7c568831SAndroid Build Coastguard Worker  *  [25]   AdditiveExpr ::=   MultiplicativeExpr
9469*7c568831SAndroid Build Coastguard Worker  *                   | AdditiveExpr '+' MultiplicativeExpr
9470*7c568831SAndroid Build Coastguard Worker  *                   | AdditiveExpr '-' MultiplicativeExpr
9471*7c568831SAndroid Build Coastguard Worker  *
9472*7c568831SAndroid Build Coastguard Worker  * Compile an Additive expression.
9473*7c568831SAndroid Build Coastguard Worker  */
9474*7c568831SAndroid Build Coastguard Worker 
9475*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt)9476*7c568831SAndroid Build Coastguard Worker xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) {
9477*7c568831SAndroid Build Coastguard Worker 
9478*7c568831SAndroid Build Coastguard Worker     xmlXPathCompMultiplicativeExpr(ctxt);
9479*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9480*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9481*7c568831SAndroid Build Coastguard Worker     while ((CUR == '+') || (CUR == '-')) {
9482*7c568831SAndroid Build Coastguard Worker 	int plus;
9483*7c568831SAndroid Build Coastguard Worker 	int op1 = ctxt->comp->last;
9484*7c568831SAndroid Build Coastguard Worker 
9485*7c568831SAndroid Build Coastguard Worker         if (CUR == '+') plus = 1;
9486*7c568831SAndroid Build Coastguard Worker 	else plus = 0;
9487*7c568831SAndroid Build Coastguard Worker 	NEXT;
9488*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9489*7c568831SAndroid Build Coastguard Worker         xmlXPathCompMultiplicativeExpr(ctxt);
9490*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
9491*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0);
9492*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9493*7c568831SAndroid Build Coastguard Worker     }
9494*7c568831SAndroid Build Coastguard Worker }
9495*7c568831SAndroid Build Coastguard Worker 
9496*7c568831SAndroid Build Coastguard Worker /**
9497*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompRelationalExpr:
9498*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9499*7c568831SAndroid Build Coastguard Worker  *
9500*7c568831SAndroid Build Coastguard Worker  *  [24]   RelationalExpr ::=   AdditiveExpr
9501*7c568831SAndroid Build Coastguard Worker  *                 | RelationalExpr '<' AdditiveExpr
9502*7c568831SAndroid Build Coastguard Worker  *                 | RelationalExpr '>' AdditiveExpr
9503*7c568831SAndroid Build Coastguard Worker  *                 | RelationalExpr '<=' AdditiveExpr
9504*7c568831SAndroid Build Coastguard Worker  *                 | RelationalExpr '>=' AdditiveExpr
9505*7c568831SAndroid Build Coastguard Worker  *
9506*7c568831SAndroid Build Coastguard Worker  *  A <= B > C is allowed ? Answer from James, yes with
9507*7c568831SAndroid Build Coastguard Worker  *  (AdditiveExpr <= AdditiveExpr) > AdditiveExpr
9508*7c568831SAndroid Build Coastguard Worker  *  which is basically what got implemented.
9509*7c568831SAndroid Build Coastguard Worker  *
9510*7c568831SAndroid Build Coastguard Worker  * Compile a Relational expression, then push the result
9511*7c568831SAndroid Build Coastguard Worker  * on the stack
9512*7c568831SAndroid Build Coastguard Worker  */
9513*7c568831SAndroid Build Coastguard Worker 
9514*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt)9515*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) {
9516*7c568831SAndroid Build Coastguard Worker     xmlXPathCompAdditiveExpr(ctxt);
9517*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9518*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9519*7c568831SAndroid Build Coastguard Worker     while ((CUR == '<') || (CUR == '>')) {
9520*7c568831SAndroid Build Coastguard Worker 	int inf, strict;
9521*7c568831SAndroid Build Coastguard Worker 	int op1 = ctxt->comp->last;
9522*7c568831SAndroid Build Coastguard Worker 
9523*7c568831SAndroid Build Coastguard Worker         if (CUR == '<') inf = 1;
9524*7c568831SAndroid Build Coastguard Worker 	else inf = 0;
9525*7c568831SAndroid Build Coastguard Worker 	if (NXT(1) == '=') strict = 0;
9526*7c568831SAndroid Build Coastguard Worker 	else strict = 1;
9527*7c568831SAndroid Build Coastguard Worker 	NEXT;
9528*7c568831SAndroid Build Coastguard Worker 	if (!strict) NEXT;
9529*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9530*7c568831SAndroid Build Coastguard Worker         xmlXPathCompAdditiveExpr(ctxt);
9531*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
9532*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict);
9533*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9534*7c568831SAndroid Build Coastguard Worker     }
9535*7c568831SAndroid Build Coastguard Worker }
9536*7c568831SAndroid Build Coastguard Worker 
9537*7c568831SAndroid Build Coastguard Worker /**
9538*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompEqualityExpr:
9539*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9540*7c568831SAndroid Build Coastguard Worker  *
9541*7c568831SAndroid Build Coastguard Worker  *  [23]   EqualityExpr ::=   RelationalExpr
9542*7c568831SAndroid Build Coastguard Worker  *                 | EqualityExpr '=' RelationalExpr
9543*7c568831SAndroid Build Coastguard Worker  *                 | EqualityExpr '!=' RelationalExpr
9544*7c568831SAndroid Build Coastguard Worker  *
9545*7c568831SAndroid Build Coastguard Worker  *  A != B != C is allowed ? Answer from James, yes with
9546*7c568831SAndroid Build Coastguard Worker  *  (RelationalExpr = RelationalExpr) = RelationalExpr
9547*7c568831SAndroid Build Coastguard Worker  *  (RelationalExpr != RelationalExpr) != RelationalExpr
9548*7c568831SAndroid Build Coastguard Worker  *  which is basically what got implemented.
9549*7c568831SAndroid Build Coastguard Worker  *
9550*7c568831SAndroid Build Coastguard Worker  * Compile an Equality expression.
9551*7c568831SAndroid Build Coastguard Worker  *
9552*7c568831SAndroid Build Coastguard Worker  */
9553*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt)9554*7c568831SAndroid Build Coastguard Worker xmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) {
9555*7c568831SAndroid Build Coastguard Worker     xmlXPathCompRelationalExpr(ctxt);
9556*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9557*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9558*7c568831SAndroid Build Coastguard Worker     while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) {
9559*7c568831SAndroid Build Coastguard Worker 	int eq;
9560*7c568831SAndroid Build Coastguard Worker 	int op1 = ctxt->comp->last;
9561*7c568831SAndroid Build Coastguard Worker 
9562*7c568831SAndroid Build Coastguard Worker         if (CUR == '=') eq = 1;
9563*7c568831SAndroid Build Coastguard Worker 	else eq = 0;
9564*7c568831SAndroid Build Coastguard Worker 	NEXT;
9565*7c568831SAndroid Build Coastguard Worker 	if (!eq) NEXT;
9566*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9567*7c568831SAndroid Build Coastguard Worker         xmlXPathCompRelationalExpr(ctxt);
9568*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
9569*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0);
9570*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9571*7c568831SAndroid Build Coastguard Worker     }
9572*7c568831SAndroid Build Coastguard Worker }
9573*7c568831SAndroid Build Coastguard Worker 
9574*7c568831SAndroid Build Coastguard Worker /**
9575*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompAndExpr:
9576*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9577*7c568831SAndroid Build Coastguard Worker  *
9578*7c568831SAndroid Build Coastguard Worker  *  [22]   AndExpr ::=   EqualityExpr
9579*7c568831SAndroid Build Coastguard Worker  *                 | AndExpr 'and' EqualityExpr
9580*7c568831SAndroid Build Coastguard Worker  *
9581*7c568831SAndroid Build Coastguard Worker  * Compile an AND expression.
9582*7c568831SAndroid Build Coastguard Worker  *
9583*7c568831SAndroid Build Coastguard Worker  */
9584*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt)9585*7c568831SAndroid Build Coastguard Worker xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) {
9586*7c568831SAndroid Build Coastguard Worker     xmlXPathCompEqualityExpr(ctxt);
9587*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9588*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9589*7c568831SAndroid Build Coastguard Worker     while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
9590*7c568831SAndroid Build Coastguard Worker 	int op1 = ctxt->comp->last;
9591*7c568831SAndroid Build Coastguard Worker         SKIP(3);
9592*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9593*7c568831SAndroid Build Coastguard Worker         xmlXPathCompEqualityExpr(ctxt);
9594*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
9595*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0);
9596*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9597*7c568831SAndroid Build Coastguard Worker     }
9598*7c568831SAndroid Build Coastguard Worker }
9599*7c568831SAndroid Build Coastguard Worker 
9600*7c568831SAndroid Build Coastguard Worker /**
9601*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompileExpr:
9602*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9603*7c568831SAndroid Build Coastguard Worker  *
9604*7c568831SAndroid Build Coastguard Worker  *  [14]   Expr ::=   OrExpr
9605*7c568831SAndroid Build Coastguard Worker  *  [21]   OrExpr ::=   AndExpr
9606*7c568831SAndroid Build Coastguard Worker  *                 | OrExpr 'or' AndExpr
9607*7c568831SAndroid Build Coastguard Worker  *
9608*7c568831SAndroid Build Coastguard Worker  * Parse and compile an expression
9609*7c568831SAndroid Build Coastguard Worker  */
9610*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt,int sort)9611*7c568831SAndroid Build Coastguard Worker xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
9612*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr xpctxt = ctxt->context;
9613*7c568831SAndroid Build Coastguard Worker 
9614*7c568831SAndroid Build Coastguard Worker     if (xpctxt != NULL) {
9615*7c568831SAndroid Build Coastguard Worker         if (xpctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
9616*7c568831SAndroid Build Coastguard Worker             XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
9617*7c568831SAndroid Build Coastguard Worker         /*
9618*7c568831SAndroid Build Coastguard Worker          * Parsing a single '(' pushes about 10 functions on the call stack
9619*7c568831SAndroid Build Coastguard Worker          * before recursing!
9620*7c568831SAndroid Build Coastguard Worker          */
9621*7c568831SAndroid Build Coastguard Worker         xpctxt->depth += 10;
9622*7c568831SAndroid Build Coastguard Worker     }
9623*7c568831SAndroid Build Coastguard Worker 
9624*7c568831SAndroid Build Coastguard Worker     xmlXPathCompAndExpr(ctxt);
9625*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9626*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9627*7c568831SAndroid Build Coastguard Worker     while ((CUR == 'o') && (NXT(1) == 'r')) {
9628*7c568831SAndroid Build Coastguard Worker 	int op1 = ctxt->comp->last;
9629*7c568831SAndroid Build Coastguard Worker         SKIP(2);
9630*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9631*7c568831SAndroid Build Coastguard Worker         xmlXPathCompAndExpr(ctxt);
9632*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
9633*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0);
9634*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9635*7c568831SAndroid Build Coastguard Worker     }
9636*7c568831SAndroid Build Coastguard Worker     if ((sort) && (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE)) {
9637*7c568831SAndroid Build Coastguard Worker 	/* more ops could be optimized too */
9638*7c568831SAndroid Build Coastguard Worker 	/*
9639*7c568831SAndroid Build Coastguard Worker 	* This is the main place to eliminate sorting for
9640*7c568831SAndroid Build Coastguard Worker 	* operations which don't require a sorted node-set.
9641*7c568831SAndroid Build Coastguard Worker 	* E.g. count().
9642*7c568831SAndroid Build Coastguard Worker 	*/
9643*7c568831SAndroid Build Coastguard Worker 	PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0);
9644*7c568831SAndroid Build Coastguard Worker     }
9645*7c568831SAndroid Build Coastguard Worker 
9646*7c568831SAndroid Build Coastguard Worker     if (xpctxt != NULL)
9647*7c568831SAndroid Build Coastguard Worker         xpctxt->depth -= 10;
9648*7c568831SAndroid Build Coastguard Worker }
9649*7c568831SAndroid Build Coastguard Worker 
9650*7c568831SAndroid Build Coastguard Worker /**
9651*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompPredicate:
9652*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9653*7c568831SAndroid Build Coastguard Worker  * @filter:  act as a filter
9654*7c568831SAndroid Build Coastguard Worker  *
9655*7c568831SAndroid Build Coastguard Worker  *  [8]   Predicate ::=   '[' PredicateExpr ']'
9656*7c568831SAndroid Build Coastguard Worker  *  [9]   PredicateExpr ::=   Expr
9657*7c568831SAndroid Build Coastguard Worker  *
9658*7c568831SAndroid Build Coastguard Worker  * Compile a predicate expression
9659*7c568831SAndroid Build Coastguard Worker  */
9660*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt,int filter)9661*7c568831SAndroid Build Coastguard Worker xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
9662*7c568831SAndroid Build Coastguard Worker     int op1 = ctxt->comp->last;
9663*7c568831SAndroid Build Coastguard Worker 
9664*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9665*7c568831SAndroid Build Coastguard Worker     if (CUR != '[') {
9666*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
9667*7c568831SAndroid Build Coastguard Worker     }
9668*7c568831SAndroid Build Coastguard Worker     NEXT;
9669*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9670*7c568831SAndroid Build Coastguard Worker 
9671*7c568831SAndroid Build Coastguard Worker     ctxt->comp->last = -1;
9672*7c568831SAndroid Build Coastguard Worker     /*
9673*7c568831SAndroid Build Coastguard Worker     * This call to xmlXPathCompileExpr() will deactivate sorting
9674*7c568831SAndroid Build Coastguard Worker     * of the predicate result.
9675*7c568831SAndroid Build Coastguard Worker     * TODO: Sorting is still activated for filters, since I'm not
9676*7c568831SAndroid Build Coastguard Worker     *  sure if needed. Normally sorting should not be needed, since
9677*7c568831SAndroid Build Coastguard Worker     *  a filter can only diminish the number of items in a sequence,
9678*7c568831SAndroid Build Coastguard Worker     *  but won't change its order; so if the initial sequence is sorted,
9679*7c568831SAndroid Build Coastguard Worker     *  subsequent sorting is not needed.
9680*7c568831SAndroid Build Coastguard Worker     */
9681*7c568831SAndroid Build Coastguard Worker     if (! filter)
9682*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompileExpr(ctxt, 0);
9683*7c568831SAndroid Build Coastguard Worker     else
9684*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompileExpr(ctxt, 1);
9685*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
9686*7c568831SAndroid Build Coastguard Worker 
9687*7c568831SAndroid Build Coastguard Worker     if (CUR != ']') {
9688*7c568831SAndroid Build Coastguard Worker 	XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
9689*7c568831SAndroid Build Coastguard Worker     }
9690*7c568831SAndroid Build Coastguard Worker 
9691*7c568831SAndroid Build Coastguard Worker     if (filter)
9692*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
9693*7c568831SAndroid Build Coastguard Worker     else
9694*7c568831SAndroid Build Coastguard Worker 	PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
9695*7c568831SAndroid Build Coastguard Worker 
9696*7c568831SAndroid Build Coastguard Worker     NEXT;
9697*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9698*7c568831SAndroid Build Coastguard Worker }
9699*7c568831SAndroid Build Coastguard Worker 
9700*7c568831SAndroid Build Coastguard Worker /**
9701*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompNodeTest:
9702*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9703*7c568831SAndroid Build Coastguard Worker  * @test:  pointer to a xmlXPathTestVal
9704*7c568831SAndroid Build Coastguard Worker  * @type:  pointer to a xmlXPathTypeVal
9705*7c568831SAndroid Build Coastguard Worker  * @prefix:  placeholder for a possible name prefix
9706*7c568831SAndroid Build Coastguard Worker  *
9707*7c568831SAndroid Build Coastguard Worker  * [7] NodeTest ::=   NameTest
9708*7c568831SAndroid Build Coastguard Worker  *		    | NodeType '(' ')'
9709*7c568831SAndroid Build Coastguard Worker  *		    | 'processing-instruction' '(' Literal ')'
9710*7c568831SAndroid Build Coastguard Worker  *
9711*7c568831SAndroid Build Coastguard Worker  * [37] NameTest ::=  '*'
9712*7c568831SAndroid Build Coastguard Worker  *		    | NCName ':' '*'
9713*7c568831SAndroid Build Coastguard Worker  *		    | QName
9714*7c568831SAndroid Build Coastguard Worker  * [38] NodeType ::= 'comment'
9715*7c568831SAndroid Build Coastguard Worker  *		   | 'text'
9716*7c568831SAndroid Build Coastguard Worker  *		   | 'processing-instruction'
9717*7c568831SAndroid Build Coastguard Worker  *		   | 'node'
9718*7c568831SAndroid Build Coastguard Worker  *
9719*7c568831SAndroid Build Coastguard Worker  * Returns the name found and updates @test, @type and @prefix appropriately
9720*7c568831SAndroid Build Coastguard Worker  */
9721*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt,xmlXPathTestVal * test,xmlXPathTypeVal * type,xmlChar ** prefix,xmlChar * name)9722*7c568831SAndroid Build Coastguard Worker xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
9723*7c568831SAndroid Build Coastguard Worker 	             xmlXPathTypeVal *type, xmlChar **prefix,
9724*7c568831SAndroid Build Coastguard Worker 		     xmlChar *name) {
9725*7c568831SAndroid Build Coastguard Worker     int blanks;
9726*7c568831SAndroid Build Coastguard Worker 
9727*7c568831SAndroid Build Coastguard Worker     if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
9728*7c568831SAndroid Build Coastguard Worker 	return(NULL);
9729*7c568831SAndroid Build Coastguard Worker     }
9730*7c568831SAndroid Build Coastguard Worker     *type = (xmlXPathTypeVal) 0;
9731*7c568831SAndroid Build Coastguard Worker     *test = (xmlXPathTestVal) 0;
9732*7c568831SAndroid Build Coastguard Worker     *prefix = NULL;
9733*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9734*7c568831SAndroid Build Coastguard Worker 
9735*7c568831SAndroid Build Coastguard Worker     if ((name == NULL) && (CUR == '*')) {
9736*7c568831SAndroid Build Coastguard Worker 	/*
9737*7c568831SAndroid Build Coastguard Worker 	 * All elements
9738*7c568831SAndroid Build Coastguard Worker 	 */
9739*7c568831SAndroid Build Coastguard Worker 	NEXT;
9740*7c568831SAndroid Build Coastguard Worker 	*test = NODE_TEST_ALL;
9741*7c568831SAndroid Build Coastguard Worker 	return(NULL);
9742*7c568831SAndroid Build Coastguard Worker     }
9743*7c568831SAndroid Build Coastguard Worker 
9744*7c568831SAndroid Build Coastguard Worker     if (name == NULL)
9745*7c568831SAndroid Build Coastguard Worker 	name = xmlXPathParseNCName(ctxt);
9746*7c568831SAndroid Build Coastguard Worker     if (name == NULL) {
9747*7c568831SAndroid Build Coastguard Worker 	XP_ERRORNULL(XPATH_EXPR_ERROR);
9748*7c568831SAndroid Build Coastguard Worker     }
9749*7c568831SAndroid Build Coastguard Worker 
9750*7c568831SAndroid Build Coastguard Worker     blanks = IS_BLANK_CH(CUR);
9751*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9752*7c568831SAndroid Build Coastguard Worker     if (CUR == '(') {
9753*7c568831SAndroid Build Coastguard Worker 	NEXT;
9754*7c568831SAndroid Build Coastguard Worker 	/*
9755*7c568831SAndroid Build Coastguard Worker 	 * NodeType or PI search
9756*7c568831SAndroid Build Coastguard Worker 	 */
9757*7c568831SAndroid Build Coastguard Worker 	if (xmlStrEqual(name, BAD_CAST "comment"))
9758*7c568831SAndroid Build Coastguard Worker 	    *type = NODE_TYPE_COMMENT;
9759*7c568831SAndroid Build Coastguard Worker 	else if (xmlStrEqual(name, BAD_CAST "node"))
9760*7c568831SAndroid Build Coastguard Worker 	    *type = NODE_TYPE_NODE;
9761*7c568831SAndroid Build Coastguard Worker 	else if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
9762*7c568831SAndroid Build Coastguard Worker 	    *type = NODE_TYPE_PI;
9763*7c568831SAndroid Build Coastguard Worker 	else if (xmlStrEqual(name, BAD_CAST "text"))
9764*7c568831SAndroid Build Coastguard Worker 	    *type = NODE_TYPE_TEXT;
9765*7c568831SAndroid Build Coastguard Worker 	else {
9766*7c568831SAndroid Build Coastguard Worker 	    if (name != NULL)
9767*7c568831SAndroid Build Coastguard Worker 		xmlFree(name);
9768*7c568831SAndroid Build Coastguard Worker 	    XP_ERRORNULL(XPATH_EXPR_ERROR);
9769*7c568831SAndroid Build Coastguard Worker 	}
9770*7c568831SAndroid Build Coastguard Worker 
9771*7c568831SAndroid Build Coastguard Worker 	*test = NODE_TEST_TYPE;
9772*7c568831SAndroid Build Coastguard Worker 
9773*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9774*7c568831SAndroid Build Coastguard Worker 	if (*type == NODE_TYPE_PI) {
9775*7c568831SAndroid Build Coastguard Worker 	    /*
9776*7c568831SAndroid Build Coastguard Worker 	     * Specific case: search a PI by name.
9777*7c568831SAndroid Build Coastguard Worker 	     */
9778*7c568831SAndroid Build Coastguard Worker 	    if (name != NULL)
9779*7c568831SAndroid Build Coastguard Worker 		xmlFree(name);
9780*7c568831SAndroid Build Coastguard Worker 	    name = NULL;
9781*7c568831SAndroid Build Coastguard Worker 	    if (CUR != ')') {
9782*7c568831SAndroid Build Coastguard Worker 		name = xmlXPathParseLiteral(ctxt);
9783*7c568831SAndroid Build Coastguard Worker 		*test = NODE_TEST_PI;
9784*7c568831SAndroid Build Coastguard Worker 		SKIP_BLANKS;
9785*7c568831SAndroid Build Coastguard Worker 	    }
9786*7c568831SAndroid Build Coastguard Worker 	}
9787*7c568831SAndroid Build Coastguard Worker 	if (CUR != ')') {
9788*7c568831SAndroid Build Coastguard Worker 	    if (name != NULL)
9789*7c568831SAndroid Build Coastguard Worker 		xmlFree(name);
9790*7c568831SAndroid Build Coastguard Worker 	    XP_ERRORNULL(XPATH_UNCLOSED_ERROR);
9791*7c568831SAndroid Build Coastguard Worker 	}
9792*7c568831SAndroid Build Coastguard Worker 	NEXT;
9793*7c568831SAndroid Build Coastguard Worker 	return(name);
9794*7c568831SAndroid Build Coastguard Worker     }
9795*7c568831SAndroid Build Coastguard Worker     *test = NODE_TEST_NAME;
9796*7c568831SAndroid Build Coastguard Worker     if ((!blanks) && (CUR == ':')) {
9797*7c568831SAndroid Build Coastguard Worker 	NEXT;
9798*7c568831SAndroid Build Coastguard Worker 
9799*7c568831SAndroid Build Coastguard Worker 	/*
9800*7c568831SAndroid Build Coastguard Worker 	 * Since currently the parser context don't have a
9801*7c568831SAndroid Build Coastguard Worker 	 * namespace list associated:
9802*7c568831SAndroid Build Coastguard Worker 	 * The namespace name for this prefix can be computed
9803*7c568831SAndroid Build Coastguard Worker 	 * only at evaluation time. The compilation is done
9804*7c568831SAndroid Build Coastguard Worker 	 * outside of any context.
9805*7c568831SAndroid Build Coastguard Worker 	 */
9806*7c568831SAndroid Build Coastguard Worker 	*prefix = name;
9807*7c568831SAndroid Build Coastguard Worker 
9808*7c568831SAndroid Build Coastguard Worker 	if (CUR == '*') {
9809*7c568831SAndroid Build Coastguard Worker 	    /*
9810*7c568831SAndroid Build Coastguard Worker 	     * All elements
9811*7c568831SAndroid Build Coastguard Worker 	     */
9812*7c568831SAndroid Build Coastguard Worker 	    NEXT;
9813*7c568831SAndroid Build Coastguard Worker 	    *test = NODE_TEST_ALL;
9814*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
9815*7c568831SAndroid Build Coastguard Worker 	}
9816*7c568831SAndroid Build Coastguard Worker 
9817*7c568831SAndroid Build Coastguard Worker 	name = xmlXPathParseNCName(ctxt);
9818*7c568831SAndroid Build Coastguard Worker 	if (name == NULL) {
9819*7c568831SAndroid Build Coastguard Worker 	    XP_ERRORNULL(XPATH_EXPR_ERROR);
9820*7c568831SAndroid Build Coastguard Worker 	}
9821*7c568831SAndroid Build Coastguard Worker     }
9822*7c568831SAndroid Build Coastguard Worker     return(name);
9823*7c568831SAndroid Build Coastguard Worker }
9824*7c568831SAndroid Build Coastguard Worker 
9825*7c568831SAndroid Build Coastguard Worker /**
9826*7c568831SAndroid Build Coastguard Worker  * xmlXPathIsAxisName:
9827*7c568831SAndroid Build Coastguard Worker  * @name:  a preparsed name token
9828*7c568831SAndroid Build Coastguard Worker  *
9829*7c568831SAndroid Build Coastguard Worker  * [6] AxisName ::=   'ancestor'
9830*7c568831SAndroid Build Coastguard Worker  *                  | 'ancestor-or-self'
9831*7c568831SAndroid Build Coastguard Worker  *                  | 'attribute'
9832*7c568831SAndroid Build Coastguard Worker  *                  | 'child'
9833*7c568831SAndroid Build Coastguard Worker  *                  | 'descendant'
9834*7c568831SAndroid Build Coastguard Worker  *                  | 'descendant-or-self'
9835*7c568831SAndroid Build Coastguard Worker  *                  | 'following'
9836*7c568831SAndroid Build Coastguard Worker  *                  | 'following-sibling'
9837*7c568831SAndroid Build Coastguard Worker  *                  | 'namespace'
9838*7c568831SAndroid Build Coastguard Worker  *                  | 'parent'
9839*7c568831SAndroid Build Coastguard Worker  *                  | 'preceding'
9840*7c568831SAndroid Build Coastguard Worker  *                  | 'preceding-sibling'
9841*7c568831SAndroid Build Coastguard Worker  *                  | 'self'
9842*7c568831SAndroid Build Coastguard Worker  *
9843*7c568831SAndroid Build Coastguard Worker  * Returns the axis or 0
9844*7c568831SAndroid Build Coastguard Worker  */
9845*7c568831SAndroid Build Coastguard Worker static xmlXPathAxisVal
xmlXPathIsAxisName(const xmlChar * name)9846*7c568831SAndroid Build Coastguard Worker xmlXPathIsAxisName(const xmlChar *name) {
9847*7c568831SAndroid Build Coastguard Worker     xmlXPathAxisVal ret = (xmlXPathAxisVal) 0;
9848*7c568831SAndroid Build Coastguard Worker     switch (name[0]) {
9849*7c568831SAndroid Build Coastguard Worker 	case 'a':
9850*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "ancestor"))
9851*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_ANCESTOR;
9852*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "ancestor-or-self"))
9853*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_ANCESTOR_OR_SELF;
9854*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "attribute"))
9855*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_ATTRIBUTE;
9856*7c568831SAndroid Build Coastguard Worker 	    break;
9857*7c568831SAndroid Build Coastguard Worker 	case 'c':
9858*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "child"))
9859*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_CHILD;
9860*7c568831SAndroid Build Coastguard Worker 	    break;
9861*7c568831SAndroid Build Coastguard Worker 	case 'd':
9862*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "descendant"))
9863*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_DESCENDANT;
9864*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "descendant-or-self"))
9865*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_DESCENDANT_OR_SELF;
9866*7c568831SAndroid Build Coastguard Worker 	    break;
9867*7c568831SAndroid Build Coastguard Worker 	case 'f':
9868*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "following"))
9869*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_FOLLOWING;
9870*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "following-sibling"))
9871*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_FOLLOWING_SIBLING;
9872*7c568831SAndroid Build Coastguard Worker 	    break;
9873*7c568831SAndroid Build Coastguard Worker 	case 'n':
9874*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "namespace"))
9875*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_NAMESPACE;
9876*7c568831SAndroid Build Coastguard Worker 	    break;
9877*7c568831SAndroid Build Coastguard Worker 	case 'p':
9878*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "parent"))
9879*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_PARENT;
9880*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "preceding"))
9881*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_PRECEDING;
9882*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "preceding-sibling"))
9883*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_PRECEDING_SIBLING;
9884*7c568831SAndroid Build Coastguard Worker 	    break;
9885*7c568831SAndroid Build Coastguard Worker 	case 's':
9886*7c568831SAndroid Build Coastguard Worker 	    if (xmlStrEqual(name, BAD_CAST "self"))
9887*7c568831SAndroid Build Coastguard Worker 		ret = AXIS_SELF;
9888*7c568831SAndroid Build Coastguard Worker 	    break;
9889*7c568831SAndroid Build Coastguard Worker     }
9890*7c568831SAndroid Build Coastguard Worker     return(ret);
9891*7c568831SAndroid Build Coastguard Worker }
9892*7c568831SAndroid Build Coastguard Worker 
9893*7c568831SAndroid Build Coastguard Worker /**
9894*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompStep:
9895*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
9896*7c568831SAndroid Build Coastguard Worker  *
9897*7c568831SAndroid Build Coastguard Worker  * [4] Step ::=   AxisSpecifier NodeTest Predicate*
9898*7c568831SAndroid Build Coastguard Worker  *                  | AbbreviatedStep
9899*7c568831SAndroid Build Coastguard Worker  *
9900*7c568831SAndroid Build Coastguard Worker  * [12] AbbreviatedStep ::=   '.' | '..'
9901*7c568831SAndroid Build Coastguard Worker  *
9902*7c568831SAndroid Build Coastguard Worker  * [5] AxisSpecifier ::= AxisName '::'
9903*7c568831SAndroid Build Coastguard Worker  *                  | AbbreviatedAxisSpecifier
9904*7c568831SAndroid Build Coastguard Worker  *
9905*7c568831SAndroid Build Coastguard Worker  * [13] AbbreviatedAxisSpecifier ::= '@'?
9906*7c568831SAndroid Build Coastguard Worker  *
9907*7c568831SAndroid Build Coastguard Worker  * Modified for XPtr range support as:
9908*7c568831SAndroid Build Coastguard Worker  *
9909*7c568831SAndroid Build Coastguard Worker  *  [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
9910*7c568831SAndroid Build Coastguard Worker  *                     | AbbreviatedStep
9911*7c568831SAndroid Build Coastguard Worker  *                     | 'range-to' '(' Expr ')' Predicate*
9912*7c568831SAndroid Build Coastguard Worker  *
9913*7c568831SAndroid Build Coastguard Worker  * Compile one step in a Location Path
9914*7c568831SAndroid Build Coastguard Worker  * A location step of . is short for self::node(). This is
9915*7c568831SAndroid Build Coastguard Worker  * particularly useful in conjunction with //. For example, the
9916*7c568831SAndroid Build Coastguard Worker  * location path .//para is short for
9917*7c568831SAndroid Build Coastguard Worker  * self::node()/descendant-or-self::node()/child::para
9918*7c568831SAndroid Build Coastguard Worker  * and so will select all para descendant elements of the context
9919*7c568831SAndroid Build Coastguard Worker  * node.
9920*7c568831SAndroid Build Coastguard Worker  * Similarly, a location step of .. is short for parent::node().
9921*7c568831SAndroid Build Coastguard Worker  * For example, ../title is short for parent::node()/child::title
9922*7c568831SAndroid Build Coastguard Worker  * and so will select the title children of the parent of the context
9923*7c568831SAndroid Build Coastguard Worker  * node.
9924*7c568831SAndroid Build Coastguard Worker  */
9925*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompStep(xmlXPathParserContextPtr ctxt)9926*7c568831SAndroid Build Coastguard Worker xmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
9927*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
9928*7c568831SAndroid Build Coastguard Worker     if ((CUR == '.') && (NXT(1) == '.')) {
9929*7c568831SAndroid Build Coastguard Worker 	SKIP(2);
9930*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9931*7c568831SAndroid Build Coastguard Worker 	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT,
9932*7c568831SAndroid Build Coastguard Worker 		    NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9933*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '.') {
9934*7c568831SAndroid Build Coastguard Worker 	NEXT;
9935*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9936*7c568831SAndroid Build Coastguard Worker     } else {
9937*7c568831SAndroid Build Coastguard Worker 	xmlChar *name = NULL;
9938*7c568831SAndroid Build Coastguard Worker 	xmlChar *prefix = NULL;
9939*7c568831SAndroid Build Coastguard Worker 	xmlXPathTestVal test = (xmlXPathTestVal) 0;
9940*7c568831SAndroid Build Coastguard Worker 	xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
9941*7c568831SAndroid Build Coastguard Worker 	xmlXPathTypeVal type = (xmlXPathTypeVal) 0;
9942*7c568831SAndroid Build Coastguard Worker 	int op1;
9943*7c568831SAndroid Build Coastguard Worker 
9944*7c568831SAndroid Build Coastguard Worker 	if (CUR == '*') {
9945*7c568831SAndroid Build Coastguard Worker 	    axis = AXIS_CHILD;
9946*7c568831SAndroid Build Coastguard Worker 	} else {
9947*7c568831SAndroid Build Coastguard Worker 	    if (name == NULL)
9948*7c568831SAndroid Build Coastguard Worker 		name = xmlXPathParseNCName(ctxt);
9949*7c568831SAndroid Build Coastguard Worker 	    if (name != NULL) {
9950*7c568831SAndroid Build Coastguard Worker 		axis = xmlXPathIsAxisName(name);
9951*7c568831SAndroid Build Coastguard Worker 		if (axis != 0) {
9952*7c568831SAndroid Build Coastguard Worker 		    SKIP_BLANKS;
9953*7c568831SAndroid Build Coastguard Worker 		    if ((CUR == ':') && (NXT(1) == ':')) {
9954*7c568831SAndroid Build Coastguard Worker 			SKIP(2);
9955*7c568831SAndroid Build Coastguard Worker 			xmlFree(name);
9956*7c568831SAndroid Build Coastguard Worker 			name = NULL;
9957*7c568831SAndroid Build Coastguard Worker 		    } else {
9958*7c568831SAndroid Build Coastguard Worker 			/* an element name can conflict with an axis one :-\ */
9959*7c568831SAndroid Build Coastguard Worker 			axis = AXIS_CHILD;
9960*7c568831SAndroid Build Coastguard Worker 		    }
9961*7c568831SAndroid Build Coastguard Worker 		} else {
9962*7c568831SAndroid Build Coastguard Worker 		    axis = AXIS_CHILD;
9963*7c568831SAndroid Build Coastguard Worker 		}
9964*7c568831SAndroid Build Coastguard Worker 	    } else if (CUR == '@') {
9965*7c568831SAndroid Build Coastguard Worker 		NEXT;
9966*7c568831SAndroid Build Coastguard Worker 		axis = AXIS_ATTRIBUTE;
9967*7c568831SAndroid Build Coastguard Worker 	    } else {
9968*7c568831SAndroid Build Coastguard Worker 		axis = AXIS_CHILD;
9969*7c568831SAndroid Build Coastguard Worker 	    }
9970*7c568831SAndroid Build Coastguard Worker 	}
9971*7c568831SAndroid Build Coastguard Worker 
9972*7c568831SAndroid Build Coastguard Worker         if (ctxt->error != XPATH_EXPRESSION_OK) {
9973*7c568831SAndroid Build Coastguard Worker             xmlFree(name);
9974*7c568831SAndroid Build Coastguard Worker             return;
9975*7c568831SAndroid Build Coastguard Worker         }
9976*7c568831SAndroid Build Coastguard Worker 
9977*7c568831SAndroid Build Coastguard Worker 	name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
9978*7c568831SAndroid Build Coastguard Worker 	if (test == 0)
9979*7c568831SAndroid Build Coastguard Worker 	    return;
9980*7c568831SAndroid Build Coastguard Worker 
9981*7c568831SAndroid Build Coastguard Worker         if ((prefix != NULL) && (ctxt->context != NULL) &&
9982*7c568831SAndroid Build Coastguard Worker 	    (ctxt->context->flags & XML_XPATH_CHECKNS)) {
9983*7c568831SAndroid Build Coastguard Worker 	    if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) {
9984*7c568831SAndroid Build Coastguard Worker 		xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR);
9985*7c568831SAndroid Build Coastguard Worker 	    }
9986*7c568831SAndroid Build Coastguard Worker 	}
9987*7c568831SAndroid Build Coastguard Worker 
9988*7c568831SAndroid Build Coastguard Worker 	op1 = ctxt->comp->last;
9989*7c568831SAndroid Build Coastguard Worker 	ctxt->comp->last = -1;
9990*7c568831SAndroid Build Coastguard Worker 
9991*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
9992*7c568831SAndroid Build Coastguard Worker 	while (CUR == '[') {
9993*7c568831SAndroid Build Coastguard Worker 	    xmlXPathCompPredicate(ctxt, 0);
9994*7c568831SAndroid Build Coastguard Worker 	}
9995*7c568831SAndroid Build Coastguard Worker 
9996*7c568831SAndroid Build Coastguard Worker         if (PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
9997*7c568831SAndroid Build Coastguard Worker                            test, type, (void *)prefix, (void *)name) == -1) {
9998*7c568831SAndroid Build Coastguard Worker             xmlFree(prefix);
9999*7c568831SAndroid Build Coastguard Worker             xmlFree(name);
10000*7c568831SAndroid Build Coastguard Worker         }
10001*7c568831SAndroid Build Coastguard Worker     }
10002*7c568831SAndroid Build Coastguard Worker }
10003*7c568831SAndroid Build Coastguard Worker 
10004*7c568831SAndroid Build Coastguard Worker /**
10005*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompRelativeLocationPath:
10006*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
10007*7c568831SAndroid Build Coastguard Worker  *
10008*7c568831SAndroid Build Coastguard Worker  *  [3]   RelativeLocationPath ::=   Step
10009*7c568831SAndroid Build Coastguard Worker  *                     | RelativeLocationPath '/' Step
10010*7c568831SAndroid Build Coastguard Worker  *                     | AbbreviatedRelativeLocationPath
10011*7c568831SAndroid Build Coastguard Worker  *  [11]  AbbreviatedRelativeLocationPath ::=   RelativeLocationPath '//' Step
10012*7c568831SAndroid Build Coastguard Worker  *
10013*7c568831SAndroid Build Coastguard Worker  * Compile a relative location path.
10014*7c568831SAndroid Build Coastguard Worker  */
10015*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt)10016*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath
10017*7c568831SAndroid Build Coastguard Worker (xmlXPathParserContextPtr ctxt) {
10018*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
10019*7c568831SAndroid Build Coastguard Worker     if ((CUR == '/') && (NXT(1) == '/')) {
10020*7c568831SAndroid Build Coastguard Worker 	SKIP(2);
10021*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
10022*7c568831SAndroid Build Coastguard Worker 	PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10023*7c568831SAndroid Build Coastguard Worker 		         NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10024*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '/') {
10025*7c568831SAndroid Build Coastguard Worker 	    NEXT;
10026*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
10027*7c568831SAndroid Build Coastguard Worker     }
10028*7c568831SAndroid Build Coastguard Worker     xmlXPathCompStep(ctxt);
10029*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR;
10030*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
10031*7c568831SAndroid Build Coastguard Worker     while (CUR == '/') {
10032*7c568831SAndroid Build Coastguard Worker 	if ((CUR == '/') && (NXT(1) == '/')) {
10033*7c568831SAndroid Build Coastguard Worker 	    SKIP(2);
10034*7c568831SAndroid Build Coastguard Worker 	    SKIP_BLANKS;
10035*7c568831SAndroid Build Coastguard Worker 	    PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10036*7c568831SAndroid Build Coastguard Worker 			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10037*7c568831SAndroid Build Coastguard Worker 	    xmlXPathCompStep(ctxt);
10038*7c568831SAndroid Build Coastguard Worker 	} else if (CUR == '/') {
10039*7c568831SAndroid Build Coastguard Worker 	    NEXT;
10040*7c568831SAndroid Build Coastguard Worker 	    SKIP_BLANKS;
10041*7c568831SAndroid Build Coastguard Worker 	    xmlXPathCompStep(ctxt);
10042*7c568831SAndroid Build Coastguard Worker 	}
10043*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS;
10044*7c568831SAndroid Build Coastguard Worker     }
10045*7c568831SAndroid Build Coastguard Worker }
10046*7c568831SAndroid Build Coastguard Worker 
10047*7c568831SAndroid Build Coastguard Worker /**
10048*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompLocationPath:
10049*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
10050*7c568831SAndroid Build Coastguard Worker  *
10051*7c568831SAndroid Build Coastguard Worker  *  [1]   LocationPath ::=   RelativeLocationPath
10052*7c568831SAndroid Build Coastguard Worker  *                     | AbsoluteLocationPath
10053*7c568831SAndroid Build Coastguard Worker  *  [2]   AbsoluteLocationPath ::=   '/' RelativeLocationPath?
10054*7c568831SAndroid Build Coastguard Worker  *                     | AbbreviatedAbsoluteLocationPath
10055*7c568831SAndroid Build Coastguard Worker  *  [10]   AbbreviatedAbsoluteLocationPath ::=
10056*7c568831SAndroid Build Coastguard Worker  *                           '//' RelativeLocationPath
10057*7c568831SAndroid Build Coastguard Worker  *
10058*7c568831SAndroid Build Coastguard Worker  * Compile a location path
10059*7c568831SAndroid Build Coastguard Worker  *
10060*7c568831SAndroid Build Coastguard Worker  * // is short for /descendant-or-self::node()/. For example,
10061*7c568831SAndroid Build Coastguard Worker  * //para is short for /descendant-or-self::node()/child::para and
10062*7c568831SAndroid Build Coastguard Worker  * so will select any para element in the document (even a para element
10063*7c568831SAndroid Build Coastguard Worker  * that is a document element will be selected by //para since the
10064*7c568831SAndroid Build Coastguard Worker  * document element node is a child of the root node); div//para is
10065*7c568831SAndroid Build Coastguard Worker  * short for div/descendant-or-self::node()/child::para and so will
10066*7c568831SAndroid Build Coastguard Worker  * select all para descendants of div children.
10067*7c568831SAndroid Build Coastguard Worker  */
10068*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt)10069*7c568831SAndroid Build Coastguard Worker xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
10070*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS;
10071*7c568831SAndroid Build Coastguard Worker     if (CUR != '/') {
10072*7c568831SAndroid Build Coastguard Worker         xmlXPathCompRelativeLocationPath(ctxt);
10073*7c568831SAndroid Build Coastguard Worker     } else {
10074*7c568831SAndroid Build Coastguard Worker 	while (CUR == '/') {
10075*7c568831SAndroid Build Coastguard Worker 	    if ((CUR == '/') && (NXT(1) == '/')) {
10076*7c568831SAndroid Build Coastguard Worker 		SKIP(2);
10077*7c568831SAndroid Build Coastguard Worker 		SKIP_BLANKS;
10078*7c568831SAndroid Build Coastguard Worker 		PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10079*7c568831SAndroid Build Coastguard Worker 			     NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10080*7c568831SAndroid Build Coastguard Worker 		xmlXPathCompRelativeLocationPath(ctxt);
10081*7c568831SAndroid Build Coastguard Worker 	    } else if (CUR == '/') {
10082*7c568831SAndroid Build Coastguard Worker 		NEXT;
10083*7c568831SAndroid Build Coastguard Worker 		SKIP_BLANKS;
10084*7c568831SAndroid Build Coastguard Worker 		if ((CUR != 0 ) &&
10085*7c568831SAndroid Build Coastguard Worker 		    ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') ||
10086*7c568831SAndroid Build Coastguard Worker 		     (CUR == '@') || (CUR == '*')))
10087*7c568831SAndroid Build Coastguard Worker 		    xmlXPathCompRelativeLocationPath(ctxt);
10088*7c568831SAndroid Build Coastguard Worker 	    }
10089*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR;
10090*7c568831SAndroid Build Coastguard Worker 	}
10091*7c568831SAndroid Build Coastguard Worker     }
10092*7c568831SAndroid Build Coastguard Worker }
10093*7c568831SAndroid Build Coastguard Worker 
10094*7c568831SAndroid Build Coastguard Worker /************************************************************************
10095*7c568831SAndroid Build Coastguard Worker  *									*
10096*7c568831SAndroid Build Coastguard Worker  *		XPath precompiled expression evaluation			*
10097*7c568831SAndroid Build Coastguard Worker  *									*
10098*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
10099*7c568831SAndroid Build Coastguard Worker 
10100*7c568831SAndroid Build Coastguard Worker static int
10101*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
10102*7c568831SAndroid Build Coastguard Worker 
10103*7c568831SAndroid Build Coastguard Worker /**
10104*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeSetFilter:
10105*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
10106*7c568831SAndroid Build Coastguard Worker  * @set: the node set to filter
10107*7c568831SAndroid Build Coastguard Worker  * @filterOpIndex: the index of the predicate/filter op
10108*7c568831SAndroid Build Coastguard Worker  * @minPos: minimum position in the filtered set (1-based)
10109*7c568831SAndroid Build Coastguard Worker  * @maxPos: maximum position in the filtered set (1-based)
10110*7c568831SAndroid Build Coastguard Worker  * @hasNsNodes: true if the node set may contain namespace nodes
10111*7c568831SAndroid Build Coastguard Worker  *
10112*7c568831SAndroid Build Coastguard Worker  * Filter a node set, keeping only nodes for which the predicate expression
10113*7c568831SAndroid Build Coastguard Worker  * matches. Afterwards, keep only nodes between minPos and maxPos in the
10114*7c568831SAndroid Build Coastguard Worker  * filtered result.
10115*7c568831SAndroid Build Coastguard Worker  */
10116*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,xmlNodeSetPtr set,int filterOpIndex,int minPos,int maxPos,int hasNsNodes)10117*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
10118*7c568831SAndroid Build Coastguard Worker 		      xmlNodeSetPtr set,
10119*7c568831SAndroid Build Coastguard Worker 		      int filterOpIndex,
10120*7c568831SAndroid Build Coastguard Worker                       int minPos, int maxPos,
10121*7c568831SAndroid Build Coastguard Worker 		      int hasNsNodes)
10122*7c568831SAndroid Build Coastguard Worker {
10123*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr xpctxt;
10124*7c568831SAndroid Build Coastguard Worker     xmlNodePtr oldnode;
10125*7c568831SAndroid Build Coastguard Worker     xmlDocPtr olddoc;
10126*7c568831SAndroid Build Coastguard Worker     xmlXPathStepOpPtr filterOp;
10127*7c568831SAndroid Build Coastguard Worker     int oldcs, oldpp;
10128*7c568831SAndroid Build Coastguard Worker     int i, j, pos;
10129*7c568831SAndroid Build Coastguard Worker 
10130*7c568831SAndroid Build Coastguard Worker     if ((set == NULL) || (set->nodeNr == 0))
10131*7c568831SAndroid Build Coastguard Worker         return;
10132*7c568831SAndroid Build Coastguard Worker 
10133*7c568831SAndroid Build Coastguard Worker     /*
10134*7c568831SAndroid Build Coastguard Worker     * Check if the node set contains a sufficient number of nodes for
10135*7c568831SAndroid Build Coastguard Worker     * the requested range.
10136*7c568831SAndroid Build Coastguard Worker     */
10137*7c568831SAndroid Build Coastguard Worker     if (set->nodeNr < minPos) {
10138*7c568831SAndroid Build Coastguard Worker         xmlXPathNodeSetClear(set, hasNsNodes);
10139*7c568831SAndroid Build Coastguard Worker         return;
10140*7c568831SAndroid Build Coastguard Worker     }
10141*7c568831SAndroid Build Coastguard Worker 
10142*7c568831SAndroid Build Coastguard Worker     xpctxt = ctxt->context;
10143*7c568831SAndroid Build Coastguard Worker     oldnode = xpctxt->node;
10144*7c568831SAndroid Build Coastguard Worker     olddoc = xpctxt->doc;
10145*7c568831SAndroid Build Coastguard Worker     oldcs = xpctxt->contextSize;
10146*7c568831SAndroid Build Coastguard Worker     oldpp = xpctxt->proximityPosition;
10147*7c568831SAndroid Build Coastguard Worker     filterOp = &ctxt->comp->steps[filterOpIndex];
10148*7c568831SAndroid Build Coastguard Worker 
10149*7c568831SAndroid Build Coastguard Worker     xpctxt->contextSize = set->nodeNr;
10150*7c568831SAndroid Build Coastguard Worker 
10151*7c568831SAndroid Build Coastguard Worker     for (i = 0, j = 0, pos = 1; i < set->nodeNr; i++) {
10152*7c568831SAndroid Build Coastguard Worker         xmlNodePtr node = set->nodeTab[i];
10153*7c568831SAndroid Build Coastguard Worker         int res;
10154*7c568831SAndroid Build Coastguard Worker 
10155*7c568831SAndroid Build Coastguard Worker         xpctxt->node = node;
10156*7c568831SAndroid Build Coastguard Worker         xpctxt->proximityPosition = i + 1;
10157*7c568831SAndroid Build Coastguard Worker 
10158*7c568831SAndroid Build Coastguard Worker         /*
10159*7c568831SAndroid Build Coastguard Worker         * Also set the xpath document in case things like
10160*7c568831SAndroid Build Coastguard Worker         * key() are evaluated in the predicate.
10161*7c568831SAndroid Build Coastguard Worker         *
10162*7c568831SAndroid Build Coastguard Worker         * TODO: Get real doc for namespace nodes.
10163*7c568831SAndroid Build Coastguard Worker         */
10164*7c568831SAndroid Build Coastguard Worker         if ((node->type != XML_NAMESPACE_DECL) &&
10165*7c568831SAndroid Build Coastguard Worker             (node->doc != NULL))
10166*7c568831SAndroid Build Coastguard Worker             xpctxt->doc = node->doc;
10167*7c568831SAndroid Build Coastguard Worker 
10168*7c568831SAndroid Build Coastguard Worker         res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
10169*7c568831SAndroid Build Coastguard Worker 
10170*7c568831SAndroid Build Coastguard Worker         if (ctxt->error != XPATH_EXPRESSION_OK)
10171*7c568831SAndroid Build Coastguard Worker             break;
10172*7c568831SAndroid Build Coastguard Worker         if (res < 0) {
10173*7c568831SAndroid Build Coastguard Worker             /* Shouldn't happen */
10174*7c568831SAndroid Build Coastguard Worker             xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
10175*7c568831SAndroid Build Coastguard Worker             break;
10176*7c568831SAndroid Build Coastguard Worker         }
10177*7c568831SAndroid Build Coastguard Worker 
10178*7c568831SAndroid Build Coastguard Worker         if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
10179*7c568831SAndroid Build Coastguard Worker             if (i != j) {
10180*7c568831SAndroid Build Coastguard Worker                 set->nodeTab[j] = node;
10181*7c568831SAndroid Build Coastguard Worker                 set->nodeTab[i] = NULL;
10182*7c568831SAndroid Build Coastguard Worker             }
10183*7c568831SAndroid Build Coastguard Worker 
10184*7c568831SAndroid Build Coastguard Worker             j += 1;
10185*7c568831SAndroid Build Coastguard Worker         } else {
10186*7c568831SAndroid Build Coastguard Worker             /* Remove the entry from the initial node set. */
10187*7c568831SAndroid Build Coastguard Worker             set->nodeTab[i] = NULL;
10188*7c568831SAndroid Build Coastguard Worker             if (node->type == XML_NAMESPACE_DECL)
10189*7c568831SAndroid Build Coastguard Worker                 xmlXPathNodeSetFreeNs((xmlNsPtr) node);
10190*7c568831SAndroid Build Coastguard Worker         }
10191*7c568831SAndroid Build Coastguard Worker 
10192*7c568831SAndroid Build Coastguard Worker         if (res != 0) {
10193*7c568831SAndroid Build Coastguard Worker             if (pos == maxPos) {
10194*7c568831SAndroid Build Coastguard Worker                 i += 1;
10195*7c568831SAndroid Build Coastguard Worker                 break;
10196*7c568831SAndroid Build Coastguard Worker             }
10197*7c568831SAndroid Build Coastguard Worker 
10198*7c568831SAndroid Build Coastguard Worker             pos += 1;
10199*7c568831SAndroid Build Coastguard Worker         }
10200*7c568831SAndroid Build Coastguard Worker     }
10201*7c568831SAndroid Build Coastguard Worker 
10202*7c568831SAndroid Build Coastguard Worker     /* Free remaining nodes. */
10203*7c568831SAndroid Build Coastguard Worker     if (hasNsNodes) {
10204*7c568831SAndroid Build Coastguard Worker         for (; i < set->nodeNr; i++) {
10205*7c568831SAndroid Build Coastguard Worker             xmlNodePtr node = set->nodeTab[i];
10206*7c568831SAndroid Build Coastguard Worker             if ((node != NULL) && (node->type == XML_NAMESPACE_DECL))
10207*7c568831SAndroid Build Coastguard Worker                 xmlXPathNodeSetFreeNs((xmlNsPtr) node);
10208*7c568831SAndroid Build Coastguard Worker         }
10209*7c568831SAndroid Build Coastguard Worker     }
10210*7c568831SAndroid Build Coastguard Worker 
10211*7c568831SAndroid Build Coastguard Worker     set->nodeNr = j;
10212*7c568831SAndroid Build Coastguard Worker 
10213*7c568831SAndroid Build Coastguard Worker     /* If too many elements were removed, shrink table to preserve memory. */
10214*7c568831SAndroid Build Coastguard Worker     if ((set->nodeMax > XML_NODESET_DEFAULT) &&
10215*7c568831SAndroid Build Coastguard Worker         (set->nodeNr < set->nodeMax / 2)) {
10216*7c568831SAndroid Build Coastguard Worker         xmlNodePtr *tmp;
10217*7c568831SAndroid Build Coastguard Worker         int nodeMax = set->nodeNr;
10218*7c568831SAndroid Build Coastguard Worker 
10219*7c568831SAndroid Build Coastguard Worker         if (nodeMax < XML_NODESET_DEFAULT)
10220*7c568831SAndroid Build Coastguard Worker             nodeMax = XML_NODESET_DEFAULT;
10221*7c568831SAndroid Build Coastguard Worker         tmp = (xmlNodePtr *) xmlRealloc(set->nodeTab,
10222*7c568831SAndroid Build Coastguard Worker                 nodeMax * sizeof(xmlNodePtr));
10223*7c568831SAndroid Build Coastguard Worker         if (tmp == NULL) {
10224*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(ctxt);
10225*7c568831SAndroid Build Coastguard Worker         } else {
10226*7c568831SAndroid Build Coastguard Worker             set->nodeTab = tmp;
10227*7c568831SAndroid Build Coastguard Worker             set->nodeMax = nodeMax;
10228*7c568831SAndroid Build Coastguard Worker         }
10229*7c568831SAndroid Build Coastguard Worker     }
10230*7c568831SAndroid Build Coastguard Worker 
10231*7c568831SAndroid Build Coastguard Worker     xpctxt->node = oldnode;
10232*7c568831SAndroid Build Coastguard Worker     xpctxt->doc = olddoc;
10233*7c568831SAndroid Build Coastguard Worker     xpctxt->contextSize = oldcs;
10234*7c568831SAndroid Build Coastguard Worker     xpctxt->proximityPosition = oldpp;
10235*7c568831SAndroid Build Coastguard Worker }
10236*7c568831SAndroid Build Coastguard Worker 
10237*7c568831SAndroid Build Coastguard Worker /**
10238*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompOpEvalPredicate:
10239*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
10240*7c568831SAndroid Build Coastguard Worker  * @op: the predicate op
10241*7c568831SAndroid Build Coastguard Worker  * @set: the node set to filter
10242*7c568831SAndroid Build Coastguard Worker  * @minPos: minimum position in the filtered set (1-based)
10243*7c568831SAndroid Build Coastguard Worker  * @maxPos: maximum position in the filtered set (1-based)
10244*7c568831SAndroid Build Coastguard Worker  * @hasNsNodes: true if the node set may contain namespace nodes
10245*7c568831SAndroid Build Coastguard Worker  *
10246*7c568831SAndroid Build Coastguard Worker  * Filter a node set, keeping only nodes for which the sequence of predicate
10247*7c568831SAndroid Build Coastguard Worker  * expressions matches. Afterwards, keep only nodes between minPos and maxPos
10248*7c568831SAndroid Build Coastguard Worker  * in the filtered result.
10249*7c568831SAndroid Build Coastguard Worker  */
10250*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodeSetPtr set,int minPos,int maxPos,int hasNsNodes)10251*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
10252*7c568831SAndroid Build Coastguard Worker 			    xmlXPathStepOpPtr op,
10253*7c568831SAndroid Build Coastguard Worker 			    xmlNodeSetPtr set,
10254*7c568831SAndroid Build Coastguard Worker                             int minPos, int maxPos,
10255*7c568831SAndroid Build Coastguard Worker 			    int hasNsNodes)
10256*7c568831SAndroid Build Coastguard Worker {
10257*7c568831SAndroid Build Coastguard Worker     if (op->ch1 != -1) {
10258*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompExprPtr comp = ctxt->comp;
10259*7c568831SAndroid Build Coastguard Worker 	/*
10260*7c568831SAndroid Build Coastguard Worker 	* Process inner predicates first.
10261*7c568831SAndroid Build Coastguard Worker 	*/
10262*7c568831SAndroid Build Coastguard Worker 	if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) {
10263*7c568831SAndroid Build Coastguard Worker             XP_ERROR(XPATH_INVALID_OPERAND);
10264*7c568831SAndroid Build Coastguard Worker 	}
10265*7c568831SAndroid Build Coastguard Worker         if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
10266*7c568831SAndroid Build Coastguard Worker             XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
10267*7c568831SAndroid Build Coastguard Worker         ctxt->context->depth += 1;
10268*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompOpEvalPredicate(ctxt, &comp->steps[op->ch1], set,
10269*7c568831SAndroid Build Coastguard Worker                                     1, set->nodeNr, hasNsNodes);
10270*7c568831SAndroid Build Coastguard Worker         ctxt->context->depth -= 1;
10271*7c568831SAndroid Build Coastguard Worker 	CHECK_ERROR;
10272*7c568831SAndroid Build Coastguard Worker     }
10273*7c568831SAndroid Build Coastguard Worker 
10274*7c568831SAndroid Build Coastguard Worker     if (op->ch2 != -1)
10275*7c568831SAndroid Build Coastguard Worker         xmlXPathNodeSetFilter(ctxt, set, op->ch2, minPos, maxPos, hasNsNodes);
10276*7c568831SAndroid Build Coastguard Worker }
10277*7c568831SAndroid Build Coastguard Worker 
10278*7c568831SAndroid Build Coastguard Worker static int
xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,int * maxPos)10279*7c568831SAndroid Build Coastguard Worker xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt,
10280*7c568831SAndroid Build Coastguard Worker 			    xmlXPathStepOpPtr op,
10281*7c568831SAndroid Build Coastguard Worker 			    int *maxPos)
10282*7c568831SAndroid Build Coastguard Worker {
10283*7c568831SAndroid Build Coastguard Worker 
10284*7c568831SAndroid Build Coastguard Worker     xmlXPathStepOpPtr exprOp;
10285*7c568831SAndroid Build Coastguard Worker 
10286*7c568831SAndroid Build Coastguard Worker     /*
10287*7c568831SAndroid Build Coastguard Worker     * BIG NOTE: This is not intended for XPATH_OP_FILTER yet!
10288*7c568831SAndroid Build Coastguard Worker     */
10289*7c568831SAndroid Build Coastguard Worker 
10290*7c568831SAndroid Build Coastguard Worker     /*
10291*7c568831SAndroid Build Coastguard Worker     * If not -1, then ch1 will point to:
10292*7c568831SAndroid Build Coastguard Worker     * 1) For predicates (XPATH_OP_PREDICATE):
10293*7c568831SAndroid Build Coastguard Worker     *    - an inner predicate operator
10294*7c568831SAndroid Build Coastguard Worker     * 2) For filters (XPATH_OP_FILTER):
10295*7c568831SAndroid Build Coastguard Worker     *    - an inner filter operator OR
10296*7c568831SAndroid Build Coastguard Worker     *    - an expression selecting the node set.
10297*7c568831SAndroid Build Coastguard Worker     *      E.g. "key('a', 'b')" or "(//foo | //bar)".
10298*7c568831SAndroid Build Coastguard Worker     */
10299*7c568831SAndroid Build Coastguard Worker     if ((op->op != XPATH_OP_PREDICATE) && (op->op != XPATH_OP_FILTER))
10300*7c568831SAndroid Build Coastguard Worker 	return(0);
10301*7c568831SAndroid Build Coastguard Worker 
10302*7c568831SAndroid Build Coastguard Worker     if (op->ch2 != -1) {
10303*7c568831SAndroid Build Coastguard Worker 	exprOp = &ctxt->comp->steps[op->ch2];
10304*7c568831SAndroid Build Coastguard Worker     } else
10305*7c568831SAndroid Build Coastguard Worker 	return(0);
10306*7c568831SAndroid Build Coastguard Worker 
10307*7c568831SAndroid Build Coastguard Worker     if ((exprOp != NULL) &&
10308*7c568831SAndroid Build Coastguard Worker 	(exprOp->op == XPATH_OP_VALUE) &&
10309*7c568831SAndroid Build Coastguard Worker 	(exprOp->value4 != NULL) &&
10310*7c568831SAndroid Build Coastguard Worker 	(((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER))
10311*7c568831SAndroid Build Coastguard Worker     {
10312*7c568831SAndroid Build Coastguard Worker         double floatval = ((xmlXPathObjectPtr) exprOp->value4)->floatval;
10313*7c568831SAndroid Build Coastguard Worker 
10314*7c568831SAndroid Build Coastguard Worker 	/*
10315*7c568831SAndroid Build Coastguard Worker 	* We have a "[n]" predicate here.
10316*7c568831SAndroid Build Coastguard Worker 	* TODO: Unfortunately this simplistic test here is not
10317*7c568831SAndroid Build Coastguard Worker 	* able to detect a position() predicate in compound
10318*7c568831SAndroid Build Coastguard Worker 	* expressions like "[@attr = 'a" and position() = 1],
10319*7c568831SAndroid Build Coastguard Worker 	* and even not the usage of position() in
10320*7c568831SAndroid Build Coastguard Worker 	* "[position() = 1]"; thus - obviously - a position-range,
10321*7c568831SAndroid Build Coastguard Worker 	* like it "[position() < 5]", is also not detected.
10322*7c568831SAndroid Build Coastguard Worker 	* Maybe we could rewrite the AST to ease the optimization.
10323*7c568831SAndroid Build Coastguard Worker 	*/
10324*7c568831SAndroid Build Coastguard Worker 
10325*7c568831SAndroid Build Coastguard Worker         if ((floatval > INT_MIN) && (floatval < INT_MAX)) {
10326*7c568831SAndroid Build Coastguard Worker 	    *maxPos = (int) floatval;
10327*7c568831SAndroid Build Coastguard Worker             if (floatval == (double) *maxPos)
10328*7c568831SAndroid Build Coastguard Worker                 return(1);
10329*7c568831SAndroid Build Coastguard Worker         }
10330*7c568831SAndroid Build Coastguard Worker     }
10331*7c568831SAndroid Build Coastguard Worker     return(0);
10332*7c568831SAndroid Build Coastguard Worker }
10333*7c568831SAndroid Build Coastguard Worker 
10334*7c568831SAndroid Build Coastguard Worker static int
xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first,xmlNodePtr * last,int toBool)10335*7c568831SAndroid Build Coastguard Worker xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
10336*7c568831SAndroid Build Coastguard Worker                            xmlXPathStepOpPtr op,
10337*7c568831SAndroid Build Coastguard Worker 			   xmlNodePtr * first, xmlNodePtr * last,
10338*7c568831SAndroid Build Coastguard Worker 			   int toBool)
10339*7c568831SAndroid Build Coastguard Worker {
10340*7c568831SAndroid Build Coastguard Worker 
10341*7c568831SAndroid Build Coastguard Worker #define XP_TEST_HIT \
10342*7c568831SAndroid Build Coastguard Worker     if (hasAxisRange != 0) { \
10343*7c568831SAndroid Build Coastguard Worker 	if (++pos == maxPos) { \
10344*7c568831SAndroid Build Coastguard Worker 	    if (addNode(seq, cur) < 0) \
10345*7c568831SAndroid Build Coastguard Worker 	        xmlXPathPErrMemory(ctxt); \
10346*7c568831SAndroid Build Coastguard Worker 	    goto axis_range_end; } \
10347*7c568831SAndroid Build Coastguard Worker     } else { \
10348*7c568831SAndroid Build Coastguard Worker 	if (addNode(seq, cur) < 0) \
10349*7c568831SAndroid Build Coastguard Worker 	    xmlXPathPErrMemory(ctxt); \
10350*7c568831SAndroid Build Coastguard Worker 	if (breakOnFirstHit) goto first_hit; }
10351*7c568831SAndroid Build Coastguard Worker 
10352*7c568831SAndroid Build Coastguard Worker #define XP_TEST_HIT_NS \
10353*7c568831SAndroid Build Coastguard Worker     if (hasAxisRange != 0) { \
10354*7c568831SAndroid Build Coastguard Worker 	if (++pos == maxPos) { \
10355*7c568831SAndroid Build Coastguard Worker 	    hasNsNodes = 1; \
10356*7c568831SAndroid Build Coastguard Worker 	    if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
10357*7c568831SAndroid Build Coastguard Worker 	        xmlXPathPErrMemory(ctxt); \
10358*7c568831SAndroid Build Coastguard Worker 	goto axis_range_end; } \
10359*7c568831SAndroid Build Coastguard Worker     } else { \
10360*7c568831SAndroid Build Coastguard Worker 	hasNsNodes = 1; \
10361*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
10362*7c568831SAndroid Build Coastguard Worker 	    xmlXPathPErrMemory(ctxt); \
10363*7c568831SAndroid Build Coastguard Worker 	if (breakOnFirstHit) goto first_hit; }
10364*7c568831SAndroid Build Coastguard Worker 
10365*7c568831SAndroid Build Coastguard Worker     xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
10366*7c568831SAndroid Build Coastguard Worker     xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
10367*7c568831SAndroid Build Coastguard Worker     xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
10368*7c568831SAndroid Build Coastguard Worker     const xmlChar *prefix = op->value4;
10369*7c568831SAndroid Build Coastguard Worker     const xmlChar *name = op->value5;
10370*7c568831SAndroid Build Coastguard Worker     const xmlChar *URI = NULL;
10371*7c568831SAndroid Build Coastguard Worker 
10372*7c568831SAndroid Build Coastguard Worker     int total = 0, hasNsNodes = 0;
10373*7c568831SAndroid Build Coastguard Worker     /* The popped object holding the context nodes */
10374*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr obj;
10375*7c568831SAndroid Build Coastguard Worker     /* The set of context nodes for the node tests */
10376*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr contextSeq;
10377*7c568831SAndroid Build Coastguard Worker     int contextIdx;
10378*7c568831SAndroid Build Coastguard Worker     xmlNodePtr contextNode;
10379*7c568831SAndroid Build Coastguard Worker     /* The final resulting node set wrt to all context nodes */
10380*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr outSeq;
10381*7c568831SAndroid Build Coastguard Worker     /*
10382*7c568831SAndroid Build Coastguard Worker     * The temporary resulting node set wrt 1 context node.
10383*7c568831SAndroid Build Coastguard Worker     * Used to feed predicate evaluation.
10384*7c568831SAndroid Build Coastguard Worker     */
10385*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr seq;
10386*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur;
10387*7c568831SAndroid Build Coastguard Worker     /* First predicate operator */
10388*7c568831SAndroid Build Coastguard Worker     xmlXPathStepOpPtr predOp;
10389*7c568831SAndroid Build Coastguard Worker     int maxPos; /* The requested position() (when a "[n]" predicate) */
10390*7c568831SAndroid Build Coastguard Worker     int hasPredicateRange, hasAxisRange, pos;
10391*7c568831SAndroid Build Coastguard Worker     int breakOnFirstHit;
10392*7c568831SAndroid Build Coastguard Worker 
10393*7c568831SAndroid Build Coastguard Worker     xmlXPathTraversalFunction next = NULL;
10394*7c568831SAndroid Build Coastguard Worker     int (*addNode) (xmlNodeSetPtr, xmlNodePtr);
10395*7c568831SAndroid Build Coastguard Worker     xmlXPathNodeSetMergeFunction mergeAndClear;
10396*7c568831SAndroid Build Coastguard Worker     xmlNodePtr oldContextNode;
10397*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr xpctxt = ctxt->context;
10398*7c568831SAndroid Build Coastguard Worker 
10399*7c568831SAndroid Build Coastguard Worker 
10400*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE0(XPATH_NODESET);
10401*7c568831SAndroid Build Coastguard Worker     obj = valuePop(ctxt);
10402*7c568831SAndroid Build Coastguard Worker     /*
10403*7c568831SAndroid Build Coastguard Worker     * Setup namespaces.
10404*7c568831SAndroid Build Coastguard Worker     */
10405*7c568831SAndroid Build Coastguard Worker     if (prefix != NULL) {
10406*7c568831SAndroid Build Coastguard Worker         URI = xmlXPathNsLookup(xpctxt, prefix);
10407*7c568831SAndroid Build Coastguard Worker         if (URI == NULL) {
10408*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(xpctxt, obj);
10409*7c568831SAndroid Build Coastguard Worker             XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
10410*7c568831SAndroid Build Coastguard Worker 	}
10411*7c568831SAndroid Build Coastguard Worker     }
10412*7c568831SAndroid Build Coastguard Worker     /*
10413*7c568831SAndroid Build Coastguard Worker     * Setup axis.
10414*7c568831SAndroid Build Coastguard Worker     *
10415*7c568831SAndroid Build Coastguard Worker     * MAYBE FUTURE TODO: merging optimizations:
10416*7c568831SAndroid Build Coastguard Worker     * - If the nodes to be traversed wrt to the initial nodes and
10417*7c568831SAndroid Build Coastguard Worker     *   the current axis cannot overlap, then we could avoid searching
10418*7c568831SAndroid Build Coastguard Worker     *   for duplicates during the merge.
10419*7c568831SAndroid Build Coastguard Worker     *   But the question is how/when to evaluate if they cannot overlap.
10420*7c568831SAndroid Build Coastguard Worker     *   Example: if we know that for two initial nodes, the one is
10421*7c568831SAndroid Build Coastguard Worker     *   not in the ancestor-or-self axis of the other, then we could safely
10422*7c568831SAndroid Build Coastguard Worker     *   avoid a duplicate-aware merge, if the axis to be traversed is e.g.
10423*7c568831SAndroid Build Coastguard Worker     *   the descendant-or-self axis.
10424*7c568831SAndroid Build Coastguard Worker     */
10425*7c568831SAndroid Build Coastguard Worker     mergeAndClear = xmlXPathNodeSetMergeAndClear;
10426*7c568831SAndroid Build Coastguard Worker     switch (axis) {
10427*7c568831SAndroid Build Coastguard Worker         case AXIS_ANCESTOR:
10428*7c568831SAndroid Build Coastguard Worker             first = NULL;
10429*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextAncestor;
10430*7c568831SAndroid Build Coastguard Worker             break;
10431*7c568831SAndroid Build Coastguard Worker         case AXIS_ANCESTOR_OR_SELF:
10432*7c568831SAndroid Build Coastguard Worker             first = NULL;
10433*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextAncestorOrSelf;
10434*7c568831SAndroid Build Coastguard Worker             break;
10435*7c568831SAndroid Build Coastguard Worker         case AXIS_ATTRIBUTE:
10436*7c568831SAndroid Build Coastguard Worker             first = NULL;
10437*7c568831SAndroid Build Coastguard Worker 	    last = NULL;
10438*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextAttribute;
10439*7c568831SAndroid Build Coastguard Worker 	    mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10440*7c568831SAndroid Build Coastguard Worker             break;
10441*7c568831SAndroid Build Coastguard Worker         case AXIS_CHILD:
10442*7c568831SAndroid Build Coastguard Worker 	    last = NULL;
10443*7c568831SAndroid Build Coastguard Worker 	    if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) &&
10444*7c568831SAndroid Build Coastguard Worker 		(type == NODE_TYPE_NODE))
10445*7c568831SAndroid Build Coastguard Worker 	    {
10446*7c568831SAndroid Build Coastguard Worker 		/*
10447*7c568831SAndroid Build Coastguard Worker 		* Optimization if an element node type is 'element'.
10448*7c568831SAndroid Build Coastguard Worker 		*/
10449*7c568831SAndroid Build Coastguard Worker 		next = xmlXPathNextChildElement;
10450*7c568831SAndroid Build Coastguard Worker 	    } else
10451*7c568831SAndroid Build Coastguard Worker 		next = xmlXPathNextChild;
10452*7c568831SAndroid Build Coastguard Worker 	    mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10453*7c568831SAndroid Build Coastguard Worker             break;
10454*7c568831SAndroid Build Coastguard Worker         case AXIS_DESCENDANT:
10455*7c568831SAndroid Build Coastguard Worker 	    last = NULL;
10456*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextDescendant;
10457*7c568831SAndroid Build Coastguard Worker             break;
10458*7c568831SAndroid Build Coastguard Worker         case AXIS_DESCENDANT_OR_SELF:
10459*7c568831SAndroid Build Coastguard Worker 	    last = NULL;
10460*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextDescendantOrSelf;
10461*7c568831SAndroid Build Coastguard Worker             break;
10462*7c568831SAndroid Build Coastguard Worker         case AXIS_FOLLOWING:
10463*7c568831SAndroid Build Coastguard Worker 	    last = NULL;
10464*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextFollowing;
10465*7c568831SAndroid Build Coastguard Worker             break;
10466*7c568831SAndroid Build Coastguard Worker         case AXIS_FOLLOWING_SIBLING:
10467*7c568831SAndroid Build Coastguard Worker 	    last = NULL;
10468*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextFollowingSibling;
10469*7c568831SAndroid Build Coastguard Worker             break;
10470*7c568831SAndroid Build Coastguard Worker         case AXIS_NAMESPACE:
10471*7c568831SAndroid Build Coastguard Worker             first = NULL;
10472*7c568831SAndroid Build Coastguard Worker 	    last = NULL;
10473*7c568831SAndroid Build Coastguard Worker             next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
10474*7c568831SAndroid Build Coastguard Worker 	    mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10475*7c568831SAndroid Build Coastguard Worker             break;
10476*7c568831SAndroid Build Coastguard Worker         case AXIS_PARENT:
10477*7c568831SAndroid Build Coastguard Worker             first = NULL;
10478*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextParent;
10479*7c568831SAndroid Build Coastguard Worker             break;
10480*7c568831SAndroid Build Coastguard Worker         case AXIS_PRECEDING:
10481*7c568831SAndroid Build Coastguard Worker             first = NULL;
10482*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextPrecedingInternal;
10483*7c568831SAndroid Build Coastguard Worker             break;
10484*7c568831SAndroid Build Coastguard Worker         case AXIS_PRECEDING_SIBLING:
10485*7c568831SAndroid Build Coastguard Worker             first = NULL;
10486*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextPrecedingSibling;
10487*7c568831SAndroid Build Coastguard Worker             break;
10488*7c568831SAndroid Build Coastguard Worker         case AXIS_SELF:
10489*7c568831SAndroid Build Coastguard Worker             first = NULL;
10490*7c568831SAndroid Build Coastguard Worker 	    last = NULL;
10491*7c568831SAndroid Build Coastguard Worker             next = xmlXPathNextSelf;
10492*7c568831SAndroid Build Coastguard Worker 	    mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10493*7c568831SAndroid Build Coastguard Worker             break;
10494*7c568831SAndroid Build Coastguard Worker     }
10495*7c568831SAndroid Build Coastguard Worker 
10496*7c568831SAndroid Build Coastguard Worker     if (next == NULL) {
10497*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(xpctxt, obj);
10498*7c568831SAndroid Build Coastguard Worker         return(0);
10499*7c568831SAndroid Build Coastguard Worker     }
10500*7c568831SAndroid Build Coastguard Worker     contextSeq = obj->nodesetval;
10501*7c568831SAndroid Build Coastguard Worker     if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) {
10502*7c568831SAndroid Build Coastguard Worker         valuePush(ctxt, obj);
10503*7c568831SAndroid Build Coastguard Worker         return(0);
10504*7c568831SAndroid Build Coastguard Worker     }
10505*7c568831SAndroid Build Coastguard Worker     /*
10506*7c568831SAndroid Build Coastguard Worker     * Predicate optimization ---------------------------------------------
10507*7c568831SAndroid Build Coastguard Worker     * If this step has a last predicate, which contains a position(),
10508*7c568831SAndroid Build Coastguard Worker     * then we'll optimize (although not exactly "position()", but only
10509*7c568831SAndroid Build Coastguard Worker     * the  short-hand form, i.e., "[n]".
10510*7c568831SAndroid Build Coastguard Worker     *
10511*7c568831SAndroid Build Coastguard Worker     * Example - expression "/foo[parent::bar][1]":
10512*7c568831SAndroid Build Coastguard Worker     *
10513*7c568831SAndroid Build Coastguard Worker     * COLLECT 'child' 'name' 'node' foo    -- op (we are here)
10514*7c568831SAndroid Build Coastguard Worker     *   ROOT                               -- op->ch1
10515*7c568831SAndroid Build Coastguard Worker     *   PREDICATE                          -- op->ch2 (predOp)
10516*7c568831SAndroid Build Coastguard Worker     *     PREDICATE                          -- predOp->ch1 = [parent::bar]
10517*7c568831SAndroid Build Coastguard Worker     *       SORT
10518*7c568831SAndroid Build Coastguard Worker     *         COLLECT  'parent' 'name' 'node' bar
10519*7c568831SAndroid Build Coastguard Worker     *           NODE
10520*7c568831SAndroid Build Coastguard Worker     *     ELEM Object is a number : 1        -- predOp->ch2 = [1]
10521*7c568831SAndroid Build Coastguard Worker     *
10522*7c568831SAndroid Build Coastguard Worker     */
10523*7c568831SAndroid Build Coastguard Worker     maxPos = 0;
10524*7c568831SAndroid Build Coastguard Worker     predOp = NULL;
10525*7c568831SAndroid Build Coastguard Worker     hasPredicateRange = 0;
10526*7c568831SAndroid Build Coastguard Worker     hasAxisRange = 0;
10527*7c568831SAndroid Build Coastguard Worker     if (op->ch2 != -1) {
10528*7c568831SAndroid Build Coastguard Worker 	/*
10529*7c568831SAndroid Build Coastguard Worker 	* There's at least one predicate. 16 == XPATH_OP_PREDICATE
10530*7c568831SAndroid Build Coastguard Worker 	*/
10531*7c568831SAndroid Build Coastguard Worker 	predOp = &ctxt->comp->steps[op->ch2];
10532*7c568831SAndroid Build Coastguard Worker 	if (xmlXPathIsPositionalPredicate(ctxt, predOp, &maxPos)) {
10533*7c568831SAndroid Build Coastguard Worker 	    if (predOp->ch1 != -1) {
10534*7c568831SAndroid Build Coastguard Worker 		/*
10535*7c568831SAndroid Build Coastguard Worker 		* Use the next inner predicate operator.
10536*7c568831SAndroid Build Coastguard Worker 		*/
10537*7c568831SAndroid Build Coastguard Worker 		predOp = &ctxt->comp->steps[predOp->ch1];
10538*7c568831SAndroid Build Coastguard Worker 		hasPredicateRange = 1;
10539*7c568831SAndroid Build Coastguard Worker 	    } else {
10540*7c568831SAndroid Build Coastguard Worker 		/*
10541*7c568831SAndroid Build Coastguard Worker 		* There's no other predicate than the [n] predicate.
10542*7c568831SAndroid Build Coastguard Worker 		*/
10543*7c568831SAndroid Build Coastguard Worker 		predOp = NULL;
10544*7c568831SAndroid Build Coastguard Worker 		hasAxisRange = 1;
10545*7c568831SAndroid Build Coastguard Worker 	    }
10546*7c568831SAndroid Build Coastguard Worker 	}
10547*7c568831SAndroid Build Coastguard Worker     }
10548*7c568831SAndroid Build Coastguard Worker     breakOnFirstHit = ((toBool) && (predOp == NULL)) ? 1 : 0;
10549*7c568831SAndroid Build Coastguard Worker     /*
10550*7c568831SAndroid Build Coastguard Worker     * Axis traversal -----------------------------------------------------
10551*7c568831SAndroid Build Coastguard Worker     */
10552*7c568831SAndroid Build Coastguard Worker     /*
10553*7c568831SAndroid Build Coastguard Worker      * 2.3 Node Tests
10554*7c568831SAndroid Build Coastguard Worker      *  - For the attribute axis, the principal node type is attribute.
10555*7c568831SAndroid Build Coastguard Worker      *  - For the namespace axis, the principal node type is namespace.
10556*7c568831SAndroid Build Coastguard Worker      *  - For other axes, the principal node type is element.
10557*7c568831SAndroid Build Coastguard Worker      *
10558*7c568831SAndroid Build Coastguard Worker      * A node test * is true for any node of the
10559*7c568831SAndroid Build Coastguard Worker      * principal node type. For example, child::* will
10560*7c568831SAndroid Build Coastguard Worker      * select all element children of the context node
10561*7c568831SAndroid Build Coastguard Worker      */
10562*7c568831SAndroid Build Coastguard Worker     oldContextNode = xpctxt->node;
10563*7c568831SAndroid Build Coastguard Worker     addNode = xmlXPathNodeSetAddUnique;
10564*7c568831SAndroid Build Coastguard Worker     outSeq = NULL;
10565*7c568831SAndroid Build Coastguard Worker     seq = NULL;
10566*7c568831SAndroid Build Coastguard Worker     contextNode = NULL;
10567*7c568831SAndroid Build Coastguard Worker     contextIdx = 0;
10568*7c568831SAndroid Build Coastguard Worker 
10569*7c568831SAndroid Build Coastguard Worker 
10570*7c568831SAndroid Build Coastguard Worker     while (((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) &&
10571*7c568831SAndroid Build Coastguard Worker            (ctxt->error == XPATH_EXPRESSION_OK)) {
10572*7c568831SAndroid Build Coastguard Worker 	xpctxt->node = contextSeq->nodeTab[contextIdx++];
10573*7c568831SAndroid Build Coastguard Worker 
10574*7c568831SAndroid Build Coastguard Worker 	if (seq == NULL) {
10575*7c568831SAndroid Build Coastguard Worker 	    seq = xmlXPathNodeSetCreate(NULL);
10576*7c568831SAndroid Build Coastguard Worker 	    if (seq == NULL) {
10577*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
10578*7c568831SAndroid Build Coastguard Worker 		total = 0;
10579*7c568831SAndroid Build Coastguard Worker 		goto error;
10580*7c568831SAndroid Build Coastguard Worker 	    }
10581*7c568831SAndroid Build Coastguard Worker 	}
10582*7c568831SAndroid Build Coastguard Worker 	/*
10583*7c568831SAndroid Build Coastguard Worker 	* Traverse the axis and test the nodes.
10584*7c568831SAndroid Build Coastguard Worker 	*/
10585*7c568831SAndroid Build Coastguard Worker 	pos = 0;
10586*7c568831SAndroid Build Coastguard Worker 	cur = NULL;
10587*7c568831SAndroid Build Coastguard Worker 	hasNsNodes = 0;
10588*7c568831SAndroid Build Coastguard Worker         do {
10589*7c568831SAndroid Build Coastguard Worker             if (OP_LIMIT_EXCEEDED(ctxt, 1))
10590*7c568831SAndroid Build Coastguard Worker                 goto error;
10591*7c568831SAndroid Build Coastguard Worker 
10592*7c568831SAndroid Build Coastguard Worker             cur = next(ctxt, cur);
10593*7c568831SAndroid Build Coastguard Worker             if (cur == NULL)
10594*7c568831SAndroid Build Coastguard Worker                 break;
10595*7c568831SAndroid Build Coastguard Worker 
10596*7c568831SAndroid Build Coastguard Worker 	    /*
10597*7c568831SAndroid Build Coastguard Worker 	    * QUESTION TODO: What does the "first" and "last" stuff do?
10598*7c568831SAndroid Build Coastguard Worker 	    */
10599*7c568831SAndroid Build Coastguard Worker             if ((first != NULL) && (*first != NULL)) {
10600*7c568831SAndroid Build Coastguard Worker 		if (*first == cur)
10601*7c568831SAndroid Build Coastguard Worker 		    break;
10602*7c568831SAndroid Build Coastguard Worker 		if (((total % 256) == 0) &&
10603*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
10604*7c568831SAndroid Build Coastguard Worker 		    (xmlXPathCmpNodesExt(*first, cur) >= 0))
10605*7c568831SAndroid Build Coastguard Worker #else
10606*7c568831SAndroid Build Coastguard Worker 		    (xmlXPathCmpNodes(*first, cur) >= 0))
10607*7c568831SAndroid Build Coastguard Worker #endif
10608*7c568831SAndroid Build Coastguard Worker 		{
10609*7c568831SAndroid Build Coastguard Worker 		    break;
10610*7c568831SAndroid Build Coastguard Worker 		}
10611*7c568831SAndroid Build Coastguard Worker 	    }
10612*7c568831SAndroid Build Coastguard Worker 	    if ((last != NULL) && (*last != NULL)) {
10613*7c568831SAndroid Build Coastguard Worker 		if (*last == cur)
10614*7c568831SAndroid Build Coastguard Worker 		    break;
10615*7c568831SAndroid Build Coastguard Worker 		if (((total % 256) == 0) &&
10616*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
10617*7c568831SAndroid Build Coastguard Worker 		    (xmlXPathCmpNodesExt(cur, *last) >= 0))
10618*7c568831SAndroid Build Coastguard Worker #else
10619*7c568831SAndroid Build Coastguard Worker 		    (xmlXPathCmpNodes(cur, *last) >= 0))
10620*7c568831SAndroid Build Coastguard Worker #endif
10621*7c568831SAndroid Build Coastguard Worker 		{
10622*7c568831SAndroid Build Coastguard Worker 		    break;
10623*7c568831SAndroid Build Coastguard Worker 		}
10624*7c568831SAndroid Build Coastguard Worker 	    }
10625*7c568831SAndroid Build Coastguard Worker 
10626*7c568831SAndroid Build Coastguard Worker             total++;
10627*7c568831SAndroid Build Coastguard Worker 
10628*7c568831SAndroid Build Coastguard Worker 	    switch (test) {
10629*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_NONE:
10630*7c568831SAndroid Build Coastguard Worker 		    total = 0;
10631*7c568831SAndroid Build Coastguard Worker 		    goto error;
10632*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_TYPE:
10633*7c568831SAndroid Build Coastguard Worker 		    if (type == NODE_TYPE_NODE) {
10634*7c568831SAndroid Build Coastguard Worker 			switch (cur->type) {
10635*7c568831SAndroid Build Coastguard Worker 			    case XML_DOCUMENT_NODE:
10636*7c568831SAndroid Build Coastguard Worker 			    case XML_HTML_DOCUMENT_NODE:
10637*7c568831SAndroid Build Coastguard Worker 			    case XML_ELEMENT_NODE:
10638*7c568831SAndroid Build Coastguard Worker 			    case XML_ATTRIBUTE_NODE:
10639*7c568831SAndroid Build Coastguard Worker 			    case XML_PI_NODE:
10640*7c568831SAndroid Build Coastguard Worker 			    case XML_COMMENT_NODE:
10641*7c568831SAndroid Build Coastguard Worker 			    case XML_CDATA_SECTION_NODE:
10642*7c568831SAndroid Build Coastguard Worker 			    case XML_TEXT_NODE:
10643*7c568831SAndroid Build Coastguard Worker 				XP_TEST_HIT
10644*7c568831SAndroid Build Coastguard Worker 				break;
10645*7c568831SAndroid Build Coastguard Worker 			    case XML_NAMESPACE_DECL: {
10646*7c568831SAndroid Build Coastguard Worker 				if (axis == AXIS_NAMESPACE) {
10647*7c568831SAndroid Build Coastguard Worker 				    XP_TEST_HIT_NS
10648*7c568831SAndroid Build Coastguard Worker 				} else {
10649*7c568831SAndroid Build Coastguard Worker 	                            hasNsNodes = 1;
10650*7c568831SAndroid Build Coastguard Worker 				    XP_TEST_HIT
10651*7c568831SAndroid Build Coastguard Worker 				}
10652*7c568831SAndroid Build Coastguard Worker 				break;
10653*7c568831SAndroid Build Coastguard Worker                             }
10654*7c568831SAndroid Build Coastguard Worker 			    default:
10655*7c568831SAndroid Build Coastguard Worker 				break;
10656*7c568831SAndroid Build Coastguard Worker 			}
10657*7c568831SAndroid Build Coastguard Worker 		    } else if (cur->type == (xmlElementType) type) {
10658*7c568831SAndroid Build Coastguard Worker 			if (cur->type == XML_NAMESPACE_DECL)
10659*7c568831SAndroid Build Coastguard Worker 			    XP_TEST_HIT_NS
10660*7c568831SAndroid Build Coastguard Worker 			else
10661*7c568831SAndroid Build Coastguard Worker 			    XP_TEST_HIT
10662*7c568831SAndroid Build Coastguard Worker 		    } else if ((type == NODE_TYPE_TEXT) &&
10663*7c568831SAndroid Build Coastguard Worker 			 (cur->type == XML_CDATA_SECTION_NODE))
10664*7c568831SAndroid Build Coastguard Worker 		    {
10665*7c568831SAndroid Build Coastguard Worker 			XP_TEST_HIT
10666*7c568831SAndroid Build Coastguard Worker 		    }
10667*7c568831SAndroid Build Coastguard Worker 		    break;
10668*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_PI:
10669*7c568831SAndroid Build Coastguard Worker                     if ((cur->type == XML_PI_NODE) &&
10670*7c568831SAndroid Build Coastguard Worker                         ((name == NULL) || xmlStrEqual(name, cur->name)))
10671*7c568831SAndroid Build Coastguard Worker 		    {
10672*7c568831SAndroid Build Coastguard Worker 			XP_TEST_HIT
10673*7c568831SAndroid Build Coastguard Worker                     }
10674*7c568831SAndroid Build Coastguard Worker                     break;
10675*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_ALL:
10676*7c568831SAndroid Build Coastguard Worker                     if (axis == AXIS_ATTRIBUTE) {
10677*7c568831SAndroid Build Coastguard Worker                         if (cur->type == XML_ATTRIBUTE_NODE)
10678*7c568831SAndroid Build Coastguard Worker 			{
10679*7c568831SAndroid Build Coastguard Worker                             if (prefix == NULL)
10680*7c568831SAndroid Build Coastguard Worker 			    {
10681*7c568831SAndroid Build Coastguard Worker 				XP_TEST_HIT
10682*7c568831SAndroid Build Coastguard Worker                             } else if ((cur->ns != NULL) &&
10683*7c568831SAndroid Build Coastguard Worker 				(xmlStrEqual(URI, cur->ns->href)))
10684*7c568831SAndroid Build Coastguard Worker 			    {
10685*7c568831SAndroid Build Coastguard Worker 				XP_TEST_HIT
10686*7c568831SAndroid Build Coastguard Worker                             }
10687*7c568831SAndroid Build Coastguard Worker                         }
10688*7c568831SAndroid Build Coastguard Worker                     } else if (axis == AXIS_NAMESPACE) {
10689*7c568831SAndroid Build Coastguard Worker                         if (cur->type == XML_NAMESPACE_DECL)
10690*7c568831SAndroid Build Coastguard Worker 			{
10691*7c568831SAndroid Build Coastguard Worker 			    XP_TEST_HIT_NS
10692*7c568831SAndroid Build Coastguard Worker                         }
10693*7c568831SAndroid Build Coastguard Worker                     } else {
10694*7c568831SAndroid Build Coastguard Worker                         if (cur->type == XML_ELEMENT_NODE) {
10695*7c568831SAndroid Build Coastguard Worker                             if (prefix == NULL)
10696*7c568831SAndroid Build Coastguard Worker 			    {
10697*7c568831SAndroid Build Coastguard Worker 				XP_TEST_HIT
10698*7c568831SAndroid Build Coastguard Worker 
10699*7c568831SAndroid Build Coastguard Worker                             } else if ((cur->ns != NULL) &&
10700*7c568831SAndroid Build Coastguard Worker 				(xmlStrEqual(URI, cur->ns->href)))
10701*7c568831SAndroid Build Coastguard Worker 			    {
10702*7c568831SAndroid Build Coastguard Worker 				XP_TEST_HIT
10703*7c568831SAndroid Build Coastguard Worker                             }
10704*7c568831SAndroid Build Coastguard Worker                         }
10705*7c568831SAndroid Build Coastguard Worker                     }
10706*7c568831SAndroid Build Coastguard Worker                     break;
10707*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_NS:{
10708*7c568831SAndroid Build Coastguard Worker                         /* TODO */
10709*7c568831SAndroid Build Coastguard Worker                         break;
10710*7c568831SAndroid Build Coastguard Worker                     }
10711*7c568831SAndroid Build Coastguard Worker                 case NODE_TEST_NAME:
10712*7c568831SAndroid Build Coastguard Worker                     if (axis == AXIS_ATTRIBUTE) {
10713*7c568831SAndroid Build Coastguard Worker                         if (cur->type != XML_ATTRIBUTE_NODE)
10714*7c568831SAndroid Build Coastguard Worker 			    break;
10715*7c568831SAndroid Build Coastguard Worker 		    } else if (axis == AXIS_NAMESPACE) {
10716*7c568831SAndroid Build Coastguard Worker                         if (cur->type != XML_NAMESPACE_DECL)
10717*7c568831SAndroid Build Coastguard Worker 			    break;
10718*7c568831SAndroid Build Coastguard Worker 		    } else {
10719*7c568831SAndroid Build Coastguard Worker 		        if (cur->type != XML_ELEMENT_NODE)
10720*7c568831SAndroid Build Coastguard Worker 			    break;
10721*7c568831SAndroid Build Coastguard Worker 		    }
10722*7c568831SAndroid Build Coastguard Worker                     switch (cur->type) {
10723*7c568831SAndroid Build Coastguard Worker                         case XML_ELEMENT_NODE:
10724*7c568831SAndroid Build Coastguard Worker                             if (xmlStrEqual(name, cur->name)) {
10725*7c568831SAndroid Build Coastguard Worker                                 if (prefix == NULL) {
10726*7c568831SAndroid Build Coastguard Worker                                     if (cur->ns == NULL)
10727*7c568831SAndroid Build Coastguard Worker 				    {
10728*7c568831SAndroid Build Coastguard Worker 					XP_TEST_HIT
10729*7c568831SAndroid Build Coastguard Worker                                     }
10730*7c568831SAndroid Build Coastguard Worker                                 } else {
10731*7c568831SAndroid Build Coastguard Worker                                     if ((cur->ns != NULL) &&
10732*7c568831SAndroid Build Coastguard Worker                                         (xmlStrEqual(URI, cur->ns->href)))
10733*7c568831SAndroid Build Coastguard Worker 				    {
10734*7c568831SAndroid Build Coastguard Worker 					XP_TEST_HIT
10735*7c568831SAndroid Build Coastguard Worker                                     }
10736*7c568831SAndroid Build Coastguard Worker                                 }
10737*7c568831SAndroid Build Coastguard Worker                             }
10738*7c568831SAndroid Build Coastguard Worker                             break;
10739*7c568831SAndroid Build Coastguard Worker                         case XML_ATTRIBUTE_NODE:{
10740*7c568831SAndroid Build Coastguard Worker                                 xmlAttrPtr attr = (xmlAttrPtr) cur;
10741*7c568831SAndroid Build Coastguard Worker 
10742*7c568831SAndroid Build Coastguard Worker                                 if (xmlStrEqual(name, attr->name)) {
10743*7c568831SAndroid Build Coastguard Worker                                     if (prefix == NULL) {
10744*7c568831SAndroid Build Coastguard Worker                                         if ((attr->ns == NULL) ||
10745*7c568831SAndroid Build Coastguard Worker                                             (attr->ns->prefix == NULL))
10746*7c568831SAndroid Build Coastguard Worker 					{
10747*7c568831SAndroid Build Coastguard Worker 					    XP_TEST_HIT
10748*7c568831SAndroid Build Coastguard Worker                                         }
10749*7c568831SAndroid Build Coastguard Worker                                     } else {
10750*7c568831SAndroid Build Coastguard Worker                                         if ((attr->ns != NULL) &&
10751*7c568831SAndroid Build Coastguard Worker                                             (xmlStrEqual(URI,
10752*7c568831SAndroid Build Coastguard Worker 					      attr->ns->href)))
10753*7c568831SAndroid Build Coastguard Worker 					{
10754*7c568831SAndroid Build Coastguard Worker 					    XP_TEST_HIT
10755*7c568831SAndroid Build Coastguard Worker                                         }
10756*7c568831SAndroid Build Coastguard Worker                                     }
10757*7c568831SAndroid Build Coastguard Worker                                 }
10758*7c568831SAndroid Build Coastguard Worker                                 break;
10759*7c568831SAndroid Build Coastguard Worker                             }
10760*7c568831SAndroid Build Coastguard Worker                         case XML_NAMESPACE_DECL:
10761*7c568831SAndroid Build Coastguard Worker                             if (cur->type == XML_NAMESPACE_DECL) {
10762*7c568831SAndroid Build Coastguard Worker                                 xmlNsPtr ns = (xmlNsPtr) cur;
10763*7c568831SAndroid Build Coastguard Worker 
10764*7c568831SAndroid Build Coastguard Worker                                 if ((ns->prefix != NULL) && (name != NULL)
10765*7c568831SAndroid Build Coastguard Worker                                     && (xmlStrEqual(ns->prefix, name)))
10766*7c568831SAndroid Build Coastguard Worker 				{
10767*7c568831SAndroid Build Coastguard Worker 				    XP_TEST_HIT_NS
10768*7c568831SAndroid Build Coastguard Worker                                 }
10769*7c568831SAndroid Build Coastguard Worker                             }
10770*7c568831SAndroid Build Coastguard Worker                             break;
10771*7c568831SAndroid Build Coastguard Worker                         default:
10772*7c568831SAndroid Build Coastguard Worker                             break;
10773*7c568831SAndroid Build Coastguard Worker                     }
10774*7c568831SAndroid Build Coastguard Worker                     break;
10775*7c568831SAndroid Build Coastguard Worker 	    } /* switch(test) */
10776*7c568831SAndroid Build Coastguard Worker         } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK));
10777*7c568831SAndroid Build Coastguard Worker 
10778*7c568831SAndroid Build Coastguard Worker 	goto apply_predicates;
10779*7c568831SAndroid Build Coastguard Worker 
10780*7c568831SAndroid Build Coastguard Worker axis_range_end: /* ----------------------------------------------------- */
10781*7c568831SAndroid Build Coastguard Worker 	/*
10782*7c568831SAndroid Build Coastguard Worker 	* We have a "/foo[n]", and position() = n was reached.
10783*7c568831SAndroid Build Coastguard Worker 	* Note that we can have as well "/foo/::parent::foo[1]", so
10784*7c568831SAndroid Build Coastguard Worker 	* a duplicate-aware merge is still needed.
10785*7c568831SAndroid Build Coastguard Worker 	* Merge with the result.
10786*7c568831SAndroid Build Coastguard Worker 	*/
10787*7c568831SAndroid Build Coastguard Worker 	if (outSeq == NULL) {
10788*7c568831SAndroid Build Coastguard Worker 	    outSeq = seq;
10789*7c568831SAndroid Build Coastguard Worker 	    seq = NULL;
10790*7c568831SAndroid Build Coastguard Worker 	} else {
10791*7c568831SAndroid Build Coastguard Worker 	    outSeq = mergeAndClear(outSeq, seq);
10792*7c568831SAndroid Build Coastguard Worker             if (outSeq == NULL)
10793*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
10794*7c568831SAndroid Build Coastguard Worker         }
10795*7c568831SAndroid Build Coastguard Worker 	/*
10796*7c568831SAndroid Build Coastguard Worker 	* Break if only a true/false result was requested.
10797*7c568831SAndroid Build Coastguard Worker 	*/
10798*7c568831SAndroid Build Coastguard Worker 	if (toBool)
10799*7c568831SAndroid Build Coastguard Worker 	    break;
10800*7c568831SAndroid Build Coastguard Worker 	continue;
10801*7c568831SAndroid Build Coastguard Worker 
10802*7c568831SAndroid Build Coastguard Worker first_hit: /* ---------------------------------------------------------- */
10803*7c568831SAndroid Build Coastguard Worker 	/*
10804*7c568831SAndroid Build Coastguard Worker 	* Break if only a true/false result was requested and
10805*7c568831SAndroid Build Coastguard Worker 	* no predicates existed and a node test succeeded.
10806*7c568831SAndroid Build Coastguard Worker 	*/
10807*7c568831SAndroid Build Coastguard Worker 	if (outSeq == NULL) {
10808*7c568831SAndroid Build Coastguard Worker 	    outSeq = seq;
10809*7c568831SAndroid Build Coastguard Worker 	    seq = NULL;
10810*7c568831SAndroid Build Coastguard Worker 	} else {
10811*7c568831SAndroid Build Coastguard Worker 	    outSeq = mergeAndClear(outSeq, seq);
10812*7c568831SAndroid Build Coastguard Worker             if (outSeq == NULL)
10813*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
10814*7c568831SAndroid Build Coastguard Worker         }
10815*7c568831SAndroid Build Coastguard Worker 	break;
10816*7c568831SAndroid Build Coastguard Worker 
10817*7c568831SAndroid Build Coastguard Worker apply_predicates: /* --------------------------------------------------- */
10818*7c568831SAndroid Build Coastguard Worker         if (ctxt->error != XPATH_EXPRESSION_OK)
10819*7c568831SAndroid Build Coastguard Worker 	    goto error;
10820*7c568831SAndroid Build Coastguard Worker 
10821*7c568831SAndroid Build Coastguard Worker         /*
10822*7c568831SAndroid Build Coastguard Worker 	* Apply predicates.
10823*7c568831SAndroid Build Coastguard Worker 	*/
10824*7c568831SAndroid Build Coastguard Worker         if ((predOp != NULL) && (seq->nodeNr > 0)) {
10825*7c568831SAndroid Build Coastguard Worker 	    /*
10826*7c568831SAndroid Build Coastguard Worker 	    * E.g. when we have a "/foo[some expression][n]".
10827*7c568831SAndroid Build Coastguard Worker 	    */
10828*7c568831SAndroid Build Coastguard Worker 	    /*
10829*7c568831SAndroid Build Coastguard Worker 	    * QUESTION TODO: The old predicate evaluation took into
10830*7c568831SAndroid Build Coastguard Worker 	    *  account location-sets.
10831*7c568831SAndroid Build Coastguard Worker 	    *  (E.g. ctxt->value->type == XPATH_LOCATIONSET)
10832*7c568831SAndroid Build Coastguard Worker 	    *  Do we expect such a set here?
10833*7c568831SAndroid Build Coastguard Worker 	    *  All what I learned now from the evaluation semantics
10834*7c568831SAndroid Build Coastguard Worker 	    *  does not indicate that a location-set will be processed
10835*7c568831SAndroid Build Coastguard Worker 	    *  here, so this looks OK.
10836*7c568831SAndroid Build Coastguard Worker 	    */
10837*7c568831SAndroid Build Coastguard Worker 	    /*
10838*7c568831SAndroid Build Coastguard Worker 	    * Iterate over all predicates, starting with the outermost
10839*7c568831SAndroid Build Coastguard Worker 	    * predicate.
10840*7c568831SAndroid Build Coastguard Worker 	    * TODO: Problem: we cannot execute the inner predicates first
10841*7c568831SAndroid Build Coastguard Worker 	    *  since we cannot go back *up* the operator tree!
10842*7c568831SAndroid Build Coastguard Worker 	    *  Options we have:
10843*7c568831SAndroid Build Coastguard Worker 	    *  1) Use of recursive functions (like is it currently done
10844*7c568831SAndroid Build Coastguard Worker 	    *     via xmlXPathCompOpEval())
10845*7c568831SAndroid Build Coastguard Worker 	    *  2) Add a predicate evaluation information stack to the
10846*7c568831SAndroid Build Coastguard Worker 	    *     context struct
10847*7c568831SAndroid Build Coastguard Worker 	    *  3) Change the way the operators are linked; we need a
10848*7c568831SAndroid Build Coastguard Worker 	    *     "parent" field on xmlXPathStepOp
10849*7c568831SAndroid Build Coastguard Worker 	    *
10850*7c568831SAndroid Build Coastguard Worker 	    * For the moment, I'll try to solve this with a recursive
10851*7c568831SAndroid Build Coastguard Worker 	    * function: xmlXPathCompOpEvalPredicate().
10852*7c568831SAndroid Build Coastguard Worker 	    */
10853*7c568831SAndroid Build Coastguard Worker 	    if (hasPredicateRange != 0)
10854*7c568831SAndroid Build Coastguard Worker 		xmlXPathCompOpEvalPredicate(ctxt, predOp, seq, maxPos, maxPos,
10855*7c568831SAndroid Build Coastguard Worker 					    hasNsNodes);
10856*7c568831SAndroid Build Coastguard Worker 	    else
10857*7c568831SAndroid Build Coastguard Worker 		xmlXPathCompOpEvalPredicate(ctxt, predOp, seq, 1, seq->nodeNr,
10858*7c568831SAndroid Build Coastguard Worker 					    hasNsNodes);
10859*7c568831SAndroid Build Coastguard Worker 
10860*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->error != XPATH_EXPRESSION_OK) {
10861*7c568831SAndroid Build Coastguard Worker 		total = 0;
10862*7c568831SAndroid Build Coastguard Worker 		goto error;
10863*7c568831SAndroid Build Coastguard Worker 	    }
10864*7c568831SAndroid Build Coastguard Worker         }
10865*7c568831SAndroid Build Coastguard Worker 
10866*7c568831SAndroid Build Coastguard Worker         if (seq->nodeNr > 0) {
10867*7c568831SAndroid Build Coastguard Worker 	    /*
10868*7c568831SAndroid Build Coastguard Worker 	    * Add to result set.
10869*7c568831SAndroid Build Coastguard Worker 	    */
10870*7c568831SAndroid Build Coastguard Worker 	    if (outSeq == NULL) {
10871*7c568831SAndroid Build Coastguard Worker 		outSeq = seq;
10872*7c568831SAndroid Build Coastguard Worker 		seq = NULL;
10873*7c568831SAndroid Build Coastguard Worker 	    } else {
10874*7c568831SAndroid Build Coastguard Worker 		outSeq = mergeAndClear(outSeq, seq);
10875*7c568831SAndroid Build Coastguard Worker                 if (outSeq == NULL)
10876*7c568831SAndroid Build Coastguard Worker                     xmlXPathPErrMemory(ctxt);
10877*7c568831SAndroid Build Coastguard Worker 	    }
10878*7c568831SAndroid Build Coastguard Worker 
10879*7c568831SAndroid Build Coastguard Worker             if (toBool)
10880*7c568831SAndroid Build Coastguard Worker                 break;
10881*7c568831SAndroid Build Coastguard Worker 	}
10882*7c568831SAndroid Build Coastguard Worker     }
10883*7c568831SAndroid Build Coastguard Worker 
10884*7c568831SAndroid Build Coastguard Worker error:
10885*7c568831SAndroid Build Coastguard Worker     if ((obj->boolval) && (obj->user != NULL)) {
10886*7c568831SAndroid Build Coastguard Worker 	/*
10887*7c568831SAndroid Build Coastguard Worker 	* QUESTION TODO: What does this do and why?
10888*7c568831SAndroid Build Coastguard Worker 	* TODO: Do we have to do this also for the "error"
10889*7c568831SAndroid Build Coastguard Worker 	* cleanup further down?
10890*7c568831SAndroid Build Coastguard Worker 	*/
10891*7c568831SAndroid Build Coastguard Worker 	ctxt->value->boolval = 1;
10892*7c568831SAndroid Build Coastguard Worker 	ctxt->value->user = obj->user;
10893*7c568831SAndroid Build Coastguard Worker 	obj->user = NULL;
10894*7c568831SAndroid Build Coastguard Worker 	obj->boolval = 0;
10895*7c568831SAndroid Build Coastguard Worker     }
10896*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(xpctxt, obj);
10897*7c568831SAndroid Build Coastguard Worker 
10898*7c568831SAndroid Build Coastguard Worker     /*
10899*7c568831SAndroid Build Coastguard Worker     * Ensure we return at least an empty set.
10900*7c568831SAndroid Build Coastguard Worker     */
10901*7c568831SAndroid Build Coastguard Worker     if (outSeq == NULL) {
10902*7c568831SAndroid Build Coastguard Worker 	if ((seq != NULL) && (seq->nodeNr == 0)) {
10903*7c568831SAndroid Build Coastguard Worker 	    outSeq = seq;
10904*7c568831SAndroid Build Coastguard Worker         } else {
10905*7c568831SAndroid Build Coastguard Worker 	    outSeq = xmlXPathNodeSetCreate(NULL);
10906*7c568831SAndroid Build Coastguard Worker             if (outSeq == NULL)
10907*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(ctxt);
10908*7c568831SAndroid Build Coastguard Worker         }
10909*7c568831SAndroid Build Coastguard Worker     }
10910*7c568831SAndroid Build Coastguard Worker     if ((seq != NULL) && (seq != outSeq)) {
10911*7c568831SAndroid Build Coastguard Worker 	 xmlXPathFreeNodeSet(seq);
10912*7c568831SAndroid Build Coastguard Worker     }
10913*7c568831SAndroid Build Coastguard Worker     /*
10914*7c568831SAndroid Build Coastguard Worker     * Hand over the result. Better to push the set also in
10915*7c568831SAndroid Build Coastguard Worker     * case of errors.
10916*7c568831SAndroid Build Coastguard Worker     */
10917*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, outSeq));
10918*7c568831SAndroid Build Coastguard Worker     /*
10919*7c568831SAndroid Build Coastguard Worker     * Reset the context node.
10920*7c568831SAndroid Build Coastguard Worker     */
10921*7c568831SAndroid Build Coastguard Worker     xpctxt->node = oldContextNode;
10922*7c568831SAndroid Build Coastguard Worker     /*
10923*7c568831SAndroid Build Coastguard Worker     * When traversing the namespace axis in "toBool" mode, it's
10924*7c568831SAndroid Build Coastguard Worker     * possible that tmpNsList wasn't freed.
10925*7c568831SAndroid Build Coastguard Worker     */
10926*7c568831SAndroid Build Coastguard Worker     if (xpctxt->tmpNsList != NULL) {
10927*7c568831SAndroid Build Coastguard Worker         xmlFree(xpctxt->tmpNsList);
10928*7c568831SAndroid Build Coastguard Worker         xpctxt->tmpNsList = NULL;
10929*7c568831SAndroid Build Coastguard Worker     }
10930*7c568831SAndroid Build Coastguard Worker 
10931*7c568831SAndroid Build Coastguard Worker     return(total);
10932*7c568831SAndroid Build Coastguard Worker }
10933*7c568831SAndroid Build Coastguard Worker 
10934*7c568831SAndroid Build Coastguard Worker static int
10935*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
10936*7c568831SAndroid Build Coastguard Worker 			      xmlXPathStepOpPtr op, xmlNodePtr * first);
10937*7c568831SAndroid Build Coastguard Worker 
10938*7c568831SAndroid Build Coastguard Worker /**
10939*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompOpEvalFirst:
10940*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath parser context with the compiled expression
10941*7c568831SAndroid Build Coastguard Worker  * @op:  an XPath compiled operation
10942*7c568831SAndroid Build Coastguard Worker  * @first:  the first elem found so far
10943*7c568831SAndroid Build Coastguard Worker  *
10944*7c568831SAndroid Build Coastguard Worker  * Evaluate the Precompiled XPath operation searching only the first
10945*7c568831SAndroid Build Coastguard Worker  * element in document order
10946*7c568831SAndroid Build Coastguard Worker  *
10947*7c568831SAndroid Build Coastguard Worker  * Returns the number of examined objects.
10948*7c568831SAndroid Build Coastguard Worker  */
10949*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first)10950*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
10951*7c568831SAndroid Build Coastguard Worker                         xmlXPathStepOpPtr op, xmlNodePtr * first)
10952*7c568831SAndroid Build Coastguard Worker {
10953*7c568831SAndroid Build Coastguard Worker     int total = 0, cur;
10954*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp;
10955*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg1, arg2;
10956*7c568831SAndroid Build Coastguard Worker 
10957*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR0;
10958*7c568831SAndroid Build Coastguard Worker     if (OP_LIMIT_EXCEEDED(ctxt, 1))
10959*7c568831SAndroid Build Coastguard Worker         return(0);
10960*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
10961*7c568831SAndroid Build Coastguard Worker         XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
10962*7c568831SAndroid Build Coastguard Worker     ctxt->context->depth += 1;
10963*7c568831SAndroid Build Coastguard Worker     comp = ctxt->comp;
10964*7c568831SAndroid Build Coastguard Worker     switch (op->op) {
10965*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_END:
10966*7c568831SAndroid Build Coastguard Worker             break;
10967*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_UNION:
10968*7c568831SAndroid Build Coastguard Worker             total =
10969*7c568831SAndroid Build Coastguard Worker                 xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
10970*7c568831SAndroid Build Coastguard Worker                                         first);
10971*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
10972*7c568831SAndroid Build Coastguard Worker             if ((ctxt->value != NULL)
10973*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->type == XPATH_NODESET)
10974*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->nodesetval != NULL)
10975*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->nodesetval->nodeNr >= 1)) {
10976*7c568831SAndroid Build Coastguard Worker                 /*
10977*7c568831SAndroid Build Coastguard Worker                  * limit tree traversing to first node in the result
10978*7c568831SAndroid Build Coastguard Worker                  */
10979*7c568831SAndroid Build Coastguard Worker 		/*
10980*7c568831SAndroid Build Coastguard Worker 		* OPTIMIZE TODO: This implicitly sorts
10981*7c568831SAndroid Build Coastguard Worker 		*  the result, even if not needed. E.g. if the argument
10982*7c568831SAndroid Build Coastguard Worker 		*  of the count() function, no sorting is needed.
10983*7c568831SAndroid Build Coastguard Worker 		* OPTIMIZE TODO: How do we know if the node-list wasn't
10984*7c568831SAndroid Build Coastguard Worker 		*  already sorted?
10985*7c568831SAndroid Build Coastguard Worker 		*/
10986*7c568831SAndroid Build Coastguard Worker 		if (ctxt->value->nodesetval->nodeNr > 1)
10987*7c568831SAndroid Build Coastguard Worker 		    xmlXPathNodeSetSort(ctxt->value->nodesetval);
10988*7c568831SAndroid Build Coastguard Worker                 *first = ctxt->value->nodesetval->nodeTab[0];
10989*7c568831SAndroid Build Coastguard Worker             }
10990*7c568831SAndroid Build Coastguard Worker             cur =
10991*7c568831SAndroid Build Coastguard Worker                 xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
10992*7c568831SAndroid Build Coastguard Worker                                         first);
10993*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
10994*7c568831SAndroid Build Coastguard Worker 
10995*7c568831SAndroid Build Coastguard Worker             arg2 = valuePop(ctxt);
10996*7c568831SAndroid Build Coastguard Worker             arg1 = valuePop(ctxt);
10997*7c568831SAndroid Build Coastguard Worker             if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
10998*7c568831SAndroid Build Coastguard Worker                 (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
10999*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg1);
11000*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg2);
11001*7c568831SAndroid Build Coastguard Worker                 XP_ERROR0(XPATH_INVALID_TYPE);
11002*7c568831SAndroid Build Coastguard Worker             }
11003*7c568831SAndroid Build Coastguard Worker             if ((ctxt->context->opLimit != 0) &&
11004*7c568831SAndroid Build Coastguard Worker                 (((arg1->nodesetval != NULL) &&
11005*7c568831SAndroid Build Coastguard Worker                   (xmlXPathCheckOpLimit(ctxt,
11006*7c568831SAndroid Build Coastguard Worker                                         arg1->nodesetval->nodeNr) < 0)) ||
11007*7c568831SAndroid Build Coastguard Worker                  ((arg2->nodesetval != NULL) &&
11008*7c568831SAndroid Build Coastguard Worker                   (xmlXPathCheckOpLimit(ctxt,
11009*7c568831SAndroid Build Coastguard Worker                                         arg2->nodesetval->nodeNr) < 0)))) {
11010*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg1);
11011*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg2);
11012*7c568831SAndroid Build Coastguard Worker                 break;
11013*7c568831SAndroid Build Coastguard Worker             }
11014*7c568831SAndroid Build Coastguard Worker 
11015*7c568831SAndroid Build Coastguard Worker             if ((arg2->nodesetval != NULL) &&
11016*7c568831SAndroid Build Coastguard Worker                 (arg2->nodesetval->nodeNr != 0)) {
11017*7c568831SAndroid Build Coastguard Worker                 arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11018*7c568831SAndroid Build Coastguard Worker                                                         arg2->nodesetval);
11019*7c568831SAndroid Build Coastguard Worker                 if (arg1->nodesetval == NULL)
11020*7c568831SAndroid Build Coastguard Worker                     xmlXPathPErrMemory(ctxt);
11021*7c568831SAndroid Build Coastguard Worker             }
11022*7c568831SAndroid Build Coastguard Worker             valuePush(ctxt, arg1);
11023*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg2);
11024*7c568831SAndroid Build Coastguard Worker             total += cur;
11025*7c568831SAndroid Build Coastguard Worker             break;
11026*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_ROOT:
11027*7c568831SAndroid Build Coastguard Worker             xmlXPathRoot(ctxt);
11028*7c568831SAndroid Build Coastguard Worker             break;
11029*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_NODE:
11030*7c568831SAndroid Build Coastguard Worker             if (op->ch1 != -1)
11031*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11032*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11033*7c568831SAndroid Build Coastguard Worker             if (op->ch2 != -1)
11034*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11035*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11036*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11037*7c568831SAndroid Build Coastguard Worker 		ctxt->context->node));
11038*7c568831SAndroid Build Coastguard Worker             break;
11039*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_COLLECT:{
11040*7c568831SAndroid Build Coastguard Worker                 if (op->ch1 == -1)
11041*7c568831SAndroid Build Coastguard Worker                     break;
11042*7c568831SAndroid Build Coastguard Worker 
11043*7c568831SAndroid Build Coastguard Worker                 total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11044*7c568831SAndroid Build Coastguard Worker 		CHECK_ERROR0;
11045*7c568831SAndroid Build Coastguard Worker 
11046*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL, 0);
11047*7c568831SAndroid Build Coastguard Worker                 break;
11048*7c568831SAndroid Build Coastguard Worker             }
11049*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_VALUE:
11050*7c568831SAndroid Build Coastguard Worker             valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11051*7c568831SAndroid Build Coastguard Worker             break;
11052*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_SORT:
11053*7c568831SAndroid Build Coastguard Worker             if (op->ch1 != -1)
11054*7c568831SAndroid Build Coastguard Worker                 total +=
11055*7c568831SAndroid Build Coastguard Worker                     xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
11056*7c568831SAndroid Build Coastguard Worker                                             first);
11057*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11058*7c568831SAndroid Build Coastguard Worker             if ((ctxt->value != NULL)
11059*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->type == XPATH_NODESET)
11060*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->nodesetval != NULL)
11061*7c568831SAndroid Build Coastguard Worker 		&& (ctxt->value->nodesetval->nodeNr > 1))
11062*7c568831SAndroid Build Coastguard Worker                 xmlXPathNodeSetSort(ctxt->value->nodesetval);
11063*7c568831SAndroid Build Coastguard Worker             break;
11064*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
11065*7c568831SAndroid Build Coastguard Worker 	case XPATH_OP_FILTER:
11066*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEvalFilterFirst(ctxt, op, first);
11067*7c568831SAndroid Build Coastguard Worker             break;
11068*7c568831SAndroid Build Coastguard Worker #endif
11069*7c568831SAndroid Build Coastguard Worker         default:
11070*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, op);
11071*7c568831SAndroid Build Coastguard Worker             break;
11072*7c568831SAndroid Build Coastguard Worker     }
11073*7c568831SAndroid Build Coastguard Worker 
11074*7c568831SAndroid Build Coastguard Worker     ctxt->context->depth -= 1;
11075*7c568831SAndroid Build Coastguard Worker     return(total);
11076*7c568831SAndroid Build Coastguard Worker }
11077*7c568831SAndroid Build Coastguard Worker 
11078*7c568831SAndroid Build Coastguard Worker /**
11079*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompOpEvalLast:
11080*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath parser context with the compiled expression
11081*7c568831SAndroid Build Coastguard Worker  * @op:  an XPath compiled operation
11082*7c568831SAndroid Build Coastguard Worker  * @last:  the last elem found so far
11083*7c568831SAndroid Build Coastguard Worker  *
11084*7c568831SAndroid Build Coastguard Worker  * Evaluate the Precompiled XPath operation searching only the last
11085*7c568831SAndroid Build Coastguard Worker  * element in document order
11086*7c568831SAndroid Build Coastguard Worker  *
11087*7c568831SAndroid Build Coastguard Worker  * Returns the number of nodes traversed
11088*7c568831SAndroid Build Coastguard Worker  */
11089*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * last)11090*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
11091*7c568831SAndroid Build Coastguard Worker                        xmlNodePtr * last)
11092*7c568831SAndroid Build Coastguard Worker {
11093*7c568831SAndroid Build Coastguard Worker     int total = 0, cur;
11094*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp;
11095*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg1, arg2;
11096*7c568831SAndroid Build Coastguard Worker 
11097*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR0;
11098*7c568831SAndroid Build Coastguard Worker     if (OP_LIMIT_EXCEEDED(ctxt, 1))
11099*7c568831SAndroid Build Coastguard Worker         return(0);
11100*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
11101*7c568831SAndroid Build Coastguard Worker         XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
11102*7c568831SAndroid Build Coastguard Worker     ctxt->context->depth += 1;
11103*7c568831SAndroid Build Coastguard Worker     comp = ctxt->comp;
11104*7c568831SAndroid Build Coastguard Worker     switch (op->op) {
11105*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_END:
11106*7c568831SAndroid Build Coastguard Worker             break;
11107*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_UNION:
11108*7c568831SAndroid Build Coastguard Worker             total =
11109*7c568831SAndroid Build Coastguard Worker                 xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
11110*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11111*7c568831SAndroid Build Coastguard Worker             if ((ctxt->value != NULL)
11112*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->type == XPATH_NODESET)
11113*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->nodesetval != NULL)
11114*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->nodesetval->nodeNr >= 1)) {
11115*7c568831SAndroid Build Coastguard Worker                 /*
11116*7c568831SAndroid Build Coastguard Worker                  * limit tree traversing to first node in the result
11117*7c568831SAndroid Build Coastguard Worker                  */
11118*7c568831SAndroid Build Coastguard Worker 		if (ctxt->value->nodesetval->nodeNr > 1)
11119*7c568831SAndroid Build Coastguard Worker 		    xmlXPathNodeSetSort(ctxt->value->nodesetval);
11120*7c568831SAndroid Build Coastguard Worker                 *last =
11121*7c568831SAndroid Build Coastguard Worker                     ctxt->value->nodesetval->nodeTab[ctxt->value->
11122*7c568831SAndroid Build Coastguard Worker                                                      nodesetval->nodeNr -
11123*7c568831SAndroid Build Coastguard Worker                                                      1];
11124*7c568831SAndroid Build Coastguard Worker             }
11125*7c568831SAndroid Build Coastguard Worker             cur =
11126*7c568831SAndroid Build Coastguard Worker                 xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
11127*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11128*7c568831SAndroid Build Coastguard Worker             if ((ctxt->value != NULL)
11129*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->type == XPATH_NODESET)
11130*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->nodesetval != NULL)
11131*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->nodesetval->nodeNr >= 1)) { /* TODO: NOP ? */
11132*7c568831SAndroid Build Coastguard Worker             }
11133*7c568831SAndroid Build Coastguard Worker 
11134*7c568831SAndroid Build Coastguard Worker             arg2 = valuePop(ctxt);
11135*7c568831SAndroid Build Coastguard Worker             arg1 = valuePop(ctxt);
11136*7c568831SAndroid Build Coastguard Worker             if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
11137*7c568831SAndroid Build Coastguard Worker                 (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
11138*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg1);
11139*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg2);
11140*7c568831SAndroid Build Coastguard Worker                 XP_ERROR0(XPATH_INVALID_TYPE);
11141*7c568831SAndroid Build Coastguard Worker             }
11142*7c568831SAndroid Build Coastguard Worker             if ((ctxt->context->opLimit != 0) &&
11143*7c568831SAndroid Build Coastguard Worker                 (((arg1->nodesetval != NULL) &&
11144*7c568831SAndroid Build Coastguard Worker                   (xmlXPathCheckOpLimit(ctxt,
11145*7c568831SAndroid Build Coastguard Worker                                         arg1->nodesetval->nodeNr) < 0)) ||
11146*7c568831SAndroid Build Coastguard Worker                  ((arg2->nodesetval != NULL) &&
11147*7c568831SAndroid Build Coastguard Worker                   (xmlXPathCheckOpLimit(ctxt,
11148*7c568831SAndroid Build Coastguard Worker                                         arg2->nodesetval->nodeNr) < 0)))) {
11149*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg1);
11150*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg2);
11151*7c568831SAndroid Build Coastguard Worker                 break;
11152*7c568831SAndroid Build Coastguard Worker             }
11153*7c568831SAndroid Build Coastguard Worker 
11154*7c568831SAndroid Build Coastguard Worker             if ((arg2->nodesetval != NULL) &&
11155*7c568831SAndroid Build Coastguard Worker                 (arg2->nodesetval->nodeNr != 0)) {
11156*7c568831SAndroid Build Coastguard Worker                 arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11157*7c568831SAndroid Build Coastguard Worker                                                         arg2->nodesetval);
11158*7c568831SAndroid Build Coastguard Worker                 if (arg1->nodesetval == NULL)
11159*7c568831SAndroid Build Coastguard Worker                     xmlXPathPErrMemory(ctxt);
11160*7c568831SAndroid Build Coastguard Worker             }
11161*7c568831SAndroid Build Coastguard Worker             valuePush(ctxt, arg1);
11162*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg2);
11163*7c568831SAndroid Build Coastguard Worker             total += cur;
11164*7c568831SAndroid Build Coastguard Worker             break;
11165*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_ROOT:
11166*7c568831SAndroid Build Coastguard Worker             xmlXPathRoot(ctxt);
11167*7c568831SAndroid Build Coastguard Worker             break;
11168*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_NODE:
11169*7c568831SAndroid Build Coastguard Worker             if (op->ch1 != -1)
11170*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11171*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11172*7c568831SAndroid Build Coastguard Worker             if (op->ch2 != -1)
11173*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11174*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11175*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11176*7c568831SAndroid Build Coastguard Worker 		ctxt->context->node));
11177*7c568831SAndroid Build Coastguard Worker             break;
11178*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_COLLECT:{
11179*7c568831SAndroid Build Coastguard Worker                 if (op->ch1 == -1)
11180*7c568831SAndroid Build Coastguard Worker                     break;
11181*7c568831SAndroid Build Coastguard Worker 
11182*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11183*7c568831SAndroid Build Coastguard Worker 		CHECK_ERROR0;
11184*7c568831SAndroid Build Coastguard Worker 
11185*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last, 0);
11186*7c568831SAndroid Build Coastguard Worker                 break;
11187*7c568831SAndroid Build Coastguard Worker             }
11188*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_VALUE:
11189*7c568831SAndroid Build Coastguard Worker             valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11190*7c568831SAndroid Build Coastguard Worker             break;
11191*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_SORT:
11192*7c568831SAndroid Build Coastguard Worker             if (op->ch1 != -1)
11193*7c568831SAndroid Build Coastguard Worker                 total +=
11194*7c568831SAndroid Build Coastguard Worker                     xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1],
11195*7c568831SAndroid Build Coastguard Worker                                            last);
11196*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11197*7c568831SAndroid Build Coastguard Worker             if ((ctxt->value != NULL)
11198*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->type == XPATH_NODESET)
11199*7c568831SAndroid Build Coastguard Worker                 && (ctxt->value->nodesetval != NULL)
11200*7c568831SAndroid Build Coastguard Worker 		&& (ctxt->value->nodesetval->nodeNr > 1))
11201*7c568831SAndroid Build Coastguard Worker                 xmlXPathNodeSetSort(ctxt->value->nodesetval);
11202*7c568831SAndroid Build Coastguard Worker             break;
11203*7c568831SAndroid Build Coastguard Worker         default:
11204*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, op);
11205*7c568831SAndroid Build Coastguard Worker             break;
11206*7c568831SAndroid Build Coastguard Worker     }
11207*7c568831SAndroid Build Coastguard Worker 
11208*7c568831SAndroid Build Coastguard Worker     ctxt->context->depth -= 1;
11209*7c568831SAndroid Build Coastguard Worker     return (total);
11210*7c568831SAndroid Build Coastguard Worker }
11211*7c568831SAndroid Build Coastguard Worker 
11212*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
11213*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first)11214*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
11215*7c568831SAndroid Build Coastguard Worker 			      xmlXPathStepOpPtr op, xmlNodePtr * first)
11216*7c568831SAndroid Build Coastguard Worker {
11217*7c568831SAndroid Build Coastguard Worker     int total = 0;
11218*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp;
11219*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr obj;
11220*7c568831SAndroid Build Coastguard Worker     xmlNodeSetPtr set;
11221*7c568831SAndroid Build Coastguard Worker 
11222*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR0;
11223*7c568831SAndroid Build Coastguard Worker     comp = ctxt->comp;
11224*7c568831SAndroid Build Coastguard Worker     /*
11225*7c568831SAndroid Build Coastguard Worker     * Optimization for ()[last()] selection i.e. the last elem
11226*7c568831SAndroid Build Coastguard Worker     */
11227*7c568831SAndroid Build Coastguard Worker     if ((op->ch1 != -1) && (op->ch2 != -1) &&
11228*7c568831SAndroid Build Coastguard Worker 	(comp->steps[op->ch1].op == XPATH_OP_SORT) &&
11229*7c568831SAndroid Build Coastguard Worker 	(comp->steps[op->ch2].op == XPATH_OP_SORT)) {
11230*7c568831SAndroid Build Coastguard Worker 	int f = comp->steps[op->ch2].ch1;
11231*7c568831SAndroid Build Coastguard Worker 
11232*7c568831SAndroid Build Coastguard Worker 	if ((f != -1) &&
11233*7c568831SAndroid Build Coastguard Worker 	    (comp->steps[f].op == XPATH_OP_FUNCTION) &&
11234*7c568831SAndroid Build Coastguard Worker 	    (comp->steps[f].value5 == NULL) &&
11235*7c568831SAndroid Build Coastguard Worker 	    (comp->steps[f].value == 0) &&
11236*7c568831SAndroid Build Coastguard Worker 	    (comp->steps[f].value4 != NULL) &&
11237*7c568831SAndroid Build Coastguard Worker 	    (xmlStrEqual
11238*7c568831SAndroid Build Coastguard Worker 	    (comp->steps[f].value4, BAD_CAST "last"))) {
11239*7c568831SAndroid Build Coastguard Worker 	    xmlNodePtr last = NULL;
11240*7c568831SAndroid Build Coastguard Worker 
11241*7c568831SAndroid Build Coastguard Worker 	    total +=
11242*7c568831SAndroid Build Coastguard Worker 		xmlXPathCompOpEvalLast(ctxt,
11243*7c568831SAndroid Build Coastguard Worker 		    &comp->steps[op->ch1],
11244*7c568831SAndroid Build Coastguard Worker 		    &last);
11245*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11246*7c568831SAndroid Build Coastguard Worker 	    /*
11247*7c568831SAndroid Build Coastguard Worker 	    * The nodeset should be in document order,
11248*7c568831SAndroid Build Coastguard Worker 	    * Keep only the last value
11249*7c568831SAndroid Build Coastguard Worker 	    */
11250*7c568831SAndroid Build Coastguard Worker 	    if ((ctxt->value != NULL) &&
11251*7c568831SAndroid Build Coastguard Worker 		(ctxt->value->type == XPATH_NODESET) &&
11252*7c568831SAndroid Build Coastguard Worker 		(ctxt->value->nodesetval != NULL) &&
11253*7c568831SAndroid Build Coastguard Worker 		(ctxt->value->nodesetval->nodeTab != NULL) &&
11254*7c568831SAndroid Build Coastguard Worker 		(ctxt->value->nodesetval->nodeNr > 1)) {
11255*7c568831SAndroid Build Coastguard Worker                 xmlXPathNodeSetKeepLast(ctxt->value->nodesetval);
11256*7c568831SAndroid Build Coastguard Worker 		*first = *(ctxt->value->nodesetval->nodeTab);
11257*7c568831SAndroid Build Coastguard Worker 	    }
11258*7c568831SAndroid Build Coastguard Worker 	    return (total);
11259*7c568831SAndroid Build Coastguard Worker 	}
11260*7c568831SAndroid Build Coastguard Worker     }
11261*7c568831SAndroid Build Coastguard Worker 
11262*7c568831SAndroid Build Coastguard Worker     if (op->ch1 != -1)
11263*7c568831SAndroid Build Coastguard Worker 	total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11264*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR0;
11265*7c568831SAndroid Build Coastguard Worker     if (op->ch2 == -1)
11266*7c568831SAndroid Build Coastguard Worker 	return (total);
11267*7c568831SAndroid Build Coastguard Worker     if (ctxt->value == NULL)
11268*7c568831SAndroid Build Coastguard Worker 	return (total);
11269*7c568831SAndroid Build Coastguard Worker 
11270*7c568831SAndroid Build Coastguard Worker     /*
11271*7c568831SAndroid Build Coastguard Worker      * In case of errors, xmlXPathNodeSetFilter can pop additional nodes from
11272*7c568831SAndroid Build Coastguard Worker      * the stack. We have to temporarily remove the nodeset object from the
11273*7c568831SAndroid Build Coastguard Worker      * stack to avoid freeing it prematurely.
11274*7c568831SAndroid Build Coastguard Worker      */
11275*7c568831SAndroid Build Coastguard Worker     CHECK_TYPE0(XPATH_NODESET);
11276*7c568831SAndroid Build Coastguard Worker     obj = valuePop(ctxt);
11277*7c568831SAndroid Build Coastguard Worker     set = obj->nodesetval;
11278*7c568831SAndroid Build Coastguard Worker     if (set != NULL) {
11279*7c568831SAndroid Build Coastguard Worker         xmlXPathNodeSetFilter(ctxt, set, op->ch2, 1, 1, 1);
11280*7c568831SAndroid Build Coastguard Worker         if (set->nodeNr > 0)
11281*7c568831SAndroid Build Coastguard Worker             *first = set->nodeTab[0];
11282*7c568831SAndroid Build Coastguard Worker     }
11283*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, obj);
11284*7c568831SAndroid Build Coastguard Worker 
11285*7c568831SAndroid Build Coastguard Worker     return (total);
11286*7c568831SAndroid Build Coastguard Worker }
11287*7c568831SAndroid Build Coastguard Worker #endif /* XP_OPTIMIZED_FILTER_FIRST */
11288*7c568831SAndroid Build Coastguard Worker 
11289*7c568831SAndroid Build Coastguard Worker /**
11290*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompOpEval:
11291*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath parser context with the compiled expression
11292*7c568831SAndroid Build Coastguard Worker  * @op:  an XPath compiled operation
11293*7c568831SAndroid Build Coastguard Worker  *
11294*7c568831SAndroid Build Coastguard Worker  * Evaluate the Precompiled XPath operation
11295*7c568831SAndroid Build Coastguard Worker  * Returns the number of nodes traversed
11296*7c568831SAndroid Build Coastguard Worker  */
11297*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op)11298*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
11299*7c568831SAndroid Build Coastguard Worker {
11300*7c568831SAndroid Build Coastguard Worker     int total = 0;
11301*7c568831SAndroid Build Coastguard Worker     int equal, ret;
11302*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp;
11303*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr arg1, arg2;
11304*7c568831SAndroid Build Coastguard Worker 
11305*7c568831SAndroid Build Coastguard Worker     CHECK_ERROR0;
11306*7c568831SAndroid Build Coastguard Worker     if (OP_LIMIT_EXCEEDED(ctxt, 1))
11307*7c568831SAndroid Build Coastguard Worker         return(0);
11308*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
11309*7c568831SAndroid Build Coastguard Worker         XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
11310*7c568831SAndroid Build Coastguard Worker     ctxt->context->depth += 1;
11311*7c568831SAndroid Build Coastguard Worker     comp = ctxt->comp;
11312*7c568831SAndroid Build Coastguard Worker     switch (op->op) {
11313*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_END:
11314*7c568831SAndroid Build Coastguard Worker             break;
11315*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_AND:
11316*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11317*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11318*7c568831SAndroid Build Coastguard Worker             xmlXPathBooleanFunction(ctxt, 1);
11319*7c568831SAndroid Build Coastguard Worker             if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
11320*7c568831SAndroid Build Coastguard Worker                 break;
11321*7c568831SAndroid Build Coastguard Worker             arg2 = valuePop(ctxt);
11322*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11323*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->error) {
11324*7c568831SAndroid Build Coastguard Worker 		xmlXPathFreeObject(arg2);
11325*7c568831SAndroid Build Coastguard Worker 		break;
11326*7c568831SAndroid Build Coastguard Worker 	    }
11327*7c568831SAndroid Build Coastguard Worker             xmlXPathBooleanFunction(ctxt, 1);
11328*7c568831SAndroid Build Coastguard Worker             if (ctxt->value != NULL)
11329*7c568831SAndroid Build Coastguard Worker                 ctxt->value->boolval &= arg2->boolval;
11330*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg2);
11331*7c568831SAndroid Build Coastguard Worker             break;
11332*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_OR:
11333*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11334*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11335*7c568831SAndroid Build Coastguard Worker             xmlXPathBooleanFunction(ctxt, 1);
11336*7c568831SAndroid Build Coastguard Worker             if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
11337*7c568831SAndroid Build Coastguard Worker                 break;
11338*7c568831SAndroid Build Coastguard Worker             arg2 = valuePop(ctxt);
11339*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11340*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->error) {
11341*7c568831SAndroid Build Coastguard Worker 		xmlXPathFreeObject(arg2);
11342*7c568831SAndroid Build Coastguard Worker 		break;
11343*7c568831SAndroid Build Coastguard Worker 	    }
11344*7c568831SAndroid Build Coastguard Worker             xmlXPathBooleanFunction(ctxt, 1);
11345*7c568831SAndroid Build Coastguard Worker             if (ctxt->value != NULL)
11346*7c568831SAndroid Build Coastguard Worker                 ctxt->value->boolval |= arg2->boolval;
11347*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg2);
11348*7c568831SAndroid Build Coastguard Worker             break;
11349*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_EQUAL:
11350*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11351*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11352*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11353*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11354*7c568831SAndroid Build Coastguard Worker 	    if (op->value)
11355*7c568831SAndroid Build Coastguard Worker 		equal = xmlXPathEqualValues(ctxt);
11356*7c568831SAndroid Build Coastguard Worker 	    else
11357*7c568831SAndroid Build Coastguard Worker 		equal = xmlXPathNotEqualValues(ctxt);
11358*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, equal));
11359*7c568831SAndroid Build Coastguard Worker             break;
11360*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_CMP:
11361*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11362*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11363*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11364*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11365*7c568831SAndroid Build Coastguard Worker             ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
11366*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret));
11367*7c568831SAndroid Build Coastguard Worker             break;
11368*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_PLUS:
11369*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11370*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11371*7c568831SAndroid Build Coastguard Worker             if (op->ch2 != -1) {
11372*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11373*7c568831SAndroid Build Coastguard Worker 	    }
11374*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11375*7c568831SAndroid Build Coastguard Worker             if (op->value == 0)
11376*7c568831SAndroid Build Coastguard Worker                 xmlXPathSubValues(ctxt);
11377*7c568831SAndroid Build Coastguard Worker             else if (op->value == 1)
11378*7c568831SAndroid Build Coastguard Worker                 xmlXPathAddValues(ctxt);
11379*7c568831SAndroid Build Coastguard Worker             else if (op->value == 2)
11380*7c568831SAndroid Build Coastguard Worker                 xmlXPathValueFlipSign(ctxt);
11381*7c568831SAndroid Build Coastguard Worker             else if (op->value == 3) {
11382*7c568831SAndroid Build Coastguard Worker                 CAST_TO_NUMBER;
11383*7c568831SAndroid Build Coastguard Worker                 CHECK_TYPE0(XPATH_NUMBER);
11384*7c568831SAndroid Build Coastguard Worker             }
11385*7c568831SAndroid Build Coastguard Worker             break;
11386*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_MULT:
11387*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11388*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11389*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11390*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11391*7c568831SAndroid Build Coastguard Worker             if (op->value == 0)
11392*7c568831SAndroid Build Coastguard Worker                 xmlXPathMultValues(ctxt);
11393*7c568831SAndroid Build Coastguard Worker             else if (op->value == 1)
11394*7c568831SAndroid Build Coastguard Worker                 xmlXPathDivValues(ctxt);
11395*7c568831SAndroid Build Coastguard Worker             else if (op->value == 2)
11396*7c568831SAndroid Build Coastguard Worker                 xmlXPathModValues(ctxt);
11397*7c568831SAndroid Build Coastguard Worker             break;
11398*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_UNION:
11399*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11400*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11401*7c568831SAndroid Build Coastguard Worker             total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11402*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11403*7c568831SAndroid Build Coastguard Worker 
11404*7c568831SAndroid Build Coastguard Worker             arg2 = valuePop(ctxt);
11405*7c568831SAndroid Build Coastguard Worker             arg1 = valuePop(ctxt);
11406*7c568831SAndroid Build Coastguard Worker             if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
11407*7c568831SAndroid Build Coastguard Worker                 (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
11408*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg1);
11409*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg2);
11410*7c568831SAndroid Build Coastguard Worker                 XP_ERROR0(XPATH_INVALID_TYPE);
11411*7c568831SAndroid Build Coastguard Worker             }
11412*7c568831SAndroid Build Coastguard Worker             if ((ctxt->context->opLimit != 0) &&
11413*7c568831SAndroid Build Coastguard Worker                 (((arg1->nodesetval != NULL) &&
11414*7c568831SAndroid Build Coastguard Worker                   (xmlXPathCheckOpLimit(ctxt,
11415*7c568831SAndroid Build Coastguard Worker                                         arg1->nodesetval->nodeNr) < 0)) ||
11416*7c568831SAndroid Build Coastguard Worker                  ((arg2->nodesetval != NULL) &&
11417*7c568831SAndroid Build Coastguard Worker                   (xmlXPathCheckOpLimit(ctxt,
11418*7c568831SAndroid Build Coastguard Worker                                         arg2->nodesetval->nodeNr) < 0)))) {
11419*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg1);
11420*7c568831SAndroid Build Coastguard Worker 	        xmlXPathReleaseObject(ctxt->context, arg2);
11421*7c568831SAndroid Build Coastguard Worker                 break;
11422*7c568831SAndroid Build Coastguard Worker             }
11423*7c568831SAndroid Build Coastguard Worker 
11424*7c568831SAndroid Build Coastguard Worker 	    if (((arg2->nodesetval != NULL) &&
11425*7c568831SAndroid Build Coastguard Worker 		 (arg2->nodesetval->nodeNr != 0)))
11426*7c568831SAndroid Build Coastguard Worker 	    {
11427*7c568831SAndroid Build Coastguard Worker 		arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11428*7c568831SAndroid Build Coastguard Worker 							arg2->nodesetval);
11429*7c568831SAndroid Build Coastguard Worker                 if (arg1->nodesetval == NULL)
11430*7c568831SAndroid Build Coastguard Worker                     xmlXPathPErrMemory(ctxt);
11431*7c568831SAndroid Build Coastguard Worker 	    }
11432*7c568831SAndroid Build Coastguard Worker 
11433*7c568831SAndroid Build Coastguard Worker             valuePush(ctxt, arg1);
11434*7c568831SAndroid Build Coastguard Worker 	    xmlXPathReleaseObject(ctxt->context, arg2);
11435*7c568831SAndroid Build Coastguard Worker             break;
11436*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_ROOT:
11437*7c568831SAndroid Build Coastguard Worker             xmlXPathRoot(ctxt);
11438*7c568831SAndroid Build Coastguard Worker             break;
11439*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_NODE:
11440*7c568831SAndroid Build Coastguard Worker             if (op->ch1 != -1)
11441*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11442*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11443*7c568831SAndroid Build Coastguard Worker             if (op->ch2 != -1)
11444*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11445*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11446*7c568831SAndroid Build Coastguard Worker 	    valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11447*7c568831SAndroid Build Coastguard Worker                                                     ctxt->context->node));
11448*7c568831SAndroid Build Coastguard Worker             break;
11449*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_COLLECT:{
11450*7c568831SAndroid Build Coastguard Worker                 if (op->ch1 == -1)
11451*7c568831SAndroid Build Coastguard Worker                     break;
11452*7c568831SAndroid Build Coastguard Worker 
11453*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11454*7c568831SAndroid Build Coastguard Worker 		CHECK_ERROR0;
11455*7c568831SAndroid Build Coastguard Worker 
11456*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 0);
11457*7c568831SAndroid Build Coastguard Worker                 break;
11458*7c568831SAndroid Build Coastguard Worker             }
11459*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_VALUE:
11460*7c568831SAndroid Build Coastguard Worker             valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11461*7c568831SAndroid Build Coastguard Worker             break;
11462*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_VARIABLE:{
11463*7c568831SAndroid Build Coastguard Worker 		xmlXPathObjectPtr val;
11464*7c568831SAndroid Build Coastguard Worker 
11465*7c568831SAndroid Build Coastguard Worker                 if (op->ch1 != -1)
11466*7c568831SAndroid Build Coastguard Worker                     total +=
11467*7c568831SAndroid Build Coastguard Worker                         xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11468*7c568831SAndroid Build Coastguard Worker                 if (op->value5 == NULL) {
11469*7c568831SAndroid Build Coastguard Worker 		    val = xmlXPathVariableLookup(ctxt->context, op->value4);
11470*7c568831SAndroid Build Coastguard Worker 		    if (val == NULL)
11471*7c568831SAndroid Build Coastguard Worker 			XP_ERROR0(XPATH_UNDEF_VARIABLE_ERROR);
11472*7c568831SAndroid Build Coastguard Worker                     valuePush(ctxt, val);
11473*7c568831SAndroid Build Coastguard Worker 		} else {
11474*7c568831SAndroid Build Coastguard Worker                     const xmlChar *URI;
11475*7c568831SAndroid Build Coastguard Worker 
11476*7c568831SAndroid Build Coastguard Worker                     URI = xmlXPathNsLookup(ctxt->context, op->value5);
11477*7c568831SAndroid Build Coastguard Worker                     if (URI == NULL) {
11478*7c568831SAndroid Build Coastguard Worker                         XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
11479*7c568831SAndroid Build Coastguard Worker                         break;
11480*7c568831SAndroid Build Coastguard Worker                     }
11481*7c568831SAndroid Build Coastguard Worker 		    val = xmlXPathVariableLookupNS(ctxt->context,
11482*7c568831SAndroid Build Coastguard Worker                                                        op->value4, URI);
11483*7c568831SAndroid Build Coastguard Worker 		    if (val == NULL)
11484*7c568831SAndroid Build Coastguard Worker 			XP_ERROR0(XPATH_UNDEF_VARIABLE_ERROR);
11485*7c568831SAndroid Build Coastguard Worker                     valuePush(ctxt, val);
11486*7c568831SAndroid Build Coastguard Worker                 }
11487*7c568831SAndroid Build Coastguard Worker                 break;
11488*7c568831SAndroid Build Coastguard Worker             }
11489*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_FUNCTION:{
11490*7c568831SAndroid Build Coastguard Worker                 xmlXPathFunction func;
11491*7c568831SAndroid Build Coastguard Worker                 const xmlChar *oldFunc, *oldFuncURI;
11492*7c568831SAndroid Build Coastguard Worker 		int i;
11493*7c568831SAndroid Build Coastguard Worker                 int frame;
11494*7c568831SAndroid Build Coastguard Worker 
11495*7c568831SAndroid Build Coastguard Worker                 frame = ctxt->valueNr;
11496*7c568831SAndroid Build Coastguard Worker                 if (op->ch1 != -1) {
11497*7c568831SAndroid Build Coastguard Worker                     total +=
11498*7c568831SAndroid Build Coastguard Worker                         xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11499*7c568831SAndroid Build Coastguard Worker                     if (ctxt->error != XPATH_EXPRESSION_OK)
11500*7c568831SAndroid Build Coastguard Worker                         break;
11501*7c568831SAndroid Build Coastguard Worker                 }
11502*7c568831SAndroid Build Coastguard Worker 		if (ctxt->valueNr < frame + op->value)
11503*7c568831SAndroid Build Coastguard Worker 		    XP_ERROR0(XPATH_INVALID_OPERAND);
11504*7c568831SAndroid Build Coastguard Worker 		for (i = 0; i < op->value; i++) {
11505*7c568831SAndroid Build Coastguard Worker 		    if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL)
11506*7c568831SAndroid Build Coastguard Worker 			XP_ERROR0(XPATH_INVALID_OPERAND);
11507*7c568831SAndroid Build Coastguard Worker                 }
11508*7c568831SAndroid Build Coastguard Worker                 if (op->cache != NULL)
11509*7c568831SAndroid Build Coastguard Worker                     func = op->cache;
11510*7c568831SAndroid Build Coastguard Worker                 else {
11511*7c568831SAndroid Build Coastguard Worker                     const xmlChar *URI = NULL;
11512*7c568831SAndroid Build Coastguard Worker 
11513*7c568831SAndroid Build Coastguard Worker                     if (op->value5 == NULL)
11514*7c568831SAndroid Build Coastguard Worker                         func =
11515*7c568831SAndroid Build Coastguard Worker                             xmlXPathFunctionLookup(ctxt->context,
11516*7c568831SAndroid Build Coastguard Worker                                                    op->value4);
11517*7c568831SAndroid Build Coastguard Worker                     else {
11518*7c568831SAndroid Build Coastguard Worker                         URI = xmlXPathNsLookup(ctxt->context, op->value5);
11519*7c568831SAndroid Build Coastguard Worker                         if (URI == NULL)
11520*7c568831SAndroid Build Coastguard Worker                             XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
11521*7c568831SAndroid Build Coastguard Worker                         func = xmlXPathFunctionLookupNS(ctxt->context,
11522*7c568831SAndroid Build Coastguard Worker                                                         op->value4, URI);
11523*7c568831SAndroid Build Coastguard Worker                     }
11524*7c568831SAndroid Build Coastguard Worker                     if (func == NULL)
11525*7c568831SAndroid Build Coastguard Worker                         XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
11526*7c568831SAndroid Build Coastguard Worker                     op->cache = func;
11527*7c568831SAndroid Build Coastguard Worker                     op->cacheURI = (void *) URI;
11528*7c568831SAndroid Build Coastguard Worker                 }
11529*7c568831SAndroid Build Coastguard Worker                 oldFunc = ctxt->context->function;
11530*7c568831SAndroid Build Coastguard Worker                 oldFuncURI = ctxt->context->functionURI;
11531*7c568831SAndroid Build Coastguard Worker                 ctxt->context->function = op->value4;
11532*7c568831SAndroid Build Coastguard Worker                 ctxt->context->functionURI = op->cacheURI;
11533*7c568831SAndroid Build Coastguard Worker                 func(ctxt, op->value);
11534*7c568831SAndroid Build Coastguard Worker                 ctxt->context->function = oldFunc;
11535*7c568831SAndroid Build Coastguard Worker                 ctxt->context->functionURI = oldFuncURI;
11536*7c568831SAndroid Build Coastguard Worker                 if ((ctxt->error == XPATH_EXPRESSION_OK) &&
11537*7c568831SAndroid Build Coastguard Worker                     (ctxt->valueNr != frame + 1))
11538*7c568831SAndroid Build Coastguard Worker                     XP_ERROR0(XPATH_STACK_ERROR);
11539*7c568831SAndroid Build Coastguard Worker                 break;
11540*7c568831SAndroid Build Coastguard Worker             }
11541*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_ARG:
11542*7c568831SAndroid Build Coastguard Worker             if (op->ch1 != -1) {
11543*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11544*7c568831SAndroid Build Coastguard Worker 	        CHECK_ERROR0;
11545*7c568831SAndroid Build Coastguard Worker             }
11546*7c568831SAndroid Build Coastguard Worker             if (op->ch2 != -1) {
11547*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11548*7c568831SAndroid Build Coastguard Worker 	        CHECK_ERROR0;
11549*7c568831SAndroid Build Coastguard Worker 	    }
11550*7c568831SAndroid Build Coastguard Worker             break;
11551*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_PREDICATE:
11552*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_FILTER:{
11553*7c568831SAndroid Build Coastguard Worker                 xmlXPathObjectPtr obj;
11554*7c568831SAndroid Build Coastguard Worker                 xmlNodeSetPtr set;
11555*7c568831SAndroid Build Coastguard Worker 
11556*7c568831SAndroid Build Coastguard Worker                 /*
11557*7c568831SAndroid Build Coastguard Worker                  * Optimization for ()[1] selection i.e. the first elem
11558*7c568831SAndroid Build Coastguard Worker                  */
11559*7c568831SAndroid Build Coastguard Worker                 if ((op->ch1 != -1) && (op->ch2 != -1) &&
11560*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
11561*7c568831SAndroid Build Coastguard Worker 		    /*
11562*7c568831SAndroid Build Coastguard Worker 		    * FILTER TODO: Can we assume that the inner processing
11563*7c568831SAndroid Build Coastguard Worker 		    *  will result in an ordered list if we have an
11564*7c568831SAndroid Build Coastguard Worker 		    *  XPATH_OP_FILTER?
11565*7c568831SAndroid Build Coastguard Worker 		    *  What about an additional field or flag on
11566*7c568831SAndroid Build Coastguard Worker 		    *  xmlXPathObject like @sorted ? This way we wouldn't need
11567*7c568831SAndroid Build Coastguard Worker 		    *  to assume anything, so it would be more robust and
11568*7c568831SAndroid Build Coastguard Worker 		    *  easier to optimize.
11569*7c568831SAndroid Build Coastguard Worker 		    */
11570*7c568831SAndroid Build Coastguard Worker                     ((comp->steps[op->ch1].op == XPATH_OP_SORT) || /* 18 */
11571*7c568831SAndroid Build Coastguard Worker 		     (comp->steps[op->ch1].op == XPATH_OP_FILTER)) && /* 17 */
11572*7c568831SAndroid Build Coastguard Worker #else
11573*7c568831SAndroid Build Coastguard Worker 		    (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
11574*7c568831SAndroid Build Coastguard Worker #endif
11575*7c568831SAndroid Build Coastguard Worker                     (comp->steps[op->ch2].op == XPATH_OP_VALUE)) { /* 12 */
11576*7c568831SAndroid Build Coastguard Worker                     xmlXPathObjectPtr val;
11577*7c568831SAndroid Build Coastguard Worker 
11578*7c568831SAndroid Build Coastguard Worker                     val = comp->steps[op->ch2].value4;
11579*7c568831SAndroid Build Coastguard Worker                     if ((val != NULL) && (val->type == XPATH_NUMBER) &&
11580*7c568831SAndroid Build Coastguard Worker                         (val->floatval == 1.0)) {
11581*7c568831SAndroid Build Coastguard Worker                         xmlNodePtr first = NULL;
11582*7c568831SAndroid Build Coastguard Worker 
11583*7c568831SAndroid Build Coastguard Worker                         total +=
11584*7c568831SAndroid Build Coastguard Worker                             xmlXPathCompOpEvalFirst(ctxt,
11585*7c568831SAndroid Build Coastguard Worker                                                     &comp->steps[op->ch1],
11586*7c568831SAndroid Build Coastguard Worker                                                     &first);
11587*7c568831SAndroid Build Coastguard Worker 			CHECK_ERROR0;
11588*7c568831SAndroid Build Coastguard Worker                         /*
11589*7c568831SAndroid Build Coastguard Worker                          * The nodeset should be in document order,
11590*7c568831SAndroid Build Coastguard Worker                          * Keep only the first value
11591*7c568831SAndroid Build Coastguard Worker                          */
11592*7c568831SAndroid Build Coastguard Worker                         if ((ctxt->value != NULL) &&
11593*7c568831SAndroid Build Coastguard Worker                             (ctxt->value->type == XPATH_NODESET) &&
11594*7c568831SAndroid Build Coastguard Worker                             (ctxt->value->nodesetval != NULL) &&
11595*7c568831SAndroid Build Coastguard Worker                             (ctxt->value->nodesetval->nodeNr > 1))
11596*7c568831SAndroid Build Coastguard Worker                             xmlXPathNodeSetClearFromPos(ctxt->value->nodesetval,
11597*7c568831SAndroid Build Coastguard Worker                                                         1, 1);
11598*7c568831SAndroid Build Coastguard Worker                         break;
11599*7c568831SAndroid Build Coastguard Worker                     }
11600*7c568831SAndroid Build Coastguard Worker                 }
11601*7c568831SAndroid Build Coastguard Worker                 /*
11602*7c568831SAndroid Build Coastguard Worker                  * Optimization for ()[last()] selection i.e. the last elem
11603*7c568831SAndroid Build Coastguard Worker                  */
11604*7c568831SAndroid Build Coastguard Worker                 if ((op->ch1 != -1) && (op->ch2 != -1) &&
11605*7c568831SAndroid Build Coastguard Worker                     (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
11606*7c568831SAndroid Build Coastguard Worker                     (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
11607*7c568831SAndroid Build Coastguard Worker                     int f = comp->steps[op->ch2].ch1;
11608*7c568831SAndroid Build Coastguard Worker 
11609*7c568831SAndroid Build Coastguard Worker                     if ((f != -1) &&
11610*7c568831SAndroid Build Coastguard Worker                         (comp->steps[f].op == XPATH_OP_FUNCTION) &&
11611*7c568831SAndroid Build Coastguard Worker                         (comp->steps[f].value5 == NULL) &&
11612*7c568831SAndroid Build Coastguard Worker                         (comp->steps[f].value == 0) &&
11613*7c568831SAndroid Build Coastguard Worker                         (comp->steps[f].value4 != NULL) &&
11614*7c568831SAndroid Build Coastguard Worker                         (xmlStrEqual
11615*7c568831SAndroid Build Coastguard Worker                          (comp->steps[f].value4, BAD_CAST "last"))) {
11616*7c568831SAndroid Build Coastguard Worker                         xmlNodePtr last = NULL;
11617*7c568831SAndroid Build Coastguard Worker 
11618*7c568831SAndroid Build Coastguard Worker                         total +=
11619*7c568831SAndroid Build Coastguard Worker                             xmlXPathCompOpEvalLast(ctxt,
11620*7c568831SAndroid Build Coastguard Worker                                                    &comp->steps[op->ch1],
11621*7c568831SAndroid Build Coastguard Worker                                                    &last);
11622*7c568831SAndroid Build Coastguard Worker 			CHECK_ERROR0;
11623*7c568831SAndroid Build Coastguard Worker                         /*
11624*7c568831SAndroid Build Coastguard Worker                          * The nodeset should be in document order,
11625*7c568831SAndroid Build Coastguard Worker                          * Keep only the last value
11626*7c568831SAndroid Build Coastguard Worker                          */
11627*7c568831SAndroid Build Coastguard Worker                         if ((ctxt->value != NULL) &&
11628*7c568831SAndroid Build Coastguard Worker                             (ctxt->value->type == XPATH_NODESET) &&
11629*7c568831SAndroid Build Coastguard Worker                             (ctxt->value->nodesetval != NULL) &&
11630*7c568831SAndroid Build Coastguard Worker                             (ctxt->value->nodesetval->nodeTab != NULL) &&
11631*7c568831SAndroid Build Coastguard Worker                             (ctxt->value->nodesetval->nodeNr > 1))
11632*7c568831SAndroid Build Coastguard Worker                             xmlXPathNodeSetKeepLast(ctxt->value->nodesetval);
11633*7c568831SAndroid Build Coastguard Worker                         break;
11634*7c568831SAndroid Build Coastguard Worker                     }
11635*7c568831SAndroid Build Coastguard Worker                 }
11636*7c568831SAndroid Build Coastguard Worker 		/*
11637*7c568831SAndroid Build Coastguard Worker 		* Process inner predicates first.
11638*7c568831SAndroid Build Coastguard Worker 		* Example "index[parent::book][1]":
11639*7c568831SAndroid Build Coastguard Worker 		* ...
11640*7c568831SAndroid Build Coastguard Worker 		*   PREDICATE   <-- we are here "[1]"
11641*7c568831SAndroid Build Coastguard Worker 		*     PREDICATE <-- process "[parent::book]" first
11642*7c568831SAndroid Build Coastguard Worker 		*       SORT
11643*7c568831SAndroid Build Coastguard Worker 		*         COLLECT  'parent' 'name' 'node' book
11644*7c568831SAndroid Build Coastguard Worker 		*           NODE
11645*7c568831SAndroid Build Coastguard Worker 		*     ELEM Object is a number : 1
11646*7c568831SAndroid Build Coastguard Worker 		*/
11647*7c568831SAndroid Build Coastguard Worker                 if (op->ch1 != -1)
11648*7c568831SAndroid Build Coastguard Worker                     total +=
11649*7c568831SAndroid Build Coastguard Worker                         xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11650*7c568831SAndroid Build Coastguard Worker 		CHECK_ERROR0;
11651*7c568831SAndroid Build Coastguard Worker                 if (op->ch2 == -1)
11652*7c568831SAndroid Build Coastguard Worker                     break;
11653*7c568831SAndroid Build Coastguard Worker                 if (ctxt->value == NULL)
11654*7c568831SAndroid Build Coastguard Worker                     break;
11655*7c568831SAndroid Build Coastguard Worker 
11656*7c568831SAndroid Build Coastguard Worker                 /*
11657*7c568831SAndroid Build Coastguard Worker                  * In case of errors, xmlXPathNodeSetFilter can pop additional
11658*7c568831SAndroid Build Coastguard Worker                  * nodes from the stack. We have to temporarily remove the
11659*7c568831SAndroid Build Coastguard Worker                  * nodeset object from the stack to avoid freeing it
11660*7c568831SAndroid Build Coastguard Worker                  * prematurely.
11661*7c568831SAndroid Build Coastguard Worker                  */
11662*7c568831SAndroid Build Coastguard Worker                 CHECK_TYPE0(XPATH_NODESET);
11663*7c568831SAndroid Build Coastguard Worker                 obj = valuePop(ctxt);
11664*7c568831SAndroid Build Coastguard Worker                 set = obj->nodesetval;
11665*7c568831SAndroid Build Coastguard Worker                 if (set != NULL)
11666*7c568831SAndroid Build Coastguard Worker                     xmlXPathNodeSetFilter(ctxt, set, op->ch2,
11667*7c568831SAndroid Build Coastguard Worker                                           1, set->nodeNr, 1);
11668*7c568831SAndroid Build Coastguard Worker                 valuePush(ctxt, obj);
11669*7c568831SAndroid Build Coastguard Worker                 break;
11670*7c568831SAndroid Build Coastguard Worker             }
11671*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_SORT:
11672*7c568831SAndroid Build Coastguard Worker             if (op->ch1 != -1)
11673*7c568831SAndroid Build Coastguard Worker                 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11674*7c568831SAndroid Build Coastguard Worker 	    CHECK_ERROR0;
11675*7c568831SAndroid Build Coastguard Worker             if ((ctxt->value != NULL) &&
11676*7c568831SAndroid Build Coastguard Worker                 (ctxt->value->type == XPATH_NODESET) &&
11677*7c568831SAndroid Build Coastguard Worker                 (ctxt->value->nodesetval != NULL) &&
11678*7c568831SAndroid Build Coastguard Worker 		(ctxt->value->nodesetval->nodeNr > 1))
11679*7c568831SAndroid Build Coastguard Worker 	    {
11680*7c568831SAndroid Build Coastguard Worker                 xmlXPathNodeSetSort(ctxt->value->nodesetval);
11681*7c568831SAndroid Build Coastguard Worker 	    }
11682*7c568831SAndroid Build Coastguard Worker             break;
11683*7c568831SAndroid Build Coastguard Worker         default:
11684*7c568831SAndroid Build Coastguard Worker             XP_ERROR0(XPATH_INVALID_OPERAND);
11685*7c568831SAndroid Build Coastguard Worker             break;
11686*7c568831SAndroid Build Coastguard Worker     }
11687*7c568831SAndroid Build Coastguard Worker 
11688*7c568831SAndroid Build Coastguard Worker     ctxt->context->depth -= 1;
11689*7c568831SAndroid Build Coastguard Worker     return (total);
11690*7c568831SAndroid Build Coastguard Worker }
11691*7c568831SAndroid Build Coastguard Worker 
11692*7c568831SAndroid Build Coastguard Worker /**
11693*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompOpEvalToBoolean:
11694*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath parser context
11695*7c568831SAndroid Build Coastguard Worker  *
11696*7c568831SAndroid Build Coastguard Worker  * Evaluates if the expression evaluates to true.
11697*7c568831SAndroid Build Coastguard Worker  *
11698*7c568831SAndroid Build Coastguard Worker  * Returns 1 if true, 0 if false and -1 on API or internal errors.
11699*7c568831SAndroid Build Coastguard Worker  */
11700*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,int isPredicate)11701*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
11702*7c568831SAndroid Build Coastguard Worker 			    xmlXPathStepOpPtr op,
11703*7c568831SAndroid Build Coastguard Worker 			    int isPredicate)
11704*7c568831SAndroid Build Coastguard Worker {
11705*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr resObj = NULL;
11706*7c568831SAndroid Build Coastguard Worker 
11707*7c568831SAndroid Build Coastguard Worker start:
11708*7c568831SAndroid Build Coastguard Worker     if (OP_LIMIT_EXCEEDED(ctxt, 1))
11709*7c568831SAndroid Build Coastguard Worker         return(0);
11710*7c568831SAndroid Build Coastguard Worker     /* comp = ctxt->comp; */
11711*7c568831SAndroid Build Coastguard Worker     switch (op->op) {
11712*7c568831SAndroid Build Coastguard Worker         case XPATH_OP_END:
11713*7c568831SAndroid Build Coastguard Worker             return (0);
11714*7c568831SAndroid Build Coastguard Worker 	case XPATH_OP_VALUE:
11715*7c568831SAndroid Build Coastguard Worker 	    resObj = (xmlXPathObjectPtr) op->value4;
11716*7c568831SAndroid Build Coastguard Worker 	    if (isPredicate)
11717*7c568831SAndroid Build Coastguard Worker 		return(xmlXPathEvaluatePredicateResult(ctxt, resObj));
11718*7c568831SAndroid Build Coastguard Worker 	    return(xmlXPathCastToBoolean(resObj));
11719*7c568831SAndroid Build Coastguard Worker 	case XPATH_OP_SORT:
11720*7c568831SAndroid Build Coastguard Worker 	    /*
11721*7c568831SAndroid Build Coastguard Worker 	    * We don't need sorting for boolean results. Skip this one.
11722*7c568831SAndroid Build Coastguard Worker 	    */
11723*7c568831SAndroid Build Coastguard Worker             if (op->ch1 != -1) {
11724*7c568831SAndroid Build Coastguard Worker 		op = &ctxt->comp->steps[op->ch1];
11725*7c568831SAndroid Build Coastguard Worker 		goto start;
11726*7c568831SAndroid Build Coastguard Worker 	    }
11727*7c568831SAndroid Build Coastguard Worker 	    return(0);
11728*7c568831SAndroid Build Coastguard Worker 	case XPATH_OP_COLLECT:
11729*7c568831SAndroid Build Coastguard Worker 	    if (op->ch1 == -1)
11730*7c568831SAndroid Build Coastguard Worker 		return(0);
11731*7c568831SAndroid Build Coastguard Worker 
11732*7c568831SAndroid Build Coastguard Worker             xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch1]);
11733*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->error != XPATH_EXPRESSION_OK)
11734*7c568831SAndroid Build Coastguard Worker 		return(-1);
11735*7c568831SAndroid Build Coastguard Worker 
11736*7c568831SAndroid Build Coastguard Worker             xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 1);
11737*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->error != XPATH_EXPRESSION_OK)
11738*7c568831SAndroid Build Coastguard Worker 		return(-1);
11739*7c568831SAndroid Build Coastguard Worker 
11740*7c568831SAndroid Build Coastguard Worker 	    resObj = valuePop(ctxt);
11741*7c568831SAndroid Build Coastguard Worker 	    if (resObj == NULL)
11742*7c568831SAndroid Build Coastguard Worker 		return(-1);
11743*7c568831SAndroid Build Coastguard Worker 	    break;
11744*7c568831SAndroid Build Coastguard Worker 	default:
11745*7c568831SAndroid Build Coastguard Worker 	    /*
11746*7c568831SAndroid Build Coastguard Worker 	    * Fallback to call xmlXPathCompOpEval().
11747*7c568831SAndroid Build Coastguard Worker 	    */
11748*7c568831SAndroid Build Coastguard Worker 	    xmlXPathCompOpEval(ctxt, op);
11749*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->error != XPATH_EXPRESSION_OK)
11750*7c568831SAndroid Build Coastguard Worker 		return(-1);
11751*7c568831SAndroid Build Coastguard Worker 
11752*7c568831SAndroid Build Coastguard Worker 	    resObj = valuePop(ctxt);
11753*7c568831SAndroid Build Coastguard Worker 	    if (resObj == NULL)
11754*7c568831SAndroid Build Coastguard Worker 		return(-1);
11755*7c568831SAndroid Build Coastguard Worker 	    break;
11756*7c568831SAndroid Build Coastguard Worker     }
11757*7c568831SAndroid Build Coastguard Worker 
11758*7c568831SAndroid Build Coastguard Worker     if (resObj) {
11759*7c568831SAndroid Build Coastguard Worker 	int res;
11760*7c568831SAndroid Build Coastguard Worker 
11761*7c568831SAndroid Build Coastguard Worker 	if (resObj->type == XPATH_BOOLEAN) {
11762*7c568831SAndroid Build Coastguard Worker 	    res = resObj->boolval;
11763*7c568831SAndroid Build Coastguard Worker 	} else if (isPredicate) {
11764*7c568831SAndroid Build Coastguard Worker 	    /*
11765*7c568831SAndroid Build Coastguard Worker 	    * For predicates a result of type "number" is handled
11766*7c568831SAndroid Build Coastguard Worker 	    * differently:
11767*7c568831SAndroid Build Coastguard Worker 	    * SPEC XPath 1.0:
11768*7c568831SAndroid Build Coastguard Worker 	    * "If the result is a number, the result will be converted
11769*7c568831SAndroid Build Coastguard Worker 	    *  to true if the number is equal to the context position
11770*7c568831SAndroid Build Coastguard Worker 	    *  and will be converted to false otherwise;"
11771*7c568831SAndroid Build Coastguard Worker 	    */
11772*7c568831SAndroid Build Coastguard Worker 	    res = xmlXPathEvaluatePredicateResult(ctxt, resObj);
11773*7c568831SAndroid Build Coastguard Worker 	} else {
11774*7c568831SAndroid Build Coastguard Worker 	    res = xmlXPathCastToBoolean(resObj);
11775*7c568831SAndroid Build Coastguard Worker 	}
11776*7c568831SAndroid Build Coastguard Worker 	xmlXPathReleaseObject(ctxt->context, resObj);
11777*7c568831SAndroid Build Coastguard Worker 	return(res);
11778*7c568831SAndroid Build Coastguard Worker     }
11779*7c568831SAndroid Build Coastguard Worker 
11780*7c568831SAndroid Build Coastguard Worker     return(0);
11781*7c568831SAndroid Build Coastguard Worker }
11782*7c568831SAndroid Build Coastguard Worker 
11783*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
11784*7c568831SAndroid Build Coastguard Worker /**
11785*7c568831SAndroid Build Coastguard Worker  * xmlXPathRunStreamEval:
11786*7c568831SAndroid Build Coastguard Worker  * @pctxt:  the XPath parser context with the compiled expression
11787*7c568831SAndroid Build Coastguard Worker  *
11788*7c568831SAndroid Build Coastguard Worker  * Evaluate the Precompiled Streamable XPath expression in the given context.
11789*7c568831SAndroid Build Coastguard Worker  */
11790*7c568831SAndroid Build Coastguard Worker static int
xmlXPathRunStreamEval(xmlXPathParserContextPtr pctxt,xmlPatternPtr comp,xmlXPathObjectPtr * resultSeq,int toBool)11791*7c568831SAndroid Build Coastguard Worker xmlXPathRunStreamEval(xmlXPathParserContextPtr pctxt, xmlPatternPtr comp,
11792*7c568831SAndroid Build Coastguard Worker 		      xmlXPathObjectPtr *resultSeq, int toBool)
11793*7c568831SAndroid Build Coastguard Worker {
11794*7c568831SAndroid Build Coastguard Worker     int max_depth, min_depth;
11795*7c568831SAndroid Build Coastguard Worker     int from_root;
11796*7c568831SAndroid Build Coastguard Worker     int ret, depth;
11797*7c568831SAndroid Build Coastguard Worker     int eval_all_nodes;
11798*7c568831SAndroid Build Coastguard Worker     xmlNodePtr cur = NULL, limit = NULL;
11799*7c568831SAndroid Build Coastguard Worker     xmlStreamCtxtPtr patstream = NULL;
11800*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt = pctxt->context;
11801*7c568831SAndroid Build Coastguard Worker 
11802*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (comp == NULL))
11803*7c568831SAndroid Build Coastguard Worker         return(-1);
11804*7c568831SAndroid Build Coastguard Worker     max_depth = xmlPatternMaxDepth(comp);
11805*7c568831SAndroid Build Coastguard Worker     if (max_depth == -1)
11806*7c568831SAndroid Build Coastguard Worker         return(-1);
11807*7c568831SAndroid Build Coastguard Worker     if (max_depth == -2)
11808*7c568831SAndroid Build Coastguard Worker         max_depth = 10000;
11809*7c568831SAndroid Build Coastguard Worker     min_depth = xmlPatternMinDepth(comp);
11810*7c568831SAndroid Build Coastguard Worker     if (min_depth == -1)
11811*7c568831SAndroid Build Coastguard Worker         return(-1);
11812*7c568831SAndroid Build Coastguard Worker     from_root = xmlPatternFromRoot(comp);
11813*7c568831SAndroid Build Coastguard Worker     if (from_root < 0)
11814*7c568831SAndroid Build Coastguard Worker         return(-1);
11815*7c568831SAndroid Build Coastguard Worker 
11816*7c568831SAndroid Build Coastguard Worker     if (! toBool) {
11817*7c568831SAndroid Build Coastguard Worker 	if (resultSeq == NULL)
11818*7c568831SAndroid Build Coastguard Worker 	    return(-1);
11819*7c568831SAndroid Build Coastguard Worker 	*resultSeq = xmlXPathCacheNewNodeSet(pctxt, NULL);
11820*7c568831SAndroid Build Coastguard Worker 	if (*resultSeq == NULL)
11821*7c568831SAndroid Build Coastguard Worker 	    return(-1);
11822*7c568831SAndroid Build Coastguard Worker     }
11823*7c568831SAndroid Build Coastguard Worker 
11824*7c568831SAndroid Build Coastguard Worker     /*
11825*7c568831SAndroid Build Coastguard Worker      * handle the special cases of "/" amd "." being matched
11826*7c568831SAndroid Build Coastguard Worker      */
11827*7c568831SAndroid Build Coastguard Worker     if (min_depth == 0) {
11828*7c568831SAndroid Build Coastguard Worker         int res;
11829*7c568831SAndroid Build Coastguard Worker 
11830*7c568831SAndroid Build Coastguard Worker 	if (from_root) {
11831*7c568831SAndroid Build Coastguard Worker 	    /* Select "/" */
11832*7c568831SAndroid Build Coastguard Worker 	    if (toBool)
11833*7c568831SAndroid Build Coastguard Worker 		return(1);
11834*7c568831SAndroid Build Coastguard Worker             res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
11835*7c568831SAndroid Build Coastguard Worker                                            (xmlNodePtr) ctxt->doc);
11836*7c568831SAndroid Build Coastguard Worker 	} else {
11837*7c568831SAndroid Build Coastguard Worker 	    /* Select "self::node()" */
11838*7c568831SAndroid Build Coastguard Worker 	    if (toBool)
11839*7c568831SAndroid Build Coastguard Worker 		return(1);
11840*7c568831SAndroid Build Coastguard Worker             res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
11841*7c568831SAndroid Build Coastguard Worker                                            ctxt->node);
11842*7c568831SAndroid Build Coastguard Worker 	}
11843*7c568831SAndroid Build Coastguard Worker 
11844*7c568831SAndroid Build Coastguard Worker         if (res < 0)
11845*7c568831SAndroid Build Coastguard Worker             xmlXPathPErrMemory(pctxt);
11846*7c568831SAndroid Build Coastguard Worker     }
11847*7c568831SAndroid Build Coastguard Worker     if (max_depth == 0) {
11848*7c568831SAndroid Build Coastguard Worker 	return(0);
11849*7c568831SAndroid Build Coastguard Worker     }
11850*7c568831SAndroid Build Coastguard Worker 
11851*7c568831SAndroid Build Coastguard Worker     if (from_root) {
11852*7c568831SAndroid Build Coastguard Worker         cur = (xmlNodePtr)ctxt->doc;
11853*7c568831SAndroid Build Coastguard Worker     } else if (ctxt->node != NULL) {
11854*7c568831SAndroid Build Coastguard Worker         switch (ctxt->node->type) {
11855*7c568831SAndroid Build Coastguard Worker             case XML_ELEMENT_NODE:
11856*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_NODE:
11857*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_FRAG_NODE:
11858*7c568831SAndroid Build Coastguard Worker             case XML_HTML_DOCUMENT_NODE:
11859*7c568831SAndroid Build Coastguard Worker 	        cur = ctxt->node;
11860*7c568831SAndroid Build Coastguard Worker 		break;
11861*7c568831SAndroid Build Coastguard Worker             case XML_ATTRIBUTE_NODE:
11862*7c568831SAndroid Build Coastguard Worker             case XML_TEXT_NODE:
11863*7c568831SAndroid Build Coastguard Worker             case XML_CDATA_SECTION_NODE:
11864*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_REF_NODE:
11865*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_NODE:
11866*7c568831SAndroid Build Coastguard Worker             case XML_PI_NODE:
11867*7c568831SAndroid Build Coastguard Worker             case XML_COMMENT_NODE:
11868*7c568831SAndroid Build Coastguard Worker             case XML_NOTATION_NODE:
11869*7c568831SAndroid Build Coastguard Worker             case XML_DTD_NODE:
11870*7c568831SAndroid Build Coastguard Worker             case XML_DOCUMENT_TYPE_NODE:
11871*7c568831SAndroid Build Coastguard Worker             case XML_ELEMENT_DECL:
11872*7c568831SAndroid Build Coastguard Worker             case XML_ATTRIBUTE_DECL:
11873*7c568831SAndroid Build Coastguard Worker             case XML_ENTITY_DECL:
11874*7c568831SAndroid Build Coastguard Worker             case XML_NAMESPACE_DECL:
11875*7c568831SAndroid Build Coastguard Worker             case XML_XINCLUDE_START:
11876*7c568831SAndroid Build Coastguard Worker             case XML_XINCLUDE_END:
11877*7c568831SAndroid Build Coastguard Worker 		break;
11878*7c568831SAndroid Build Coastguard Worker 	}
11879*7c568831SAndroid Build Coastguard Worker 	limit = cur;
11880*7c568831SAndroid Build Coastguard Worker     }
11881*7c568831SAndroid Build Coastguard Worker     if (cur == NULL) {
11882*7c568831SAndroid Build Coastguard Worker         return(0);
11883*7c568831SAndroid Build Coastguard Worker     }
11884*7c568831SAndroid Build Coastguard Worker 
11885*7c568831SAndroid Build Coastguard Worker     patstream = xmlPatternGetStreamCtxt(comp);
11886*7c568831SAndroid Build Coastguard Worker     if (patstream == NULL) {
11887*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(pctxt);
11888*7c568831SAndroid Build Coastguard Worker 	return(-1);
11889*7c568831SAndroid Build Coastguard Worker     }
11890*7c568831SAndroid Build Coastguard Worker 
11891*7c568831SAndroid Build Coastguard Worker     eval_all_nodes = xmlStreamWantsAnyNode(patstream);
11892*7c568831SAndroid Build Coastguard Worker 
11893*7c568831SAndroid Build Coastguard Worker     if (from_root) {
11894*7c568831SAndroid Build Coastguard Worker 	ret = xmlStreamPush(patstream, NULL, NULL);
11895*7c568831SAndroid Build Coastguard Worker 	if (ret < 0) {
11896*7c568831SAndroid Build Coastguard Worker 	} else if (ret == 1) {
11897*7c568831SAndroid Build Coastguard Worker 	    if (toBool)
11898*7c568831SAndroid Build Coastguard Worker 		goto return_1;
11899*7c568831SAndroid Build Coastguard Worker 	    if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur) < 0)
11900*7c568831SAndroid Build Coastguard Worker                 xmlXPathPErrMemory(pctxt);
11901*7c568831SAndroid Build Coastguard Worker 	}
11902*7c568831SAndroid Build Coastguard Worker     }
11903*7c568831SAndroid Build Coastguard Worker     depth = 0;
11904*7c568831SAndroid Build Coastguard Worker     goto scan_children;
11905*7c568831SAndroid Build Coastguard Worker next_node:
11906*7c568831SAndroid Build Coastguard Worker     do {
11907*7c568831SAndroid Build Coastguard Worker         if (ctxt->opLimit != 0) {
11908*7c568831SAndroid Build Coastguard Worker             if (ctxt->opCount >= ctxt->opLimit) {
11909*7c568831SAndroid Build Coastguard Worker                 xmlXPathErr(ctxt, XPATH_RECURSION_LIMIT_EXCEEDED);
11910*7c568831SAndroid Build Coastguard Worker                 xmlFreeStreamCtxt(patstream);
11911*7c568831SAndroid Build Coastguard Worker                 return(-1);
11912*7c568831SAndroid Build Coastguard Worker             }
11913*7c568831SAndroid Build Coastguard Worker             ctxt->opCount++;
11914*7c568831SAndroid Build Coastguard Worker         }
11915*7c568831SAndroid Build Coastguard Worker 
11916*7c568831SAndroid Build Coastguard Worker 	switch (cur->type) {
11917*7c568831SAndroid Build Coastguard Worker 	    case XML_ELEMENT_NODE:
11918*7c568831SAndroid Build Coastguard Worker 	    case XML_TEXT_NODE:
11919*7c568831SAndroid Build Coastguard Worker 	    case XML_CDATA_SECTION_NODE:
11920*7c568831SAndroid Build Coastguard Worker 	    case XML_COMMENT_NODE:
11921*7c568831SAndroid Build Coastguard Worker 	    case XML_PI_NODE:
11922*7c568831SAndroid Build Coastguard Worker 		if (cur->type == XML_ELEMENT_NODE) {
11923*7c568831SAndroid Build Coastguard Worker 		    ret = xmlStreamPush(patstream, cur->name,
11924*7c568831SAndroid Build Coastguard Worker 				(cur->ns ? cur->ns->href : NULL));
11925*7c568831SAndroid Build Coastguard Worker 		} else if (eval_all_nodes)
11926*7c568831SAndroid Build Coastguard Worker 		    ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type);
11927*7c568831SAndroid Build Coastguard Worker 		else
11928*7c568831SAndroid Build Coastguard Worker 		    break;
11929*7c568831SAndroid Build Coastguard Worker 
11930*7c568831SAndroid Build Coastguard Worker 		if (ret < 0) {
11931*7c568831SAndroid Build Coastguard Worker 		    xmlXPathPErrMemory(pctxt);
11932*7c568831SAndroid Build Coastguard Worker 		} else if (ret == 1) {
11933*7c568831SAndroid Build Coastguard Worker 		    if (toBool)
11934*7c568831SAndroid Build Coastguard Worker 			goto return_1;
11935*7c568831SAndroid Build Coastguard Worker 		    if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
11936*7c568831SAndroid Build Coastguard Worker                                                  cur) < 0)
11937*7c568831SAndroid Build Coastguard Worker                         xmlXPathPErrMemory(pctxt);
11938*7c568831SAndroid Build Coastguard Worker 		}
11939*7c568831SAndroid Build Coastguard Worker 		if ((cur->children == NULL) || (depth >= max_depth)) {
11940*7c568831SAndroid Build Coastguard Worker 		    ret = xmlStreamPop(patstream);
11941*7c568831SAndroid Build Coastguard Worker 		    while (cur->next != NULL) {
11942*7c568831SAndroid Build Coastguard Worker 			cur = cur->next;
11943*7c568831SAndroid Build Coastguard Worker 			if ((cur->type != XML_ENTITY_DECL) &&
11944*7c568831SAndroid Build Coastguard Worker 			    (cur->type != XML_DTD_NODE))
11945*7c568831SAndroid Build Coastguard Worker 			    goto next_node;
11946*7c568831SAndroid Build Coastguard Worker 		    }
11947*7c568831SAndroid Build Coastguard Worker 		}
11948*7c568831SAndroid Build Coastguard Worker 	    default:
11949*7c568831SAndroid Build Coastguard Worker 		break;
11950*7c568831SAndroid Build Coastguard Worker 	}
11951*7c568831SAndroid Build Coastguard Worker 
11952*7c568831SAndroid Build Coastguard Worker scan_children:
11953*7c568831SAndroid Build Coastguard Worker 	if (cur->type == XML_NAMESPACE_DECL) break;
11954*7c568831SAndroid Build Coastguard Worker 	if ((cur->children != NULL) && (depth < max_depth)) {
11955*7c568831SAndroid Build Coastguard Worker 	    /*
11956*7c568831SAndroid Build Coastguard Worker 	     * Do not descend on entities declarations
11957*7c568831SAndroid Build Coastguard Worker 	     */
11958*7c568831SAndroid Build Coastguard Worker 	    if (cur->children->type != XML_ENTITY_DECL) {
11959*7c568831SAndroid Build Coastguard Worker 		cur = cur->children;
11960*7c568831SAndroid Build Coastguard Worker 		depth++;
11961*7c568831SAndroid Build Coastguard Worker 		/*
11962*7c568831SAndroid Build Coastguard Worker 		 * Skip DTDs
11963*7c568831SAndroid Build Coastguard Worker 		 */
11964*7c568831SAndroid Build Coastguard Worker 		if (cur->type != XML_DTD_NODE)
11965*7c568831SAndroid Build Coastguard Worker 		    continue;
11966*7c568831SAndroid Build Coastguard Worker 	    }
11967*7c568831SAndroid Build Coastguard Worker 	}
11968*7c568831SAndroid Build Coastguard Worker 
11969*7c568831SAndroid Build Coastguard Worker 	if (cur == limit)
11970*7c568831SAndroid Build Coastguard Worker 	    break;
11971*7c568831SAndroid Build Coastguard Worker 
11972*7c568831SAndroid Build Coastguard Worker 	while (cur->next != NULL) {
11973*7c568831SAndroid Build Coastguard Worker 	    cur = cur->next;
11974*7c568831SAndroid Build Coastguard Worker 	    if ((cur->type != XML_ENTITY_DECL) &&
11975*7c568831SAndroid Build Coastguard Worker 		(cur->type != XML_DTD_NODE))
11976*7c568831SAndroid Build Coastguard Worker 		goto next_node;
11977*7c568831SAndroid Build Coastguard Worker 	}
11978*7c568831SAndroid Build Coastguard Worker 
11979*7c568831SAndroid Build Coastguard Worker 	do {
11980*7c568831SAndroid Build Coastguard Worker 	    cur = cur->parent;
11981*7c568831SAndroid Build Coastguard Worker 	    depth--;
11982*7c568831SAndroid Build Coastguard Worker 	    if ((cur == NULL) || (cur == limit) ||
11983*7c568831SAndroid Build Coastguard Worker                 (cur->type == XML_DOCUMENT_NODE))
11984*7c568831SAndroid Build Coastguard Worker 	        goto done;
11985*7c568831SAndroid Build Coastguard Worker 	    if (cur->type == XML_ELEMENT_NODE) {
11986*7c568831SAndroid Build Coastguard Worker 		ret = xmlStreamPop(patstream);
11987*7c568831SAndroid Build Coastguard Worker 	    } else if ((eval_all_nodes) &&
11988*7c568831SAndroid Build Coastguard Worker 		((cur->type == XML_TEXT_NODE) ||
11989*7c568831SAndroid Build Coastguard Worker 		 (cur->type == XML_CDATA_SECTION_NODE) ||
11990*7c568831SAndroid Build Coastguard Worker 		 (cur->type == XML_COMMENT_NODE) ||
11991*7c568831SAndroid Build Coastguard Worker 		 (cur->type == XML_PI_NODE)))
11992*7c568831SAndroid Build Coastguard Worker 	    {
11993*7c568831SAndroid Build Coastguard Worker 		ret = xmlStreamPop(patstream);
11994*7c568831SAndroid Build Coastguard Worker 	    }
11995*7c568831SAndroid Build Coastguard Worker 	    if (cur->next != NULL) {
11996*7c568831SAndroid Build Coastguard Worker 		cur = cur->next;
11997*7c568831SAndroid Build Coastguard Worker 		break;
11998*7c568831SAndroid Build Coastguard Worker 	    }
11999*7c568831SAndroid Build Coastguard Worker 	} while (cur != NULL);
12000*7c568831SAndroid Build Coastguard Worker 
12001*7c568831SAndroid Build Coastguard Worker     } while ((cur != NULL) && (depth >= 0));
12002*7c568831SAndroid Build Coastguard Worker 
12003*7c568831SAndroid Build Coastguard Worker done:
12004*7c568831SAndroid Build Coastguard Worker 
12005*7c568831SAndroid Build Coastguard Worker     if (patstream)
12006*7c568831SAndroid Build Coastguard Worker 	xmlFreeStreamCtxt(patstream);
12007*7c568831SAndroid Build Coastguard Worker     return(0);
12008*7c568831SAndroid Build Coastguard Worker 
12009*7c568831SAndroid Build Coastguard Worker return_1:
12010*7c568831SAndroid Build Coastguard Worker     if (patstream)
12011*7c568831SAndroid Build Coastguard Worker 	xmlFreeStreamCtxt(patstream);
12012*7c568831SAndroid Build Coastguard Worker     return(1);
12013*7c568831SAndroid Build Coastguard Worker }
12014*7c568831SAndroid Build Coastguard Worker #endif /* XPATH_STREAMING */
12015*7c568831SAndroid Build Coastguard Worker 
12016*7c568831SAndroid Build Coastguard Worker /**
12017*7c568831SAndroid Build Coastguard Worker  * xmlXPathRunEval:
12018*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath parser context with the compiled expression
12019*7c568831SAndroid Build Coastguard Worker  * @toBool:  evaluate to a boolean result
12020*7c568831SAndroid Build Coastguard Worker  *
12021*7c568831SAndroid Build Coastguard Worker  * Evaluate the Precompiled XPath expression in the given context.
12022*7c568831SAndroid Build Coastguard Worker  */
12023*7c568831SAndroid Build Coastguard Worker static int
xmlXPathRunEval(xmlXPathParserContextPtr ctxt,int toBool)12024*7c568831SAndroid Build Coastguard Worker xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
12025*7c568831SAndroid Build Coastguard Worker {
12026*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp;
12027*7c568831SAndroid Build Coastguard Worker     int oldDepth;
12028*7c568831SAndroid Build Coastguard Worker 
12029*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->comp == NULL))
12030*7c568831SAndroid Build Coastguard Worker 	return(-1);
12031*7c568831SAndroid Build Coastguard Worker 
12032*7c568831SAndroid Build Coastguard Worker     if (ctxt->valueTab == NULL) {
12033*7c568831SAndroid Build Coastguard Worker 	/* Allocate the value stack */
12034*7c568831SAndroid Build Coastguard Worker 	ctxt->valueTab = (xmlXPathObjectPtr *)
12035*7c568831SAndroid Build Coastguard Worker 			 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
12036*7c568831SAndroid Build Coastguard Worker 	if (ctxt->valueTab == NULL) {
12037*7c568831SAndroid Build Coastguard Worker 	    xmlXPathPErrMemory(ctxt);
12038*7c568831SAndroid Build Coastguard Worker 	    return(-1);
12039*7c568831SAndroid Build Coastguard Worker 	}
12040*7c568831SAndroid Build Coastguard Worker 	ctxt->valueNr = 0;
12041*7c568831SAndroid Build Coastguard Worker 	ctxt->valueMax = 10;
12042*7c568831SAndroid Build Coastguard Worker 	ctxt->value = NULL;
12043*7c568831SAndroid Build Coastguard Worker     }
12044*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12045*7c568831SAndroid Build Coastguard Worker     if (ctxt->comp->stream) {
12046*7c568831SAndroid Build Coastguard Worker 	int res;
12047*7c568831SAndroid Build Coastguard Worker 
12048*7c568831SAndroid Build Coastguard Worker 	if (toBool) {
12049*7c568831SAndroid Build Coastguard Worker 	    /*
12050*7c568831SAndroid Build Coastguard Worker 	    * Evaluation to boolean result.
12051*7c568831SAndroid Build Coastguard Worker 	    */
12052*7c568831SAndroid Build Coastguard Worker 	    res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, NULL, 1);
12053*7c568831SAndroid Build Coastguard Worker 	    if (res != -1)
12054*7c568831SAndroid Build Coastguard Worker 		return(res);
12055*7c568831SAndroid Build Coastguard Worker 	} else {
12056*7c568831SAndroid Build Coastguard Worker 	    xmlXPathObjectPtr resObj = NULL;
12057*7c568831SAndroid Build Coastguard Worker 
12058*7c568831SAndroid Build Coastguard Worker 	    /*
12059*7c568831SAndroid Build Coastguard Worker 	    * Evaluation to a sequence.
12060*7c568831SAndroid Build Coastguard Worker 	    */
12061*7c568831SAndroid Build Coastguard Worker 	    res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, &resObj, 0);
12062*7c568831SAndroid Build Coastguard Worker 
12063*7c568831SAndroid Build Coastguard Worker 	    if ((res != -1) && (resObj != NULL)) {
12064*7c568831SAndroid Build Coastguard Worker 		valuePush(ctxt, resObj);
12065*7c568831SAndroid Build Coastguard Worker 		return(0);
12066*7c568831SAndroid Build Coastguard Worker 	    }
12067*7c568831SAndroid Build Coastguard Worker 	    if (resObj != NULL)
12068*7c568831SAndroid Build Coastguard Worker 		xmlXPathReleaseObject(ctxt->context, resObj);
12069*7c568831SAndroid Build Coastguard Worker 	}
12070*7c568831SAndroid Build Coastguard Worker 	/*
12071*7c568831SAndroid Build Coastguard Worker 	* QUESTION TODO: This falls back to normal XPath evaluation
12072*7c568831SAndroid Build Coastguard Worker 	* if res == -1. Is this intended?
12073*7c568831SAndroid Build Coastguard Worker 	*/
12074*7c568831SAndroid Build Coastguard Worker     }
12075*7c568831SAndroid Build Coastguard Worker #endif
12076*7c568831SAndroid Build Coastguard Worker     comp = ctxt->comp;
12077*7c568831SAndroid Build Coastguard Worker     if (comp->last < 0) {
12078*7c568831SAndroid Build Coastguard Worker         xmlXPathErr(ctxt, XPATH_STACK_ERROR);
12079*7c568831SAndroid Build Coastguard Worker 	return(-1);
12080*7c568831SAndroid Build Coastguard Worker     }
12081*7c568831SAndroid Build Coastguard Worker     oldDepth = ctxt->context->depth;
12082*7c568831SAndroid Build Coastguard Worker     if (toBool)
12083*7c568831SAndroid Build Coastguard Worker 	return(xmlXPathCompOpEvalToBoolean(ctxt,
12084*7c568831SAndroid Build Coastguard Worker 	    &comp->steps[comp->last], 0));
12085*7c568831SAndroid Build Coastguard Worker     else
12086*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
12087*7c568831SAndroid Build Coastguard Worker     ctxt->context->depth = oldDepth;
12088*7c568831SAndroid Build Coastguard Worker 
12089*7c568831SAndroid Build Coastguard Worker     return(0);
12090*7c568831SAndroid Build Coastguard Worker }
12091*7c568831SAndroid Build Coastguard Worker 
12092*7c568831SAndroid Build Coastguard Worker /************************************************************************
12093*7c568831SAndroid Build Coastguard Worker  *									*
12094*7c568831SAndroid Build Coastguard Worker  *			Public interfaces				*
12095*7c568831SAndroid Build Coastguard Worker  *									*
12096*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
12097*7c568831SAndroid Build Coastguard Worker 
12098*7c568831SAndroid Build Coastguard Worker /**
12099*7c568831SAndroid Build Coastguard Worker  * xmlXPathEvalPredicate:
12100*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
12101*7c568831SAndroid Build Coastguard Worker  * @res:  the Predicate Expression evaluation result
12102*7c568831SAndroid Build Coastguard Worker  *
12103*7c568831SAndroid Build Coastguard Worker  * Evaluate a predicate result for the current node.
12104*7c568831SAndroid Build Coastguard Worker  * A PredicateExpr is evaluated by evaluating the Expr and converting
12105*7c568831SAndroid Build Coastguard Worker  * the result to a boolean. If the result is a number, the result will
12106*7c568831SAndroid Build Coastguard Worker  * be converted to true if the number is equal to the position of the
12107*7c568831SAndroid Build Coastguard Worker  * context node in the context node list (as returned by the position
12108*7c568831SAndroid Build Coastguard Worker  * function) and will be converted to false otherwise; if the result
12109*7c568831SAndroid Build Coastguard Worker  * is not a number, then the result will be converted as if by a call
12110*7c568831SAndroid Build Coastguard Worker  * to the boolean function.
12111*7c568831SAndroid Build Coastguard Worker  *
12112*7c568831SAndroid Build Coastguard Worker  * Returns 1 if predicate is true, 0 otherwise
12113*7c568831SAndroid Build Coastguard Worker  */
12114*7c568831SAndroid Build Coastguard Worker int
xmlXPathEvalPredicate(xmlXPathContextPtr ctxt,xmlXPathObjectPtr res)12115*7c568831SAndroid Build Coastguard Worker xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
12116*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (res == NULL)) return(0);
12117*7c568831SAndroid Build Coastguard Worker     switch (res->type) {
12118*7c568831SAndroid Build Coastguard Worker         case XPATH_BOOLEAN:
12119*7c568831SAndroid Build Coastguard Worker 	    return(res->boolval);
12120*7c568831SAndroid Build Coastguard Worker         case XPATH_NUMBER:
12121*7c568831SAndroid Build Coastguard Worker 	    return(res->floatval == ctxt->proximityPosition);
12122*7c568831SAndroid Build Coastguard Worker         case XPATH_NODESET:
12123*7c568831SAndroid Build Coastguard Worker         case XPATH_XSLT_TREE:
12124*7c568831SAndroid Build Coastguard Worker 	    if (res->nodesetval == NULL)
12125*7c568831SAndroid Build Coastguard Worker 		return(0);
12126*7c568831SAndroid Build Coastguard Worker 	    return(res->nodesetval->nodeNr != 0);
12127*7c568831SAndroid Build Coastguard Worker         case XPATH_STRING:
12128*7c568831SAndroid Build Coastguard Worker 	    return((res->stringval != NULL) &&
12129*7c568831SAndroid Build Coastguard Worker 	           (xmlStrlen(res->stringval) != 0));
12130*7c568831SAndroid Build Coastguard Worker         default:
12131*7c568831SAndroid Build Coastguard Worker 	    break;
12132*7c568831SAndroid Build Coastguard Worker     }
12133*7c568831SAndroid Build Coastguard Worker     return(0);
12134*7c568831SAndroid Build Coastguard Worker }
12135*7c568831SAndroid Build Coastguard Worker 
12136*7c568831SAndroid Build Coastguard Worker /**
12137*7c568831SAndroid Build Coastguard Worker  * xmlXPathEvaluatePredicateResult:
12138*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
12139*7c568831SAndroid Build Coastguard Worker  * @res:  the Predicate Expression evaluation result
12140*7c568831SAndroid Build Coastguard Worker  *
12141*7c568831SAndroid Build Coastguard Worker  * Evaluate a predicate result for the current node.
12142*7c568831SAndroid Build Coastguard Worker  * A PredicateExpr is evaluated by evaluating the Expr and converting
12143*7c568831SAndroid Build Coastguard Worker  * the result to a boolean. If the result is a number, the result will
12144*7c568831SAndroid Build Coastguard Worker  * be converted to true if the number is equal to the position of the
12145*7c568831SAndroid Build Coastguard Worker  * context node in the context node list (as returned by the position
12146*7c568831SAndroid Build Coastguard Worker  * function) and will be converted to false otherwise; if the result
12147*7c568831SAndroid Build Coastguard Worker  * is not a number, then the result will be converted as if by a call
12148*7c568831SAndroid Build Coastguard Worker  * to the boolean function.
12149*7c568831SAndroid Build Coastguard Worker  *
12150*7c568831SAndroid Build Coastguard Worker  * Returns 1 if predicate is true, 0 otherwise
12151*7c568831SAndroid Build Coastguard Worker  */
12152*7c568831SAndroid Build Coastguard Worker int
xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr res)12153*7c568831SAndroid Build Coastguard Worker xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
12154*7c568831SAndroid Build Coastguard Worker                                 xmlXPathObjectPtr res) {
12155*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (res == NULL)) return(0);
12156*7c568831SAndroid Build Coastguard Worker     switch (res->type) {
12157*7c568831SAndroid Build Coastguard Worker         case XPATH_BOOLEAN:
12158*7c568831SAndroid Build Coastguard Worker 	    return(res->boolval);
12159*7c568831SAndroid Build Coastguard Worker         case XPATH_NUMBER:
12160*7c568831SAndroid Build Coastguard Worker #if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200))
12161*7c568831SAndroid Build Coastguard Worker 	    return((res->floatval == ctxt->context->proximityPosition) &&
12162*7c568831SAndroid Build Coastguard Worker 	           (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/
12163*7c568831SAndroid Build Coastguard Worker #else
12164*7c568831SAndroid Build Coastguard Worker 	    return(res->floatval == ctxt->context->proximityPosition);
12165*7c568831SAndroid Build Coastguard Worker #endif
12166*7c568831SAndroid Build Coastguard Worker         case XPATH_NODESET:
12167*7c568831SAndroid Build Coastguard Worker         case XPATH_XSLT_TREE:
12168*7c568831SAndroid Build Coastguard Worker 	    if (res->nodesetval == NULL)
12169*7c568831SAndroid Build Coastguard Worker 		return(0);
12170*7c568831SAndroid Build Coastguard Worker 	    return(res->nodesetval->nodeNr != 0);
12171*7c568831SAndroid Build Coastguard Worker         case XPATH_STRING:
12172*7c568831SAndroid Build Coastguard Worker 	    return((res->stringval != NULL) && (res->stringval[0] != 0));
12173*7c568831SAndroid Build Coastguard Worker         default:
12174*7c568831SAndroid Build Coastguard Worker 	    break;
12175*7c568831SAndroid Build Coastguard Worker     }
12176*7c568831SAndroid Build Coastguard Worker     return(0);
12177*7c568831SAndroid Build Coastguard Worker }
12178*7c568831SAndroid Build Coastguard Worker 
12179*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12180*7c568831SAndroid Build Coastguard Worker /**
12181*7c568831SAndroid Build Coastguard Worker  * xmlXPathTryStreamCompile:
12182*7c568831SAndroid Build Coastguard Worker  * @ctxt: an XPath context
12183*7c568831SAndroid Build Coastguard Worker  * @str:  the XPath expression
12184*7c568831SAndroid Build Coastguard Worker  *
12185*7c568831SAndroid Build Coastguard Worker  * Try to compile the XPath expression as a streamable subset.
12186*7c568831SAndroid Build Coastguard Worker  *
12187*7c568831SAndroid Build Coastguard Worker  * Returns the compiled expression or NULL if failed to compile.
12188*7c568831SAndroid Build Coastguard Worker  */
12189*7c568831SAndroid Build Coastguard Worker static xmlXPathCompExprPtr
xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt,const xmlChar * str)12190*7c568831SAndroid Build Coastguard Worker xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
12191*7c568831SAndroid Build Coastguard Worker     /*
12192*7c568831SAndroid Build Coastguard Worker      * Optimization: use streaming patterns when the XPath expression can
12193*7c568831SAndroid Build Coastguard Worker      * be compiled to a stream lookup
12194*7c568831SAndroid Build Coastguard Worker      */
12195*7c568831SAndroid Build Coastguard Worker     xmlPatternPtr stream;
12196*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp;
12197*7c568831SAndroid Build Coastguard Worker     xmlDictPtr dict = NULL;
12198*7c568831SAndroid Build Coastguard Worker     const xmlChar **namespaces = NULL;
12199*7c568831SAndroid Build Coastguard Worker     xmlNsPtr ns;
12200*7c568831SAndroid Build Coastguard Worker     int i, j;
12201*7c568831SAndroid Build Coastguard Worker 
12202*7c568831SAndroid Build Coastguard Worker     if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) &&
12203*7c568831SAndroid Build Coastguard Worker         (!xmlStrchr(str, '@'))) {
12204*7c568831SAndroid Build Coastguard Worker 	const xmlChar *tmp;
12205*7c568831SAndroid Build Coastguard Worker         int res;
12206*7c568831SAndroid Build Coastguard Worker 
12207*7c568831SAndroid Build Coastguard Worker 	/*
12208*7c568831SAndroid Build Coastguard Worker 	 * We don't try to handle expressions using the verbose axis
12209*7c568831SAndroid Build Coastguard Worker 	 * specifiers ("::"), just the simplified form at this point.
12210*7c568831SAndroid Build Coastguard Worker 	 * Additionally, if there is no list of namespaces available and
12211*7c568831SAndroid Build Coastguard Worker 	 *  there's a ":" in the expression, indicating a prefixed QName,
12212*7c568831SAndroid Build Coastguard Worker 	 *  then we won't try to compile either. xmlPatterncompile() needs
12213*7c568831SAndroid Build Coastguard Worker 	 *  to have a list of namespaces at compilation time in order to
12214*7c568831SAndroid Build Coastguard Worker 	 *  compile prefixed name tests.
12215*7c568831SAndroid Build Coastguard Worker 	 */
12216*7c568831SAndroid Build Coastguard Worker 	tmp = xmlStrchr(str, ':');
12217*7c568831SAndroid Build Coastguard Worker 	if ((tmp != NULL) &&
12218*7c568831SAndroid Build Coastguard Worker 	    ((ctxt == NULL) || (ctxt->nsNr == 0) || (tmp[1] == ':')))
12219*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
12220*7c568831SAndroid Build Coastguard Worker 
12221*7c568831SAndroid Build Coastguard Worker 	if (ctxt != NULL) {
12222*7c568831SAndroid Build Coastguard Worker 	    dict = ctxt->dict;
12223*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->nsNr > 0) {
12224*7c568831SAndroid Build Coastguard Worker 		namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*));
12225*7c568831SAndroid Build Coastguard Worker 		if (namespaces == NULL) {
12226*7c568831SAndroid Build Coastguard Worker 		    xmlXPathErrMemory(ctxt);
12227*7c568831SAndroid Build Coastguard Worker 		    return(NULL);
12228*7c568831SAndroid Build Coastguard Worker 		}
12229*7c568831SAndroid Build Coastguard Worker 		for (i = 0, j = 0; (j < ctxt->nsNr); j++) {
12230*7c568831SAndroid Build Coastguard Worker 		    ns = ctxt->namespaces[j];
12231*7c568831SAndroid Build Coastguard Worker 		    namespaces[i++] = ns->href;
12232*7c568831SAndroid Build Coastguard Worker 		    namespaces[i++] = ns->prefix;
12233*7c568831SAndroid Build Coastguard Worker 		}
12234*7c568831SAndroid Build Coastguard Worker 		namespaces[i++] = NULL;
12235*7c568831SAndroid Build Coastguard Worker 		namespaces[i] = NULL;
12236*7c568831SAndroid Build Coastguard Worker 	    }
12237*7c568831SAndroid Build Coastguard Worker 	}
12238*7c568831SAndroid Build Coastguard Worker 
12239*7c568831SAndroid Build Coastguard Worker 	res = xmlPatternCompileSafe(str, dict, XML_PATTERN_XPATH, namespaces,
12240*7c568831SAndroid Build Coastguard Worker                                     &stream);
12241*7c568831SAndroid Build Coastguard Worker 	if (namespaces != NULL) {
12242*7c568831SAndroid Build Coastguard Worker 	    xmlFree((xmlChar **)namespaces);
12243*7c568831SAndroid Build Coastguard Worker 	}
12244*7c568831SAndroid Build Coastguard Worker         if (res < 0) {
12245*7c568831SAndroid Build Coastguard Worker             xmlXPathErrMemory(ctxt);
12246*7c568831SAndroid Build Coastguard Worker             return(NULL);
12247*7c568831SAndroid Build Coastguard Worker         }
12248*7c568831SAndroid Build Coastguard Worker 	if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) {
12249*7c568831SAndroid Build Coastguard Worker 	    comp = xmlXPathNewCompExpr();
12250*7c568831SAndroid Build Coastguard Worker 	    if (comp == NULL) {
12251*7c568831SAndroid Build Coastguard Worker 		xmlXPathErrMemory(ctxt);
12252*7c568831SAndroid Build Coastguard Worker 	        xmlFreePattern(stream);
12253*7c568831SAndroid Build Coastguard Worker 		return(NULL);
12254*7c568831SAndroid Build Coastguard Worker 	    }
12255*7c568831SAndroid Build Coastguard Worker 	    comp->stream = stream;
12256*7c568831SAndroid Build Coastguard Worker 	    comp->dict = dict;
12257*7c568831SAndroid Build Coastguard Worker 	    if (comp->dict)
12258*7c568831SAndroid Build Coastguard Worker 		xmlDictReference(comp->dict);
12259*7c568831SAndroid Build Coastguard Worker 	    return(comp);
12260*7c568831SAndroid Build Coastguard Worker 	}
12261*7c568831SAndroid Build Coastguard Worker 	xmlFreePattern(stream);
12262*7c568831SAndroid Build Coastguard Worker     }
12263*7c568831SAndroid Build Coastguard Worker     return(NULL);
12264*7c568831SAndroid Build Coastguard Worker }
12265*7c568831SAndroid Build Coastguard Worker #endif /* XPATH_STREAMING */
12266*7c568831SAndroid Build Coastguard Worker 
12267*7c568831SAndroid Build Coastguard Worker static void
xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,xmlXPathStepOpPtr op)12268*7c568831SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,
12269*7c568831SAndroid Build Coastguard Worker                            xmlXPathStepOpPtr op)
12270*7c568831SAndroid Build Coastguard Worker {
12271*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp = pctxt->comp;
12272*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr ctxt;
12273*7c568831SAndroid Build Coastguard Worker 
12274*7c568831SAndroid Build Coastguard Worker     /*
12275*7c568831SAndroid Build Coastguard Worker     * Try to rewrite "descendant-or-self::node()/foo" to an optimized
12276*7c568831SAndroid Build Coastguard Worker     * internal representation.
12277*7c568831SAndroid Build Coastguard Worker     */
12278*7c568831SAndroid Build Coastguard Worker 
12279*7c568831SAndroid Build Coastguard Worker     if ((op->op == XPATH_OP_COLLECT /* 11 */) &&
12280*7c568831SAndroid Build Coastguard Worker         (op->ch1 != -1) &&
12281*7c568831SAndroid Build Coastguard Worker         (op->ch2 == -1 /* no predicate */))
12282*7c568831SAndroid Build Coastguard Worker     {
12283*7c568831SAndroid Build Coastguard Worker         xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
12284*7c568831SAndroid Build Coastguard Worker 
12285*7c568831SAndroid Build Coastguard Worker         if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&
12286*7c568831SAndroid Build Coastguard Worker             ((xmlXPathAxisVal) prevop->value ==
12287*7c568831SAndroid Build Coastguard Worker                 AXIS_DESCENDANT_OR_SELF) &&
12288*7c568831SAndroid Build Coastguard Worker             (prevop->ch2 == -1) &&
12289*7c568831SAndroid Build Coastguard Worker             ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&
12290*7c568831SAndroid Build Coastguard Worker             ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE))
12291*7c568831SAndroid Build Coastguard Worker         {
12292*7c568831SAndroid Build Coastguard Worker             /*
12293*7c568831SAndroid Build Coastguard Worker             * This is a "descendant-or-self::node()" without predicates.
12294*7c568831SAndroid Build Coastguard Worker             * Try to eliminate it.
12295*7c568831SAndroid Build Coastguard Worker             */
12296*7c568831SAndroid Build Coastguard Worker 
12297*7c568831SAndroid Build Coastguard Worker             switch ((xmlXPathAxisVal) op->value) {
12298*7c568831SAndroid Build Coastguard Worker                 case AXIS_CHILD:
12299*7c568831SAndroid Build Coastguard Worker                 case AXIS_DESCENDANT:
12300*7c568831SAndroid Build Coastguard Worker                     /*
12301*7c568831SAndroid Build Coastguard Worker                     * Convert "descendant-or-self::node()/child::" or
12302*7c568831SAndroid Build Coastguard Worker                     * "descendant-or-self::node()/descendant::" to
12303*7c568831SAndroid Build Coastguard Worker                     * "descendant::"
12304*7c568831SAndroid Build Coastguard Worker                     */
12305*7c568831SAndroid Build Coastguard Worker                     op->ch1   = prevop->ch1;
12306*7c568831SAndroid Build Coastguard Worker                     op->value = AXIS_DESCENDANT;
12307*7c568831SAndroid Build Coastguard Worker                     break;
12308*7c568831SAndroid Build Coastguard Worker                 case AXIS_SELF:
12309*7c568831SAndroid Build Coastguard Worker                 case AXIS_DESCENDANT_OR_SELF:
12310*7c568831SAndroid Build Coastguard Worker                     /*
12311*7c568831SAndroid Build Coastguard Worker                     * Convert "descendant-or-self::node()/self::" or
12312*7c568831SAndroid Build Coastguard Worker                     * "descendant-or-self::node()/descendant-or-self::" to
12313*7c568831SAndroid Build Coastguard Worker                     * to "descendant-or-self::"
12314*7c568831SAndroid Build Coastguard Worker                     */
12315*7c568831SAndroid Build Coastguard Worker                     op->ch1   = prevop->ch1;
12316*7c568831SAndroid Build Coastguard Worker                     op->value = AXIS_DESCENDANT_OR_SELF;
12317*7c568831SAndroid Build Coastguard Worker                     break;
12318*7c568831SAndroid Build Coastguard Worker                 default:
12319*7c568831SAndroid Build Coastguard Worker                     break;
12320*7c568831SAndroid Build Coastguard Worker             }
12321*7c568831SAndroid Build Coastguard Worker 	}
12322*7c568831SAndroid Build Coastguard Worker     }
12323*7c568831SAndroid Build Coastguard Worker 
12324*7c568831SAndroid Build Coastguard Worker     /* OP_VALUE has invalid ch1. */
12325*7c568831SAndroid Build Coastguard Worker     if (op->op == XPATH_OP_VALUE)
12326*7c568831SAndroid Build Coastguard Worker         return;
12327*7c568831SAndroid Build Coastguard Worker 
12328*7c568831SAndroid Build Coastguard Worker     /* Recurse */
12329*7c568831SAndroid Build Coastguard Worker     ctxt = pctxt->context;
12330*7c568831SAndroid Build Coastguard Worker     if (ctxt != NULL) {
12331*7c568831SAndroid Build Coastguard Worker         if (ctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
12332*7c568831SAndroid Build Coastguard Worker             return;
12333*7c568831SAndroid Build Coastguard Worker         ctxt->depth += 1;
12334*7c568831SAndroid Build Coastguard Worker     }
12335*7c568831SAndroid Build Coastguard Worker     if (op->ch1 != -1)
12336*7c568831SAndroid Build Coastguard Worker         xmlXPathOptimizeExpression(pctxt, &comp->steps[op->ch1]);
12337*7c568831SAndroid Build Coastguard Worker     if (op->ch2 != -1)
12338*7c568831SAndroid Build Coastguard Worker 	xmlXPathOptimizeExpression(pctxt, &comp->steps[op->ch2]);
12339*7c568831SAndroid Build Coastguard Worker     if (ctxt != NULL)
12340*7c568831SAndroid Build Coastguard Worker         ctxt->depth -= 1;
12341*7c568831SAndroid Build Coastguard Worker }
12342*7c568831SAndroid Build Coastguard Worker 
12343*7c568831SAndroid Build Coastguard Worker /**
12344*7c568831SAndroid Build Coastguard Worker  * xmlXPathCtxtCompile:
12345*7c568831SAndroid Build Coastguard Worker  * @ctxt: an XPath context
12346*7c568831SAndroid Build Coastguard Worker  * @str:  the XPath expression
12347*7c568831SAndroid Build Coastguard Worker  *
12348*7c568831SAndroid Build Coastguard Worker  * Compile an XPath expression
12349*7c568831SAndroid Build Coastguard Worker  *
12350*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
12351*7c568831SAndroid Build Coastguard Worker  *         the caller has to free the object.
12352*7c568831SAndroid Build Coastguard Worker  */
12353*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr
xmlXPathCtxtCompile(xmlXPathContextPtr ctxt,const xmlChar * str)12354*7c568831SAndroid Build Coastguard Worker xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
12355*7c568831SAndroid Build Coastguard Worker     xmlXPathParserContextPtr pctxt;
12356*7c568831SAndroid Build Coastguard Worker     xmlXPathContextPtr tmpctxt = NULL;
12357*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp;
12358*7c568831SAndroid Build Coastguard Worker     int oldDepth = 0;
12359*7c568831SAndroid Build Coastguard Worker 
12360*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12361*7c568831SAndroid Build Coastguard Worker     comp = xmlXPathTryStreamCompile(ctxt, str);
12362*7c568831SAndroid Build Coastguard Worker     if (comp != NULL)
12363*7c568831SAndroid Build Coastguard Worker         return(comp);
12364*7c568831SAndroid Build Coastguard Worker #endif
12365*7c568831SAndroid Build Coastguard Worker 
12366*7c568831SAndroid Build Coastguard Worker     xmlInitParser();
12367*7c568831SAndroid Build Coastguard Worker 
12368*7c568831SAndroid Build Coastguard Worker     /*
12369*7c568831SAndroid Build Coastguard Worker      * We need an xmlXPathContext for the depth check.
12370*7c568831SAndroid Build Coastguard Worker      */
12371*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL) {
12372*7c568831SAndroid Build Coastguard Worker         tmpctxt = xmlXPathNewContext(NULL);
12373*7c568831SAndroid Build Coastguard Worker         if (tmpctxt == NULL)
12374*7c568831SAndroid Build Coastguard Worker             return(NULL);
12375*7c568831SAndroid Build Coastguard Worker         ctxt = tmpctxt;
12376*7c568831SAndroid Build Coastguard Worker     }
12377*7c568831SAndroid Build Coastguard Worker 
12378*7c568831SAndroid Build Coastguard Worker     pctxt = xmlXPathNewParserContext(str, ctxt);
12379*7c568831SAndroid Build Coastguard Worker     if (pctxt == NULL) {
12380*7c568831SAndroid Build Coastguard Worker         if (tmpctxt != NULL)
12381*7c568831SAndroid Build Coastguard Worker             xmlXPathFreeContext(tmpctxt);
12382*7c568831SAndroid Build Coastguard Worker         return NULL;
12383*7c568831SAndroid Build Coastguard Worker     }
12384*7c568831SAndroid Build Coastguard Worker 
12385*7c568831SAndroid Build Coastguard Worker     oldDepth = ctxt->depth;
12386*7c568831SAndroid Build Coastguard Worker     xmlXPathCompileExpr(pctxt, 1);
12387*7c568831SAndroid Build Coastguard Worker     ctxt->depth = oldDepth;
12388*7c568831SAndroid Build Coastguard Worker 
12389*7c568831SAndroid Build Coastguard Worker     if( pctxt->error != XPATH_EXPRESSION_OK )
12390*7c568831SAndroid Build Coastguard Worker     {
12391*7c568831SAndroid Build Coastguard Worker         xmlXPathFreeParserContext(pctxt);
12392*7c568831SAndroid Build Coastguard Worker         if (tmpctxt != NULL)
12393*7c568831SAndroid Build Coastguard Worker             xmlXPathFreeContext(tmpctxt);
12394*7c568831SAndroid Build Coastguard Worker         return(NULL);
12395*7c568831SAndroid Build Coastguard Worker     }
12396*7c568831SAndroid Build Coastguard Worker 
12397*7c568831SAndroid Build Coastguard Worker     if (*pctxt->cur != 0) {
12398*7c568831SAndroid Build Coastguard Worker 	/*
12399*7c568831SAndroid Build Coastguard Worker 	 * aleksey: in some cases this line prints *second* error message
12400*7c568831SAndroid Build Coastguard Worker 	 * (see bug #78858) and probably this should be fixed.
12401*7c568831SAndroid Build Coastguard Worker 	 * However, we are not sure that all error messages are printed
12402*7c568831SAndroid Build Coastguard Worker 	 * out in other places. It's not critical so we leave it as-is for now
12403*7c568831SAndroid Build Coastguard Worker 	 */
12404*7c568831SAndroid Build Coastguard Worker 	xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
12405*7c568831SAndroid Build Coastguard Worker 	comp = NULL;
12406*7c568831SAndroid Build Coastguard Worker     } else {
12407*7c568831SAndroid Build Coastguard Worker 	comp = pctxt->comp;
12408*7c568831SAndroid Build Coastguard Worker 	if ((comp->nbStep > 1) && (comp->last >= 0)) {
12409*7c568831SAndroid Build Coastguard Worker             if (ctxt != NULL)
12410*7c568831SAndroid Build Coastguard Worker                 oldDepth = ctxt->depth;
12411*7c568831SAndroid Build Coastguard Worker 	    xmlXPathOptimizeExpression(pctxt, &comp->steps[comp->last]);
12412*7c568831SAndroid Build Coastguard Worker             if (ctxt != NULL)
12413*7c568831SAndroid Build Coastguard Worker                 ctxt->depth = oldDepth;
12414*7c568831SAndroid Build Coastguard Worker 	}
12415*7c568831SAndroid Build Coastguard Worker 	pctxt->comp = NULL;
12416*7c568831SAndroid Build Coastguard Worker     }
12417*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeParserContext(pctxt);
12418*7c568831SAndroid Build Coastguard Worker     if (tmpctxt != NULL)
12419*7c568831SAndroid Build Coastguard Worker         xmlXPathFreeContext(tmpctxt);
12420*7c568831SAndroid Build Coastguard Worker 
12421*7c568831SAndroid Build Coastguard Worker     if (comp != NULL) {
12422*7c568831SAndroid Build Coastguard Worker 	comp->expr = xmlStrdup(str);
12423*7c568831SAndroid Build Coastguard Worker     }
12424*7c568831SAndroid Build Coastguard Worker     return(comp);
12425*7c568831SAndroid Build Coastguard Worker }
12426*7c568831SAndroid Build Coastguard Worker 
12427*7c568831SAndroid Build Coastguard Worker /**
12428*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompile:
12429*7c568831SAndroid Build Coastguard Worker  * @str:  the XPath expression
12430*7c568831SAndroid Build Coastguard Worker  *
12431*7c568831SAndroid Build Coastguard Worker  * Compile an XPath expression
12432*7c568831SAndroid Build Coastguard Worker  *
12433*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
12434*7c568831SAndroid Build Coastguard Worker  *         the caller has to free the object.
12435*7c568831SAndroid Build Coastguard Worker  */
12436*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr
xmlXPathCompile(const xmlChar * str)12437*7c568831SAndroid Build Coastguard Worker xmlXPathCompile(const xmlChar *str) {
12438*7c568831SAndroid Build Coastguard Worker     return(xmlXPathCtxtCompile(NULL, str));
12439*7c568831SAndroid Build Coastguard Worker }
12440*7c568831SAndroid Build Coastguard Worker 
12441*7c568831SAndroid Build Coastguard Worker /**
12442*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompiledEvalInternal:
12443*7c568831SAndroid Build Coastguard Worker  * @comp:  the compiled XPath expression
12444*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
12445*7c568831SAndroid Build Coastguard Worker  * @resObj: the resulting XPath object or NULL
12446*7c568831SAndroid Build Coastguard Worker  * @toBool: 1 if only a boolean result is requested
12447*7c568831SAndroid Build Coastguard Worker  *
12448*7c568831SAndroid Build Coastguard Worker  * Evaluate the Precompiled XPath expression in the given context.
12449*7c568831SAndroid Build Coastguard Worker  * The caller has to free @resObj.
12450*7c568831SAndroid Build Coastguard Worker  *
12451*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12452*7c568831SAndroid Build Coastguard Worker  *         the caller has to free the object.
12453*7c568831SAndroid Build Coastguard Worker  */
12454*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt,xmlXPathObjectPtr * resObjPtr,int toBool)12455*7c568831SAndroid Build Coastguard Worker xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
12456*7c568831SAndroid Build Coastguard Worker 			     xmlXPathContextPtr ctxt,
12457*7c568831SAndroid Build Coastguard Worker 			     xmlXPathObjectPtr *resObjPtr,
12458*7c568831SAndroid Build Coastguard Worker 			     int toBool)
12459*7c568831SAndroid Build Coastguard Worker {
12460*7c568831SAndroid Build Coastguard Worker     xmlXPathParserContextPtr pctxt;
12461*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr resObj = NULL;
12462*7c568831SAndroid Build Coastguard Worker     int res;
12463*7c568831SAndroid Build Coastguard Worker 
12464*7c568831SAndroid Build Coastguard Worker     if (comp == NULL)
12465*7c568831SAndroid Build Coastguard Worker 	return(-1);
12466*7c568831SAndroid Build Coastguard Worker     xmlInitParser();
12467*7c568831SAndroid Build Coastguard Worker 
12468*7c568831SAndroid Build Coastguard Worker     xmlResetError(&ctxt->lastError);
12469*7c568831SAndroid Build Coastguard Worker 
12470*7c568831SAndroid Build Coastguard Worker     pctxt = xmlXPathCompParserContext(comp, ctxt);
12471*7c568831SAndroid Build Coastguard Worker     if (pctxt == NULL)
12472*7c568831SAndroid Build Coastguard Worker         return(-1);
12473*7c568831SAndroid Build Coastguard Worker     res = xmlXPathRunEval(pctxt, toBool);
12474*7c568831SAndroid Build Coastguard Worker 
12475*7c568831SAndroid Build Coastguard Worker     if (pctxt->error == XPATH_EXPRESSION_OK) {
12476*7c568831SAndroid Build Coastguard Worker         if (pctxt->valueNr != ((toBool) ? 0 : 1))
12477*7c568831SAndroid Build Coastguard Worker             xmlXPathErr(pctxt, XPATH_STACK_ERROR);
12478*7c568831SAndroid Build Coastguard Worker         else if (!toBool)
12479*7c568831SAndroid Build Coastguard Worker             resObj = valuePop(pctxt);
12480*7c568831SAndroid Build Coastguard Worker     }
12481*7c568831SAndroid Build Coastguard Worker 
12482*7c568831SAndroid Build Coastguard Worker     if (resObjPtr)
12483*7c568831SAndroid Build Coastguard Worker         *resObjPtr = resObj;
12484*7c568831SAndroid Build Coastguard Worker     else
12485*7c568831SAndroid Build Coastguard Worker         xmlXPathReleaseObject(ctxt, resObj);
12486*7c568831SAndroid Build Coastguard Worker 
12487*7c568831SAndroid Build Coastguard Worker     pctxt->comp = NULL;
12488*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeParserContext(pctxt);
12489*7c568831SAndroid Build Coastguard Worker 
12490*7c568831SAndroid Build Coastguard Worker     return(res);
12491*7c568831SAndroid Build Coastguard Worker }
12492*7c568831SAndroid Build Coastguard Worker 
12493*7c568831SAndroid Build Coastguard Worker /**
12494*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompiledEval:
12495*7c568831SAndroid Build Coastguard Worker  * @comp:  the compiled XPath expression
12496*7c568831SAndroid Build Coastguard Worker  * @ctx:  the XPath context
12497*7c568831SAndroid Build Coastguard Worker  *
12498*7c568831SAndroid Build Coastguard Worker  * Evaluate the Precompiled XPath expression in the given context.
12499*7c568831SAndroid Build Coastguard Worker  *
12500*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12501*7c568831SAndroid Build Coastguard Worker  *         the caller has to free the object.
12502*7c568831SAndroid Build Coastguard Worker  */
12503*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathCompiledEval(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctx)12504*7c568831SAndroid Build Coastguard Worker xmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx)
12505*7c568831SAndroid Build Coastguard Worker {
12506*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr res = NULL;
12507*7c568831SAndroid Build Coastguard Worker 
12508*7c568831SAndroid Build Coastguard Worker     xmlXPathCompiledEvalInternal(comp, ctx, &res, 0);
12509*7c568831SAndroid Build Coastguard Worker     return(res);
12510*7c568831SAndroid Build Coastguard Worker }
12511*7c568831SAndroid Build Coastguard Worker 
12512*7c568831SAndroid Build Coastguard Worker /**
12513*7c568831SAndroid Build Coastguard Worker  * xmlXPathCompiledEvalToBoolean:
12514*7c568831SAndroid Build Coastguard Worker  * @comp:  the compiled XPath expression
12515*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
12516*7c568831SAndroid Build Coastguard Worker  *
12517*7c568831SAndroid Build Coastguard Worker  * Applies the XPath boolean() function on the result of the given
12518*7c568831SAndroid Build Coastguard Worker  * compiled expression.
12519*7c568831SAndroid Build Coastguard Worker  *
12520*7c568831SAndroid Build Coastguard Worker  * Returns 1 if the expression evaluated to true, 0 if to false and
12521*7c568831SAndroid Build Coastguard Worker  *         -1 in API and internal errors.
12522*7c568831SAndroid Build Coastguard Worker  */
12523*7c568831SAndroid Build Coastguard Worker int
xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt)12524*7c568831SAndroid Build Coastguard Worker xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp,
12525*7c568831SAndroid Build Coastguard Worker 			      xmlXPathContextPtr ctxt)
12526*7c568831SAndroid Build Coastguard Worker {
12527*7c568831SAndroid Build Coastguard Worker     return(xmlXPathCompiledEvalInternal(comp, ctxt, NULL, 1));
12528*7c568831SAndroid Build Coastguard Worker }
12529*7c568831SAndroid Build Coastguard Worker 
12530*7c568831SAndroid Build Coastguard Worker /**
12531*7c568831SAndroid Build Coastguard Worker  * xmlXPathEvalExpr:
12532*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
12533*7c568831SAndroid Build Coastguard Worker  *
12534*7c568831SAndroid Build Coastguard Worker  * DEPRECATED: Internal function, don't use.
12535*7c568831SAndroid Build Coastguard Worker  *
12536*7c568831SAndroid Build Coastguard Worker  * Parse and evaluate an XPath expression in the given context,
12537*7c568831SAndroid Build Coastguard Worker  * then push the result on the context stack
12538*7c568831SAndroid Build Coastguard Worker  */
12539*7c568831SAndroid Build Coastguard Worker void
xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt)12540*7c568831SAndroid Build Coastguard Worker xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
12541*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12542*7c568831SAndroid Build Coastguard Worker     xmlXPathCompExprPtr comp;
12543*7c568831SAndroid Build Coastguard Worker #endif
12544*7c568831SAndroid Build Coastguard Worker     int oldDepth = 0;
12545*7c568831SAndroid Build Coastguard Worker 
12546*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (ctxt->context == NULL))
12547*7c568831SAndroid Build Coastguard Worker         return;
12548*7c568831SAndroid Build Coastguard Worker     if (ctxt->context->lastError.code != 0)
12549*7c568831SAndroid Build Coastguard Worker         return;
12550*7c568831SAndroid Build Coastguard Worker 
12551*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12552*7c568831SAndroid Build Coastguard Worker     comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base);
12553*7c568831SAndroid Build Coastguard Worker     if ((comp == NULL) &&
12554*7c568831SAndroid Build Coastguard Worker         (ctxt->context->lastError.code == XML_ERR_NO_MEMORY)) {
12555*7c568831SAndroid Build Coastguard Worker         xmlXPathPErrMemory(ctxt);
12556*7c568831SAndroid Build Coastguard Worker         return;
12557*7c568831SAndroid Build Coastguard Worker     }
12558*7c568831SAndroid Build Coastguard Worker     if (comp != NULL) {
12559*7c568831SAndroid Build Coastguard Worker         if (ctxt->comp != NULL)
12560*7c568831SAndroid Build Coastguard Worker 	    xmlXPathFreeCompExpr(ctxt->comp);
12561*7c568831SAndroid Build Coastguard Worker         ctxt->comp = comp;
12562*7c568831SAndroid Build Coastguard Worker     } else
12563*7c568831SAndroid Build Coastguard Worker #endif
12564*7c568831SAndroid Build Coastguard Worker     {
12565*7c568831SAndroid Build Coastguard Worker         if (ctxt->context != NULL)
12566*7c568831SAndroid Build Coastguard Worker             oldDepth = ctxt->context->depth;
12567*7c568831SAndroid Build Coastguard Worker 	xmlXPathCompileExpr(ctxt, 1);
12568*7c568831SAndroid Build Coastguard Worker         if (ctxt->context != NULL)
12569*7c568831SAndroid Build Coastguard Worker             ctxt->context->depth = oldDepth;
12570*7c568831SAndroid Build Coastguard Worker         CHECK_ERROR;
12571*7c568831SAndroid Build Coastguard Worker 
12572*7c568831SAndroid Build Coastguard Worker         /* Check for trailing characters. */
12573*7c568831SAndroid Build Coastguard Worker         if (*ctxt->cur != 0)
12574*7c568831SAndroid Build Coastguard Worker             XP_ERROR(XPATH_EXPR_ERROR);
12575*7c568831SAndroid Build Coastguard Worker 
12576*7c568831SAndroid Build Coastguard Worker 	if ((ctxt->comp->nbStep > 1) && (ctxt->comp->last >= 0)) {
12577*7c568831SAndroid Build Coastguard Worker             if (ctxt->context != NULL)
12578*7c568831SAndroid Build Coastguard Worker                 oldDepth = ctxt->context->depth;
12579*7c568831SAndroid Build Coastguard Worker 	    xmlXPathOptimizeExpression(ctxt,
12580*7c568831SAndroid Build Coastguard Worker 		&ctxt->comp->steps[ctxt->comp->last]);
12581*7c568831SAndroid Build Coastguard Worker             if (ctxt->context != NULL)
12582*7c568831SAndroid Build Coastguard Worker                 ctxt->context->depth = oldDepth;
12583*7c568831SAndroid Build Coastguard Worker         }
12584*7c568831SAndroid Build Coastguard Worker     }
12585*7c568831SAndroid Build Coastguard Worker 
12586*7c568831SAndroid Build Coastguard Worker     xmlXPathRunEval(ctxt, 0);
12587*7c568831SAndroid Build Coastguard Worker }
12588*7c568831SAndroid Build Coastguard Worker 
12589*7c568831SAndroid Build Coastguard Worker /**
12590*7c568831SAndroid Build Coastguard Worker  * xmlXPathEval:
12591*7c568831SAndroid Build Coastguard Worker  * @str:  the XPath expression
12592*7c568831SAndroid Build Coastguard Worker  * @ctx:  the XPath context
12593*7c568831SAndroid Build Coastguard Worker  *
12594*7c568831SAndroid Build Coastguard Worker  * Evaluate the XPath Location Path in the given context.
12595*7c568831SAndroid Build Coastguard Worker  *
12596*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12597*7c568831SAndroid Build Coastguard Worker  *         the caller has to free the object.
12598*7c568831SAndroid Build Coastguard Worker  */
12599*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathEval(const xmlChar * str,xmlXPathContextPtr ctx)12600*7c568831SAndroid Build Coastguard Worker xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
12601*7c568831SAndroid Build Coastguard Worker     xmlXPathParserContextPtr ctxt;
12602*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr res;
12603*7c568831SAndroid Build Coastguard Worker 
12604*7c568831SAndroid Build Coastguard Worker     if (ctx == NULL)
12605*7c568831SAndroid Build Coastguard Worker         return(NULL);
12606*7c568831SAndroid Build Coastguard Worker 
12607*7c568831SAndroid Build Coastguard Worker     xmlInitParser();
12608*7c568831SAndroid Build Coastguard Worker 
12609*7c568831SAndroid Build Coastguard Worker     xmlResetError(&ctx->lastError);
12610*7c568831SAndroid Build Coastguard Worker 
12611*7c568831SAndroid Build Coastguard Worker     ctxt = xmlXPathNewParserContext(str, ctx);
12612*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
12613*7c568831SAndroid Build Coastguard Worker         return NULL;
12614*7c568831SAndroid Build Coastguard Worker     xmlXPathEvalExpr(ctxt);
12615*7c568831SAndroid Build Coastguard Worker 
12616*7c568831SAndroid Build Coastguard Worker     if (ctxt->error != XPATH_EXPRESSION_OK) {
12617*7c568831SAndroid Build Coastguard Worker 	res = NULL;
12618*7c568831SAndroid Build Coastguard Worker     } else if (ctxt->valueNr != 1) {
12619*7c568831SAndroid Build Coastguard Worker         xmlXPathErr(ctxt, XPATH_STACK_ERROR);
12620*7c568831SAndroid Build Coastguard Worker 	res = NULL;
12621*7c568831SAndroid Build Coastguard Worker     } else {
12622*7c568831SAndroid Build Coastguard Worker 	res = valuePop(ctxt);
12623*7c568831SAndroid Build Coastguard Worker     }
12624*7c568831SAndroid Build Coastguard Worker 
12625*7c568831SAndroid Build Coastguard Worker     xmlXPathFreeParserContext(ctxt);
12626*7c568831SAndroid Build Coastguard Worker     return(res);
12627*7c568831SAndroid Build Coastguard Worker }
12628*7c568831SAndroid Build Coastguard Worker 
12629*7c568831SAndroid Build Coastguard Worker /**
12630*7c568831SAndroid Build Coastguard Worker  * xmlXPathSetContextNode:
12631*7c568831SAndroid Build Coastguard Worker  * @node: the node to to use as the context node
12632*7c568831SAndroid Build Coastguard Worker  * @ctx:  the XPath context
12633*7c568831SAndroid Build Coastguard Worker  *
12634*7c568831SAndroid Build Coastguard Worker  * Sets 'node' as the context node. The node must be in the same
12635*7c568831SAndroid Build Coastguard Worker  * document as that associated with the context.
12636*7c568831SAndroid Build Coastguard Worker  *
12637*7c568831SAndroid Build Coastguard Worker  * Returns -1 in case of error or 0 if successful
12638*7c568831SAndroid Build Coastguard Worker  */
12639*7c568831SAndroid Build Coastguard Worker int
xmlXPathSetContextNode(xmlNodePtr node,xmlXPathContextPtr ctx)12640*7c568831SAndroid Build Coastguard Worker xmlXPathSetContextNode(xmlNodePtr node, xmlXPathContextPtr ctx) {
12641*7c568831SAndroid Build Coastguard Worker     if ((node == NULL) || (ctx == NULL))
12642*7c568831SAndroid Build Coastguard Worker         return(-1);
12643*7c568831SAndroid Build Coastguard Worker 
12644*7c568831SAndroid Build Coastguard Worker     if (node->doc == ctx->doc) {
12645*7c568831SAndroid Build Coastguard Worker         ctx->node = node;
12646*7c568831SAndroid Build Coastguard Worker 	return(0);
12647*7c568831SAndroid Build Coastguard Worker     }
12648*7c568831SAndroid Build Coastguard Worker     return(-1);
12649*7c568831SAndroid Build Coastguard Worker }
12650*7c568831SAndroid Build Coastguard Worker 
12651*7c568831SAndroid Build Coastguard Worker /**
12652*7c568831SAndroid Build Coastguard Worker  * xmlXPathNodeEval:
12653*7c568831SAndroid Build Coastguard Worker  * @node: the node to to use as the context node
12654*7c568831SAndroid Build Coastguard Worker  * @str:  the XPath expression
12655*7c568831SAndroid Build Coastguard Worker  * @ctx:  the XPath context
12656*7c568831SAndroid Build Coastguard Worker  *
12657*7c568831SAndroid Build Coastguard Worker  * Evaluate the XPath Location Path in the given context. The node 'node'
12658*7c568831SAndroid Build Coastguard Worker  * is set as the context node. The context node is not restored.
12659*7c568831SAndroid Build Coastguard Worker  *
12660*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12661*7c568831SAndroid Build Coastguard Worker  *         the caller has to free the object.
12662*7c568831SAndroid Build Coastguard Worker  */
12663*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNodeEval(xmlNodePtr node,const xmlChar * str,xmlXPathContextPtr ctx)12664*7c568831SAndroid Build Coastguard Worker xmlXPathNodeEval(xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx) {
12665*7c568831SAndroid Build Coastguard Worker     if (str == NULL)
12666*7c568831SAndroid Build Coastguard Worker         return(NULL);
12667*7c568831SAndroid Build Coastguard Worker     if (xmlXPathSetContextNode(node, ctx) < 0)
12668*7c568831SAndroid Build Coastguard Worker         return(NULL);
12669*7c568831SAndroid Build Coastguard Worker     return(xmlXPathEval(str, ctx));
12670*7c568831SAndroid Build Coastguard Worker }
12671*7c568831SAndroid Build Coastguard Worker 
12672*7c568831SAndroid Build Coastguard Worker /**
12673*7c568831SAndroid Build Coastguard Worker  * xmlXPathEvalExpression:
12674*7c568831SAndroid Build Coastguard Worker  * @str:  the XPath expression
12675*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
12676*7c568831SAndroid Build Coastguard Worker  *
12677*7c568831SAndroid Build Coastguard Worker  * Alias for xmlXPathEval().
12678*7c568831SAndroid Build Coastguard Worker  *
12679*7c568831SAndroid Build Coastguard Worker  * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12680*7c568831SAndroid Build Coastguard Worker  *         the caller has to free the object.
12681*7c568831SAndroid Build Coastguard Worker  */
12682*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathEvalExpression(const xmlChar * str,xmlXPathContextPtr ctxt)12683*7c568831SAndroid Build Coastguard Worker xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
12684*7c568831SAndroid Build Coastguard Worker     return(xmlXPathEval(str, ctxt));
12685*7c568831SAndroid Build Coastguard Worker }
12686*7c568831SAndroid Build Coastguard Worker 
12687*7c568831SAndroid Build Coastguard Worker /************************************************************************
12688*7c568831SAndroid Build Coastguard Worker  *									*
12689*7c568831SAndroid Build Coastguard Worker  *	Extra functions not pertaining to the XPath spec		*
12690*7c568831SAndroid Build Coastguard Worker  *									*
12691*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
12692*7c568831SAndroid Build Coastguard Worker /**
12693*7c568831SAndroid Build Coastguard Worker  * xmlXPathEscapeUriFunction:
12694*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath Parser context
12695*7c568831SAndroid Build Coastguard Worker  * @nargs:  the number of arguments
12696*7c568831SAndroid Build Coastguard Worker  *
12697*7c568831SAndroid Build Coastguard Worker  * Implement the escape-uri() XPath function
12698*7c568831SAndroid Build Coastguard Worker  *    string escape-uri(string $str, bool $escape-reserved)
12699*7c568831SAndroid Build Coastguard Worker  *
12700*7c568831SAndroid Build Coastguard Worker  * This function applies the URI escaping rules defined in section 2 of [RFC
12701*7c568831SAndroid Build Coastguard Worker  * 2396] to the string supplied as $uri-part, which typically represents all
12702*7c568831SAndroid Build Coastguard Worker  * or part of a URI. The effect of the function is to replace any special
12703*7c568831SAndroid Build Coastguard Worker  * character in the string by an escape sequence of the form %xx%yy...,
12704*7c568831SAndroid Build Coastguard Worker  * where xxyy... is the hexadecimal representation of the octets used to
12705*7c568831SAndroid Build Coastguard Worker  * represent the character in UTF-8.
12706*7c568831SAndroid Build Coastguard Worker  *
12707*7c568831SAndroid Build Coastguard Worker  * The set of characters that are escaped depends on the setting of the
12708*7c568831SAndroid Build Coastguard Worker  * boolean argument $escape-reserved.
12709*7c568831SAndroid Build Coastguard Worker  *
12710*7c568831SAndroid Build Coastguard Worker  * If $escape-reserved is true, all characters are escaped other than lower
12711*7c568831SAndroid Build Coastguard Worker  * case letters a-z, upper case letters A-Z, digits 0-9, and the characters
12712*7c568831SAndroid Build Coastguard Worker  * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!"
12713*7c568831SAndroid Build Coastguard Worker  * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only
12714*7c568831SAndroid Build Coastguard Worker  * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and
12715*7c568831SAndroid Build Coastguard Worker  * A-F).
12716*7c568831SAndroid Build Coastguard Worker  *
12717*7c568831SAndroid Build Coastguard Worker  * If $escape-reserved is false, the behavior differs in that characters
12718*7c568831SAndroid Build Coastguard Worker  * referred to in [RFC 2396] as reserved characters are not escaped. These
12719*7c568831SAndroid Build Coastguard Worker  * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",".
12720*7c568831SAndroid Build Coastguard Worker  *
12721*7c568831SAndroid Build Coastguard Worker  * [RFC 2396] does not define whether escaped URIs should use lower case or
12722*7c568831SAndroid Build Coastguard Worker  * upper case for hexadecimal digits. To ensure that escaped URIs can be
12723*7c568831SAndroid Build Coastguard Worker  * compared using string comparison functions, this function must always use
12724*7c568831SAndroid Build Coastguard Worker  * the upper-case letters A-F.
12725*7c568831SAndroid Build Coastguard Worker  *
12726*7c568831SAndroid Build Coastguard Worker  * Generally, $escape-reserved should be set to true when escaping a string
12727*7c568831SAndroid Build Coastguard Worker  * that is to form a single part of a URI, and to false when escaping an
12728*7c568831SAndroid Build Coastguard Worker  * entire URI or URI reference.
12729*7c568831SAndroid Build Coastguard Worker  *
12730*7c568831SAndroid Build Coastguard Worker  * In the case of non-ascii characters, the string is encoded according to
12731*7c568831SAndroid Build Coastguard Worker  * utf-8 and then converted according to RFC 2396.
12732*7c568831SAndroid Build Coastguard Worker  *
12733*7c568831SAndroid Build Coastguard Worker  * Examples
12734*7c568831SAndroid Build Coastguard Worker  *  xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), true())
12735*7c568831SAndroid Build Coastguard Worker  *  returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%2FLos%20Angeles%23ocean"
12736*7c568831SAndroid Build Coastguard Worker  *  xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), false())
12737*7c568831SAndroid Build Coastguard Worker  *  returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles%23ocean"
12738*7c568831SAndroid Build Coastguard Worker  *
12739*7c568831SAndroid Build Coastguard Worker  */
12740*7c568831SAndroid Build Coastguard Worker static void
xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt,int nargs)12741*7c568831SAndroid Build Coastguard Worker xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
12742*7c568831SAndroid Build Coastguard Worker     xmlXPathObjectPtr str;
12743*7c568831SAndroid Build Coastguard Worker     int escape_reserved;
12744*7c568831SAndroid Build Coastguard Worker     xmlBufPtr target;
12745*7c568831SAndroid Build Coastguard Worker     xmlChar *cptr;
12746*7c568831SAndroid Build Coastguard Worker     xmlChar escape[4];
12747*7c568831SAndroid Build Coastguard Worker 
12748*7c568831SAndroid Build Coastguard Worker     CHECK_ARITY(2);
12749*7c568831SAndroid Build Coastguard Worker 
12750*7c568831SAndroid Build Coastguard Worker     escape_reserved = xmlXPathPopBoolean(ctxt);
12751*7c568831SAndroid Build Coastguard Worker 
12752*7c568831SAndroid Build Coastguard Worker     CAST_TO_STRING;
12753*7c568831SAndroid Build Coastguard Worker     str = valuePop(ctxt);
12754*7c568831SAndroid Build Coastguard Worker 
12755*7c568831SAndroid Build Coastguard Worker     target = xmlBufCreate(50);
12756*7c568831SAndroid Build Coastguard Worker 
12757*7c568831SAndroid Build Coastguard Worker     escape[0] = '%';
12758*7c568831SAndroid Build Coastguard Worker     escape[3] = 0;
12759*7c568831SAndroid Build Coastguard Worker 
12760*7c568831SAndroid Build Coastguard Worker     if (target) {
12761*7c568831SAndroid Build Coastguard Worker 	for (cptr = str->stringval; *cptr; cptr++) {
12762*7c568831SAndroid Build Coastguard Worker 	    if ((*cptr >= 'A' && *cptr <= 'Z') ||
12763*7c568831SAndroid Build Coastguard Worker 		(*cptr >= 'a' && *cptr <= 'z') ||
12764*7c568831SAndroid Build Coastguard Worker 		(*cptr >= '0' && *cptr <= '9') ||
12765*7c568831SAndroid Build Coastguard Worker 		*cptr == '-' || *cptr == '_' || *cptr == '.' ||
12766*7c568831SAndroid Build Coastguard Worker 		*cptr == '!' || *cptr == '~' || *cptr == '*' ||
12767*7c568831SAndroid Build Coastguard Worker 		*cptr == '\''|| *cptr == '(' || *cptr == ')' ||
12768*7c568831SAndroid Build Coastguard Worker 		(*cptr == '%' &&
12769*7c568831SAndroid Build Coastguard Worker 		 ((cptr[1] >= 'A' && cptr[1] <= 'F') ||
12770*7c568831SAndroid Build Coastguard Worker 		  (cptr[1] >= 'a' && cptr[1] <= 'f') ||
12771*7c568831SAndroid Build Coastguard Worker 		  (cptr[1] >= '0' && cptr[1] <= '9')) &&
12772*7c568831SAndroid Build Coastguard Worker 		 ((cptr[2] >= 'A' && cptr[2] <= 'F') ||
12773*7c568831SAndroid Build Coastguard Worker 		  (cptr[2] >= 'a' && cptr[2] <= 'f') ||
12774*7c568831SAndroid Build Coastguard Worker 		  (cptr[2] >= '0' && cptr[2] <= '9'))) ||
12775*7c568831SAndroid Build Coastguard Worker 		(!escape_reserved &&
12776*7c568831SAndroid Build Coastguard Worker 		 (*cptr == ';' || *cptr == '/' || *cptr == '?' ||
12777*7c568831SAndroid Build Coastguard Worker 		  *cptr == ':' || *cptr == '@' || *cptr == '&' ||
12778*7c568831SAndroid Build Coastguard Worker 		  *cptr == '=' || *cptr == '+' || *cptr == '$' ||
12779*7c568831SAndroid Build Coastguard Worker 		  *cptr == ','))) {
12780*7c568831SAndroid Build Coastguard Worker 		xmlBufAdd(target, cptr, 1);
12781*7c568831SAndroid Build Coastguard Worker 	    } else {
12782*7c568831SAndroid Build Coastguard Worker 		if ((*cptr >> 4) < 10)
12783*7c568831SAndroid Build Coastguard Worker 		    escape[1] = '0' + (*cptr >> 4);
12784*7c568831SAndroid Build Coastguard Worker 		else
12785*7c568831SAndroid Build Coastguard Worker 		    escape[1] = 'A' - 10 + (*cptr >> 4);
12786*7c568831SAndroid Build Coastguard Worker 		if ((*cptr & 0xF) < 10)
12787*7c568831SAndroid Build Coastguard Worker 		    escape[2] = '0' + (*cptr & 0xF);
12788*7c568831SAndroid Build Coastguard Worker 		else
12789*7c568831SAndroid Build Coastguard Worker 		    escape[2] = 'A' - 10 + (*cptr & 0xF);
12790*7c568831SAndroid Build Coastguard Worker 
12791*7c568831SAndroid Build Coastguard Worker 		xmlBufAdd(target, &escape[0], 3);
12792*7c568831SAndroid Build Coastguard Worker 	    }
12793*7c568831SAndroid Build Coastguard Worker 	}
12794*7c568831SAndroid Build Coastguard Worker     }
12795*7c568831SAndroid Build Coastguard Worker     valuePush(ctxt, xmlXPathCacheNewString(ctxt, xmlBufContent(target)));
12796*7c568831SAndroid Build Coastguard Worker     xmlBufFree(target);
12797*7c568831SAndroid Build Coastguard Worker     xmlXPathReleaseObject(ctxt->context, str);
12798*7c568831SAndroid Build Coastguard Worker }
12799*7c568831SAndroid Build Coastguard Worker 
12800*7c568831SAndroid Build Coastguard Worker /**
12801*7c568831SAndroid Build Coastguard Worker  * xmlXPathRegisterAllFunctions:
12802*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the XPath context
12803*7c568831SAndroid Build Coastguard Worker  *
12804*7c568831SAndroid Build Coastguard Worker  * Registers all default XPath functions in this context
12805*7c568831SAndroid Build Coastguard Worker  */
12806*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)12807*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
12808*7c568831SAndroid Build Coastguard Worker {
12809*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
12810*7c568831SAndroid Build Coastguard Worker                          xmlXPathBooleanFunction);
12811*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
12812*7c568831SAndroid Build Coastguard Worker                          xmlXPathCeilingFunction);
12813*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
12814*7c568831SAndroid Build Coastguard Worker                          xmlXPathCountFunction);
12815*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
12816*7c568831SAndroid Build Coastguard Worker                          xmlXPathConcatFunction);
12817*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
12818*7c568831SAndroid Build Coastguard Worker                          xmlXPathContainsFunction);
12819*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
12820*7c568831SAndroid Build Coastguard Worker                          xmlXPathIdFunction);
12821*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
12822*7c568831SAndroid Build Coastguard Worker                          xmlXPathFalseFunction);
12823*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
12824*7c568831SAndroid Build Coastguard Worker                          xmlXPathFloorFunction);
12825*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
12826*7c568831SAndroid Build Coastguard Worker                          xmlXPathLastFunction);
12827*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
12828*7c568831SAndroid Build Coastguard Worker                          xmlXPathLangFunction);
12829*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
12830*7c568831SAndroid Build Coastguard Worker                          xmlXPathLocalNameFunction);
12831*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
12832*7c568831SAndroid Build Coastguard Worker                          xmlXPathNotFunction);
12833*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
12834*7c568831SAndroid Build Coastguard Worker                          xmlXPathNameFunction);
12835*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
12836*7c568831SAndroid Build Coastguard Worker                          xmlXPathNamespaceURIFunction);
12837*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
12838*7c568831SAndroid Build Coastguard Worker                          xmlXPathNormalizeFunction);
12839*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
12840*7c568831SAndroid Build Coastguard Worker                          xmlXPathNumberFunction);
12841*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
12842*7c568831SAndroid Build Coastguard Worker                          xmlXPathPositionFunction);
12843*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
12844*7c568831SAndroid Build Coastguard Worker                          xmlXPathRoundFunction);
12845*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
12846*7c568831SAndroid Build Coastguard Worker                          xmlXPathStringFunction);
12847*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
12848*7c568831SAndroid Build Coastguard Worker                          xmlXPathStringLengthFunction);
12849*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
12850*7c568831SAndroid Build Coastguard Worker                          xmlXPathStartsWithFunction);
12851*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
12852*7c568831SAndroid Build Coastguard Worker                          xmlXPathSubstringFunction);
12853*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
12854*7c568831SAndroid Build Coastguard Worker                          xmlXPathSubstringBeforeFunction);
12855*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
12856*7c568831SAndroid Build Coastguard Worker                          xmlXPathSubstringAfterFunction);
12857*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
12858*7c568831SAndroid Build Coastguard Worker                          xmlXPathSumFunction);
12859*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
12860*7c568831SAndroid Build Coastguard Worker                          xmlXPathTrueFunction);
12861*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
12862*7c568831SAndroid Build Coastguard Worker                          xmlXPathTranslateFunction);
12863*7c568831SAndroid Build Coastguard Worker 
12864*7c568831SAndroid Build Coastguard Worker     xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
12865*7c568831SAndroid Build Coastguard Worker 	 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
12866*7c568831SAndroid Build Coastguard Worker                          xmlXPathEscapeUriFunction);
12867*7c568831SAndroid Build Coastguard Worker }
12868*7c568831SAndroid Build Coastguard Worker 
12869*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_XPATH_ENABLED */
12870