Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1179)

Side by Side Diff: third_party/libxml/src/xpath.c

Issue 1193533007: Upgrade to libxml 2.9.2 and libxslt 1.1.28 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: no iconv Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/libxml/src/xmlwriter.c ('k') | third_party/libxml/src/xpointer.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * xpath.c: XML Path Language implementation 2 * xpath.c: XML Path Language implementation
3 * XPath is a language for addressing parts of an XML document, 3 * XPath is a language for addressing parts of an XML document,
4 * designed to be used by both XSLT and XPointer 4 * designed to be used by both XSLT and XPointer
5 *f 5 *f
6 * Reference: W3C Recommendation 16 November 1999 6 * Reference: W3C Recommendation 16 November 1999
7 * http://www.w3.org/TR/1999/REC-xpath-19991116 7 * http://www.w3.org/TR/1999/REC-xpath-19991116
8 * Public reference: 8 * Public reference:
9 * http://www.w3.org/TR/xpath 9 * http://www.w3.org/TR/xpath
10 * 10 *
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 #ifdef LIBXML_DEBUG_ENABLED 48 #ifdef LIBXML_DEBUG_ENABLED
49 #include <libxml/debugXML.h> 49 #include <libxml/debugXML.h>
50 #endif 50 #endif
51 #include <libxml/xmlerror.h> 51 #include <libxml/xmlerror.h>
52 #include <libxml/threads.h> 52 #include <libxml/threads.h>
53 #include <libxml/globals.h> 53 #include <libxml/globals.h>
54 #ifdef LIBXML_PATTERN_ENABLED 54 #ifdef LIBXML_PATTERN_ENABLED
55 #include <libxml/pattern.h> 55 #include <libxml/pattern.h>
56 #endif 56 #endif
57 57
58 #include "buf.h"
59
58 #ifdef LIBXML_PATTERN_ENABLED 60 #ifdef LIBXML_PATTERN_ENABLED
59 #define XPATH_STREAMING 61 #define XPATH_STREAMING
60 #endif 62 #endif
61 63
62 #define TODO \ 64 #define TODO \
63 xmlGenericError(xmlGenericErrorContext, \ 65 xmlGenericError(xmlGenericErrorContext, \
64 "Unimplemented block at %s:%d\n", \ 66 "Unimplemented block at %s:%d\n", \
65 __FILE__, __LINE__); 67 __FILE__, __LINE__);
66 68
69 /**
70 * WITH_TIM_SORT:
71 *
72 * Use the Timsort algorithm provided in timsort.h to sort
73 * nodeset as this is a great improvement over the old Shell sort
74 * used in xmlXPathNodeSetSort()
75 */
76 #define WITH_TIM_SORT
77
67 /* 78 /*
68 * XP_OPTIMIZED_NON_ELEM_COMPARISON: 79 * XP_OPTIMIZED_NON_ELEM_COMPARISON:
69 * If defined, this will use xmlXPathCmpNodesExt() instead of 80 * If defined, this will use xmlXPathCmpNodesExt() instead of
70 * xmlXPathCmpNodes(). The new function is optimized comparison of 81 * xmlXPathCmpNodes(). The new function is optimized comparison of
71 * non-element nodes; actually it will speed up comparison only if 82 * non-element nodes; actually it will speed up comparison only if
72 * xmlXPathOrderDocElems() was called in order to index the elements of 83 * xmlXPathOrderDocElems() was called in order to index the elements of
73 * a tree in document order; Libxslt does such an indexing, thus it will 84 * a tree in document order; Libxslt does such an indexing, thus it will
74 * benefit from this optimization. 85 * benefit from this optimization.
75 */ 86 */
76 #define XP_OPTIMIZED_NON_ELEM_COMPARISON 87 #define XP_OPTIMIZED_NON_ELEM_COMPARISON
77 88
78 /* 89 /*
79 * XP_OPTIMIZED_FILTER_FIRST: 90 * XP_OPTIMIZED_FILTER_FIRST:
80 * If defined, this will optimize expressions like "key('foo', 'val')[b][1]" 91 * If defined, this will optimize expressions like "key('foo', 'val')[b][1]"
81 * in a way, that it stop evaluation at the first node. 92 * in a way, that it stop evaluation at the first node.
82 */ 93 */
83 #define XP_OPTIMIZED_FILTER_FIRST 94 #define XP_OPTIMIZED_FILTER_FIRST
84 95
85 /* 96 /*
86 * XP_DEBUG_OBJ_USAGE: 97 * XP_DEBUG_OBJ_USAGE:
87 * Internal flag to enable tracking of how much XPath objects have been 98 * Internal flag to enable tracking of how much XPath objects have been
88 * created. 99 * created.
89 */ 100 */
90 /* #define XP_DEBUG_OBJ_USAGE */ 101 /* #define XP_DEBUG_OBJ_USAGE */
91 102
92 /* 103 /*
104 * XPATH_MAX_STEPS:
105 * when compiling an XPath expression we arbitrary limit the maximum
106 * number of step operation in the compiled expression. 1000000 is
107 * an insanely large value which should never be reached under normal
108 * circumstances
109 */
110 #define XPATH_MAX_STEPS 1000000
111
112 /*
113 * XPATH_MAX_STACK_DEPTH:
114 * when evaluating an XPath expression we arbitrary limit the maximum
115 * number of object allowed to be pushed on the stack. 1000000 is
116 * an insanely large value which should never be reached under normal
117 * circumstances
118 */
119 #define XPATH_MAX_STACK_DEPTH 1000000
120
121 /*
122 * XPATH_MAX_NODESET_LENGTH:
123 * when evaluating an XPath expression nodesets are created and we
124 * arbitrary limit the maximum length of those node set. 10000000 is
125 * an insanely large value which should never be reached under normal
126 * circumstances, one would first need to construct an in memory tree
127 * with more than 10 millions nodes.
128 */
129 #define XPATH_MAX_NODESET_LENGTH 10000000
130
131 /*
93 * TODO: 132 * TODO:
94 * There are a few spots where some tests are done which depend upon ascii 133 * There are a few spots where some tests are done which depend upon ascii
95 * data. These should be enhanced for full UTF8 support (see particularly 134 * data. These should be enhanced for full UTF8 support (see particularly
96 * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT) 135 * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
97 */ 136 */
98 137
138 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
139 /**
140 * xmlXPathCmpNodesExt:
141 * @node1: the first node
142 * @node2: the second node
143 *
144 * Compare two nodes w.r.t document order.
145 * This one is optimized for handling of non-element nodes.
146 *
147 * Returns -2 in case of error 1 if first point < second point, 0 if
148 * it's the same node, -1 otherwise
149 */
150 static int
151 xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
152 int depth1, depth2;
153 int misc = 0, precedence1 = 0, precedence2 = 0;
154 xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
155 xmlNodePtr cur, root;
156 long l1, l2;
157
158 if ((node1 == NULL) || (node2 == NULL))
159 return(-2);
160
161 if (node1 == node2)
162 return(0);
163
164 /*
165 * a couple of optimizations which will avoid computations in most cases
166 */
167 switch (node1->type) {
168 case XML_ELEMENT_NODE:
169 if (node2->type == XML_ELEMENT_NODE) {
170 if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice here? */
171 (0 > (long) node2->content) &&
172 (node1->doc == node2->doc))
173 {
174 l1 = -((long) node1->content);
175 l2 = -((long) node2->content);
176 if (l1 < l2)
177 return(1);
178 if (l1 > l2)
179 return(-1);
180 } else
181 goto turtle_comparison;
182 }
183 break;
184 case XML_ATTRIBUTE_NODE:
185 precedence1 = 1; /* element is owner */
186 miscNode1 = node1;
187 node1 = node1->parent;
188 misc = 1;
189 break;
190 case XML_TEXT_NODE:
191 case XML_CDATA_SECTION_NODE:
192 case XML_COMMENT_NODE:
193 case XML_PI_NODE: {
194 miscNode1 = node1;
195 /*
196 * Find nearest element node.
197 */
198 if (node1->prev != NULL) {
199 do {
200 node1 = node1->prev;
201 if (node1->type == XML_ELEMENT_NODE) {
202 precedence1 = 3; /* element in prev-sibl axis */
203 break;
204 }
205 if (node1->prev == NULL) {
206 precedence1 = 2; /* element is parent */
207 /*
208 * URGENT TODO: Are there any cases, where the
209 * parent of such a node is not an element node?
210 */
211 node1 = node1->parent;
212 break;
213 }
214 } while (1);
215 } else {
216 precedence1 = 2; /* element is parent */
217 node1 = node1->parent;
218 }
219 if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
220 (0 <= (long) node1->content)) {
221 /*
222 * Fallback for whatever case.
223 */
224 node1 = miscNode1;
225 precedence1 = 0;
226 } else
227 misc = 1;
228 }
229 break;
230 case XML_NAMESPACE_DECL:
231 /*
232 * TODO: why do we return 1 for namespace nodes?
233 */
234 return(1);
235 default:
236 break;
237 }
238 switch (node2->type) {
239 case XML_ELEMENT_NODE:
240 break;
241 case XML_ATTRIBUTE_NODE:
242 precedence2 = 1; /* element is owner */
243 miscNode2 = node2;
244 node2 = node2->parent;
245 misc = 1;
246 break;
247 case XML_TEXT_NODE:
248 case XML_CDATA_SECTION_NODE:
249 case XML_COMMENT_NODE:
250 case XML_PI_NODE: {
251 miscNode2 = node2;
252 if (node2->prev != NULL) {
253 do {
254 node2 = node2->prev;
255 if (node2->type == XML_ELEMENT_NODE) {
256 precedence2 = 3; /* element in prev-sibl axis */
257 break;
258 }
259 if (node2->prev == NULL) {
260 precedence2 = 2; /* element is parent */
261 node2 = node2->parent;
262 break;
263 }
264 } while (1);
265 } else {
266 precedence2 = 2; /* element is parent */
267 node2 = node2->parent;
268 }
269 if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
270 (0 <= (long) node2->content))
271 {
272 node2 = miscNode2;
273 precedence2 = 0;
274 } else
275 misc = 1;
276 }
277 break;
278 case XML_NAMESPACE_DECL:
279 return(1);
280 default:
281 break;
282 }
283 if (misc) {
284 if (node1 == node2) {
285 if (precedence1 == precedence2) {
286 /*
287 * The ugly case; but normally there aren't many
288 * adjacent non-element nodes around.
289 */
290 cur = miscNode2->prev;
291 while (cur != NULL) {
292 if (cur == miscNode1)
293 return(1);
294 if (cur->type == XML_ELEMENT_NODE)
295 return(-1);
296 cur = cur->prev;
297 }
298 return (-1);
299 } else {
300 /*
301 * Evaluate based on higher precedence wrt to the element.
302 * TODO: This assumes attributes are sorted before content.
303 * Is this 100% correct?
304 */
305 if (precedence1 < precedence2)
306 return(1);
307 else
308 return(-1);
309 }
310 }
311 /*
312 * Special case: One of the helper-elements is contained by the other.
313 * <foo>
314 * <node2>
315 * <node1>Text-1(precedence1 == 2)</node1>
316 * </node2>
317 * Text-6(precedence2 == 3)
318 * </foo>
319 */
320 if ((precedence2 == 3) && (precedence1 > 1)) {
321 cur = node1->parent;
322 while (cur) {
323 if (cur == node2)
324 return(1);
325 cur = cur->parent;
326 }
327 }
328 if ((precedence1 == 3) && (precedence2 > 1)) {
329 cur = node2->parent;
330 while (cur) {
331 if (cur == node1)
332 return(-1);
333 cur = cur->parent;
334 }
335 }
336 }
337
338 /*
339 * Speedup using document order if availble.
340 */
341 if ((node1->type == XML_ELEMENT_NODE) &&
342 (node2->type == XML_ELEMENT_NODE) &&
343 (0 > (long) node1->content) &&
344 (0 > (long) node2->content) &&
345 (node1->doc == node2->doc)) {
346
347 l1 = -((long) node1->content);
348 l2 = -((long) node2->content);
349 if (l1 < l2)
350 return(1);
351 if (l1 > l2)
352 return(-1);
353 }
354
355 turtle_comparison:
356
357 if (node1 == node2->prev)
358 return(1);
359 if (node1 == node2->next)
360 return(-1);
361 /*
362 * compute depth to root
363 */
364 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
365 if (cur == node1)
366 return(1);
367 depth2++;
368 }
369 root = cur;
370 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
371 if (cur == node2)
372 return(-1);
373 depth1++;
374 }
375 /*
376 * Distinct document (or distinct entities :-( ) case.
377 */
378 if (root != cur) {
379 return(-2);
380 }
381 /*
382 * get the nearest common ancestor.
383 */
384 while (depth1 > depth2) {
385 depth1--;
386 node1 = node1->parent;
387 }
388 while (depth2 > depth1) {
389 depth2--;
390 node2 = node2->parent;
391 }
392 while (node1->parent != node2->parent) {
393 node1 = node1->parent;
394 node2 = node2->parent;
395 /* should not happen but just in case ... */
396 if ((node1 == NULL) || (node2 == NULL))
397 return(-2);
398 }
399 /*
400 * Find who's first.
401 */
402 if (node1 == node2->prev)
403 return(1);
404 if (node1 == node2->next)
405 return(-1);
406 /*
407 * Speedup using document order if availble.
408 */
409 if ((node1->type == XML_ELEMENT_NODE) &&
410 (node2->type == XML_ELEMENT_NODE) &&
411 (0 > (long) node1->content) &&
412 (0 > (long) node2->content) &&
413 (node1->doc == node2->doc)) {
414
415 l1 = -((long) node1->content);
416 l2 = -((long) node2->content);
417 if (l1 < l2)
418 return(1);
419 if (l1 > l2)
420 return(-1);
421 }
422
423 for (cur = node1->next;cur != NULL;cur = cur->next)
424 if (cur == node2)
425 return(1);
426 return(-1); /* assume there is no sibling list corruption */
427 }
428 #endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */
429
430 /*
431 * Wrapper for the Timsort argorithm from timsort.h
432 */
433 #ifdef WITH_TIM_SORT
434 #define SORT_NAME libxml_domnode
435 #define SORT_TYPE xmlNodePtr
436 /**
437 * wrap_cmp:
438 * @x: a node
439 * @y: another node
440 *
441 * Comparison function for the Timsort implementation
442 *
443 * Returns -2 in case of error -1 if first point < second point, 0 if
444 * it's the same node, +1 otherwise
445 */
446 static
447 int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
448 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
449 static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
450 {
451 int res = xmlXPathCmpNodesExt(x, y);
452 return res == -2 ? res : -res;
453 }
454 #else
455 static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
456 {
457 int res = xmlXPathCmpNodes(x, y);
458 return res == -2 ? res : -res;
459 }
460 #endif
461 #define SORT_CMP(x, y) (wrap_cmp(x, y))
462 #include "timsort.h"
463 #endif /* WITH_TIM_SORT */
464
99 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) 465 #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
100 466
101 /************************************************************************ 467 /************************************************************************
102 * * 468 * *
103 * Floating point stuff * 469 * Floating point stuff *
104 * * 470 * *
105 ************************************************************************/ 471 ************************************************************************/
106 472
107 #ifndef TRIO_REPLACE_STDIO 473 #ifndef TRIO_REPLACE_STDIO
108 #define TRIO_PUBLIC static 474 #define TRIO_PUBLIC static
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 "Invalid context size\n", 611 "Invalid context size\n",
246 "Invalid context position\n", 612 "Invalid context position\n",
247 "Memory allocation error\n", 613 "Memory allocation error\n",
248 "Syntax error\n", 614 "Syntax error\n",
249 "Resource error\n", 615 "Resource error\n",
250 "Sub resource error\n", 616 "Sub resource error\n",
251 "Undefined namespace prefix\n", 617 "Undefined namespace prefix\n",
252 "Encoding error\n", 618 "Encoding error\n",
253 "Char out of XML range\n", 619 "Char out of XML range\n",
254 "Invalid or incomplete context\n", 620 "Invalid or incomplete context\n",
621 "Stack usage error\n",
622 "Forbidden variable\n",
255 "?? Unknown error ??\n" /* Must be last in the list! */ 623 "?? Unknown error ??\n" /* Must be last in the list! */
256 }; 624 };
257 #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \ 625 #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
258 sizeof(xmlXPathErrorMessages[0])) - 1) 626 sizeof(xmlXPathErrorMessages[0])) - 1)
259 /** 627 /**
260 * xmlXPathErrMemory: 628 * xmlXPathErrMemory:
261 * @ctxt: an XPath context 629 * @ctxt: an XPath context
262 * @extra: extra informations 630 * @extra: extra informations
263 * 631 *
264 * Handle a redefinition of attribute error 632 * Handle a redefinition of attribute error
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 * and here, we should make the functions public. 780 * and here, we should make the functions public.
413 */ 781 */
414 static int 782 static int
415 xmlPointerListAddSize(xmlPointerListPtr list, 783 xmlPointerListAddSize(xmlPointerListPtr list,
416 void *item, 784 void *item,
417 int initialSize) 785 int initialSize)
418 { 786 {
419 if (list->items == NULL) { 787 if (list->items == NULL) {
420 if (initialSize <= 0) 788 if (initialSize <= 0)
421 initialSize = 1; 789 initialSize = 1;
422 » list->items = (void **) xmlMalloc( 790 » list->items = (void **) xmlMalloc(initialSize * sizeof(void *));
423 » initialSize * sizeof(void *));
424 if (list->items == NULL) { 791 if (list->items == NULL) {
425 xmlXPathErrMemory(NULL, 792 xmlXPathErrMemory(NULL,
426 "xmlPointerListCreate: allocating item\n"); 793 "xmlPointerListCreate: allocating item\n");
427 return(-1); 794 return(-1);
428 } 795 }
429 list->number = 0; 796 list->number = 0;
430 list->size = initialSize; 797 list->size = initialSize;
431 } else if (list->size <= list->number) { 798 } else if (list->size <= list->number) {
799 if (list->size > 50000000) {
800 xmlXPathErrMemory(NULL,
801 "xmlPointerListAddSize: re-allocating item\n");
802 return(-1);
803 }
432 list->size *= 2; 804 list->size *= 2;
433 list->items = (void **) xmlRealloc(list->items, 805 list->items = (void **) xmlRealloc(list->items,
434 list->size * sizeof(void *)); 806 list->size * sizeof(void *));
435 if (list->items == NULL) { 807 if (list->items == NULL) {
436 xmlXPathErrMemory(NULL, 808 xmlXPathErrMemory(NULL,
437 » » "xmlPointerListCreate: re-allocating item\n"); 809 » » "xmlPointerListAddSize: re-allocating item\n");
438 list->size = 0; 810 list->size = 0;
439 return(-1); 811 return(-1);
440 } 812 }
441 } 813 }
442 list->items[list->number++] = item; 814 list->items[list->number++] = item;
443 return(0); 815 return(0);
444 } 816 }
445 817
446 /** 818 /**
447 * xsltPointerListCreate: 819 * xsltPointerListCreate:
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 NODE_TEST_NAME = 5 917 NODE_TEST_NAME = 5
546 } xmlXPathTestVal; 918 } xmlXPathTestVal;
547 919
548 typedef enum { 920 typedef enum {
549 NODE_TYPE_NODE = 0, 921 NODE_TYPE_NODE = 0,
550 NODE_TYPE_COMMENT = XML_COMMENT_NODE, 922 NODE_TYPE_COMMENT = XML_COMMENT_NODE,
551 NODE_TYPE_TEXT = XML_TEXT_NODE, 923 NODE_TYPE_TEXT = XML_TEXT_NODE,
552 NODE_TYPE_PI = XML_PI_NODE 924 NODE_TYPE_PI = XML_PI_NODE
553 } xmlXPathTypeVal; 925 } xmlXPathTypeVal;
554 926
555 #define XP_REWRITE_DOS_CHILD_ELEM 1
556
557 typedef struct _xmlXPathStepOp xmlXPathStepOp; 927 typedef struct _xmlXPathStepOp xmlXPathStepOp;
558 typedef xmlXPathStepOp *xmlXPathStepOpPtr; 928 typedef xmlXPathStepOp *xmlXPathStepOpPtr;
559 struct _xmlXPathStepOp { 929 struct _xmlXPathStepOp {
560 xmlXPathOp op; /* The identifier of the operation */ 930 xmlXPathOp op; /* The identifier of the operation */
561 int ch1; /* First child */ 931 int ch1; /* First child */
562 int ch2; /* Second child */ 932 int ch2; /* Second child */
563 int value; 933 int value;
564 int value2; 934 int value2;
565 int value3; 935 int value3;
566 void *value4; 936 void *value4;
567 void *value5; 937 void *value5;
568 void *cache; 938 void *cache;
569 void *cacheURI; 939 void *cacheURI;
570 int rewriteType;
571 }; 940 };
572 941
573 struct _xmlXPathCompExpr { 942 struct _xmlXPathCompExpr {
574 int nbStep; /* Number of steps in this expression */ 943 int nbStep; /* Number of steps in this expression */
575 int maxStep; /* Maximum number of steps allocated */ 944 int maxStep; /* Maximum number of steps allocated */
576 xmlXPathStepOp *steps; /* ops for computation of this expression */ 945 xmlXPathStepOp *steps; /* ops for computation of this expression */
577 int last; /* index of last step in expression */ 946 int last; /* index of last step in expression */
578 xmlChar *expr; /* the expression being computed */ 947 xmlChar *expr; /* the expression being computed */
579 xmlDictPtr dict; /* the dictionnary to use if any */ 948 xmlDictPtr dict; /* the dictionnary to use if any */
580 #ifdef DEBUG_EVAL_COUNTS 949 #ifdef DEBUG_EVAL_COUNTS
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 * 1084 *
716 * Returns -1 in case of failure, the index otherwise 1085 * Returns -1 in case of failure, the index otherwise
717 */ 1086 */
718 static int 1087 static int
719 xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2, 1088 xmlXPathCompExprAdd(xmlXPathCompExprPtr comp, int ch1, int ch2,
720 xmlXPathOp op, int value, 1089 xmlXPathOp op, int value,
721 int value2, int value3, void *value4, void *value5) { 1090 int value2, int value3, void *value4, void *value5) {
722 if (comp->nbStep >= comp->maxStep) { 1091 if (comp->nbStep >= comp->maxStep) {
723 xmlXPathStepOp *real; 1092 xmlXPathStepOp *real;
724 1093
1094 if (comp->maxStep >= XPATH_MAX_STEPS) {
1095 xmlXPathErrMemory(NULL, "adding step\n");
1096 return(-1);
1097 }
725 comp->maxStep *= 2; 1098 comp->maxStep *= 2;
726 real = (xmlXPathStepOp *) xmlRealloc(comp->steps, 1099 real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
727 comp->maxStep * sizeof(xmlXPathStepOp)); 1100 comp->maxStep * sizeof(xmlXPathStepOp));
728 if (real == NULL) { 1101 if (real == NULL) {
729 comp->maxStep /= 2; 1102 comp->maxStep /= 2;
730 xmlXPathErrMemory(NULL, "adding step\n"); 1103 xmlXPathErrMemory(NULL, "adding step\n");
731 return(-1); 1104 return(-1);
732 } 1105 }
733 comp->steps = real; 1106 comp->steps = real;
734 } 1107 }
735 comp->last = comp->nbStep; 1108 comp->last = comp->nbStep;
736 comp->steps[comp->nbStep].rewriteType = 0;
737 comp->steps[comp->nbStep].ch1 = ch1; 1109 comp->steps[comp->nbStep].ch1 = ch1;
738 comp->steps[comp->nbStep].ch2 = ch2; 1110 comp->steps[comp->nbStep].ch2 = ch2;
739 comp->steps[comp->nbStep].op = op; 1111 comp->steps[comp->nbStep].op = op;
740 comp->steps[comp->nbStep].value = value; 1112 comp->steps[comp->nbStep].value = value;
741 comp->steps[comp->nbStep].value2 = value2; 1113 comp->steps[comp->nbStep].value2 = value2;
742 comp->steps[comp->nbStep].value3 = value3; 1114 comp->steps[comp->nbStep].value3 = value3;
743 if ((comp->dict != NULL) && 1115 if ((comp->dict != NULL) &&
744 ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) || 1116 ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) ||
745 (op == XPATH_OP_COLLECT))) { 1117 (op == XPATH_OP_COLLECT))) {
746 if (value4 != NULL) { 1118 if (value4 != NULL) {
(...skipping 1297 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 /* 2416 /*
2045 * Fallback to misc-cache. 2417 * Fallback to misc-cache.
2046 */ 2418 */
2047 2419
2048 ret = (xmlXPathObjectPtr) 2420 ret = (xmlXPathObjectPtr)
2049 cache->miscObjs->items[--cache->miscObjs->number]; 2421 cache->miscObjs->items[--cache->miscObjs->number];
2050 2422
2051 ret->type = XPATH_NODESET; 2423 ret->type = XPATH_NODESET;
2052 ret->boolval = 0; 2424 ret->boolval = 0;
2053 ret->nodesetval = xmlXPathNodeSetCreate(val); 2425 ret->nodesetval = xmlXPathNodeSetCreate(val);
2426 if (ret->nodesetval == NULL) {
2427 ctxt->lastError.domain = XML_FROM_XPATH;
2428 ctxt->lastError.code = XML_ERR_NO_MEMORY;
2429 return(NULL);
2430 }
2054 #ifdef XP_DEBUG_OBJ_USAGE 2431 #ifdef XP_DEBUG_OBJ_USAGE
2055 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET); 2432 xmlXPathDebugObjUsageRequested(ctxt, XPATH_NODESET);
2056 #endif 2433 #endif
2057 return(ret); 2434 return(ret);
2058 } 2435 }
2059 } 2436 }
2060 return(xmlXPathNewNodeSet(val)); 2437 return(xmlXPathNewNodeSet(val));
2061 } 2438 }
2062 2439
2063 /** 2440 /**
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
2391 return(ret); 2768 return(ret);
2392 } 2769 }
2393 2770
2394 /************************************************************************ 2771 /************************************************************************
2395 * * 2772 * *
2396 * Parser stacks related functions and macros * 2773 * Parser stacks related functions and macros *
2397 * * 2774 * *
2398 ************************************************************************/ 2775 ************************************************************************/
2399 2776
2400 /** 2777 /**
2778 * xmlXPathSetFrame:
2779 * @ctxt: an XPath parser context
2780 *
2781 * Set the callee evaluation frame
2782 *
2783 * Returns the previous frame value to be restored once done
2784 */
2785 static int
2786 xmlXPathSetFrame(xmlXPathParserContextPtr ctxt) {
2787 int ret;
2788
2789 if (ctxt == NULL)
2790 return(0);
2791 ret = ctxt->valueFrame;
2792 ctxt->valueFrame = ctxt->valueNr;
2793 return(ret);
2794 }
2795
2796 /**
2797 * xmlXPathPopFrame:
2798 * @ctxt: an XPath parser context
2799 * @frame: the previous frame value
2800 *
2801 * Remove the callee evaluation frame
2802 */
2803 static void
2804 xmlXPathPopFrame(xmlXPathParserContextPtr ctxt, int frame) {
2805 if (ctxt == NULL)
2806 return;
2807 if (ctxt->valueNr < ctxt->valueFrame) {
2808 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
2809 }
2810 ctxt->valueFrame = frame;
2811 }
2812
2813 /**
2401 * valuePop: 2814 * valuePop:
2402 * @ctxt: an XPath evaluation context 2815 * @ctxt: an XPath evaluation context
2403 * 2816 *
2404 * Pops the top XPath object from the value stack 2817 * Pops the top XPath object from the value stack
2405 * 2818 *
2406 * Returns the XPath object just removed 2819 * Returns the XPath object just removed
2407 */ 2820 */
2408 xmlXPathObjectPtr 2821 xmlXPathObjectPtr
2409 valuePop(xmlXPathParserContextPtr ctxt) 2822 valuePop(xmlXPathParserContextPtr ctxt)
2410 { 2823 {
2411 xmlXPathObjectPtr ret; 2824 xmlXPathObjectPtr ret;
2412 2825
2413 if ((ctxt == NULL) || (ctxt->valueNr <= 0)) 2826 if ((ctxt == NULL) || (ctxt->valueNr <= 0))
2414 return (NULL); 2827 return (NULL);
2828
2829 if (ctxt->valueNr <= ctxt->valueFrame) {
2830 xmlXPatherror(ctxt, __FILE__, __LINE__, XPATH_STACK_ERROR);
2831 return (NULL);
2832 }
2833
2415 ctxt->valueNr--; 2834 ctxt->valueNr--;
2416 if (ctxt->valueNr > 0) 2835 if (ctxt->valueNr > 0)
2417 ctxt->value = ctxt->valueTab[ctxt->valueNr - 1]; 2836 ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
2418 else 2837 else
2419 ctxt->value = NULL; 2838 ctxt->value = NULL;
2420 ret = ctxt->valueTab[ctxt->valueNr]; 2839 ret = ctxt->valueTab[ctxt->valueNr];
2421 ctxt->valueTab[ctxt->valueNr] = NULL; 2840 ctxt->valueTab[ctxt->valueNr] = NULL;
2422 return (ret); 2841 return (ret);
2423 } 2842 }
2424 /** 2843 /**
2425 * valuePush: 2844 * valuePush:
2426 * @ctxt: an XPath evaluation context 2845 * @ctxt: an XPath evaluation context
2427 * @value: the XPath object 2846 * @value: the XPath object
2428 * 2847 *
2429 * Pushes a new XPath object on top of the value stack 2848 * Pushes a new XPath object on top of the value stack
2430 * 2849 *
2431 * returns the number of items on the value stack 2850 * returns the number of items on the value stack
2432 */ 2851 */
2433 int 2852 int
2434 valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value) 2853 valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
2435 { 2854 {
2436 if ((ctxt == NULL) || (value == NULL)) return(-1); 2855 if ((ctxt == NULL) || (value == NULL)) return(-1);
2437 if (ctxt->valueNr >= ctxt->valueMax) { 2856 if (ctxt->valueNr >= ctxt->valueMax) {
2438 xmlXPathObjectPtr *tmp; 2857 xmlXPathObjectPtr *tmp;
2439 2858
2859 if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
2860 xmlXPathErrMemory(NULL, "XPath stack depth limit reached\n");
2861 ctxt->error = XPATH_MEMORY_ERROR;
2862 return (0);
2863 }
2440 tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab, 2864 tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
2441 2 * ctxt->valueMax * 2865 2 * ctxt->valueMax *
2442 sizeof(ctxt->valueTab[0])); 2866 sizeof(ctxt->valueTab[0]));
2443 if (tmp == NULL) { 2867 if (tmp == NULL) {
2444 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n"); 2868 xmlXPathErrMemory(NULL, "pushing value\n");
2869 ctxt->error = XPATH_MEMORY_ERROR;
2445 return (0); 2870 return (0);
2446 } 2871 }
2447 ctxt->valueMax *= 2; 2872 ctxt->valueMax *= 2;
2448 ctxt->valueTab = tmp; 2873 ctxt->valueTab = tmp;
2449 } 2874 }
2450 ctxt->valueTab[ctxt->valueNr] = value; 2875 ctxt->valueTab[ctxt->valueNr] = value;
2451 ctxt->value = value; 2876 ctxt->value = value;
2452 return (ctxt->valueNr++); 2877 return (ctxt->valueNr++);
2453 } 2878 }
2454 2879
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
2744 fraction_place = DBL_DIG - integer_place - 1; 3169 fraction_place = DBL_DIG - integer_place - 1;
2745 else 3170 else
2746 fraction_place = DBL_DIG - integer_place; 3171 fraction_place = DBL_DIG - integer_place;
2747 } else { 3172 } else {
2748 fraction_place = 1; 3173 fraction_place = 1;
2749 } 3174 }
2750 size = snprintf(work, sizeof(work), "%0.*f", 3175 size = snprintf(work, sizeof(work), "%0.*f",
2751 fraction_place, number); 3176 fraction_place, number);
2752 } 3177 }
2753 3178
3179 /* Remove leading spaces sometimes inserted by snprintf */
3180 while (work[0] == ' ') {
3181 for (ptr = &work[0];(ptr[0] = ptr[1]);ptr++);
3182 size--;
3183 }
3184
2754 /* Remove fractional trailing zeroes */ 3185 /* Remove fractional trailing zeroes */
2755 after_fraction = work + size; 3186 after_fraction = work + size;
2756 ptr = after_fraction; 3187 ptr = after_fraction;
2757 while (*(--ptr) == '0') 3188 while (*(--ptr) == '0')
2758 ; 3189 ;
2759 if (*ptr != '.') 3190 if (*ptr != '.')
2760 ptr++; 3191 ptr++;
2761 while ((*ptr++ = *after_fraction++) != 0); 3192 while ((*ptr++ = *after_fraction++) != 0);
2762 3193
2763 /* Finally copy result back to caller */ 3194 /* Finally copy result back to caller */
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2884 if ((node1->type == XML_NAMESPACE_DECL) || 3315 if ((node1->type == XML_NAMESPACE_DECL) ||
2885 (node2->type == XML_NAMESPACE_DECL)) 3316 (node2->type == XML_NAMESPACE_DECL))
2886 return(1); 3317 return(1);
2887 if (node1 == node2->prev) 3318 if (node1 == node2->prev)
2888 return(1); 3319 return(1);
2889 if (node1 == node2->next) 3320 if (node1 == node2->next)
2890 return(-1); 3321 return(-1);
2891 3322
2892 /* 3323 /*
2893 * Speedup using document order if availble. 3324 * Speedup using document order if availble.
2894 */
2895 if ((node1->type == XML_ELEMENT_NODE) &&
2896 (node2->type == XML_ELEMENT_NODE) &&
2897 (0 > (long) node1->content) &&
2898 (0 > (long) node2->content) &&
2899 (node1->doc == node2->doc)) {
2900 long l1, l2;
2901
2902 l1 = -((long) node1->content);
2903 l2 = -((long) node2->content);
2904 if (l1 < l2)
2905 return(1);
2906 if (l1 > l2)
2907 return(-1);
2908 }
2909
2910 /*
2911 * compute depth to root
2912 */
2913 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
2914 if (cur == node1)
2915 return(1);
2916 depth2++;
2917 }
2918 root = cur;
2919 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
2920 if (cur == node2)
2921 return(-1);
2922 depth1++;
2923 }
2924 /*
2925 * Distinct document (or distinct entities :-( ) case.
2926 */
2927 if (root != cur) {
2928 return(-2);
2929 }
2930 /*
2931 * get the nearest common ancestor.
2932 */
2933 while (depth1 > depth2) {
2934 depth1--;
2935 node1 = node1->parent;
2936 }
2937 while (depth2 > depth1) {
2938 depth2--;
2939 node2 = node2->parent;
2940 }
2941 while (node1->parent != node2->parent) {
2942 node1 = node1->parent;
2943 node2 = node2->parent;
2944 /* should not happen but just in case ... */
2945 if ((node1 == NULL) || (node2 == NULL))
2946 return(-2);
2947 }
2948 /*
2949 * Find who's first.
2950 */
2951 if (node1 == node2->prev)
2952 return(1);
2953 if (node1 == node2->next)
2954 return(-1);
2955 /*
2956 * Speedup using document order if availble.
2957 */
2958 if ((node1->type == XML_ELEMENT_NODE) &&
2959 (node2->type == XML_ELEMENT_NODE) &&
2960 (0 > (long) node1->content) &&
2961 (0 > (long) node2->content) &&
2962 (node1->doc == node2->doc)) {
2963 long l1, l2;
2964
2965 l1 = -((long) node1->content);
2966 l2 = -((long) node2->content);
2967 if (l1 < l2)
2968 return(1);
2969 if (l1 > l2)
2970 return(-1);
2971 }
2972
2973 for (cur = node1->next;cur != NULL;cur = cur->next)
2974 if (cur == node2)
2975 return(1);
2976 return(-1); /* assume there is no sibling list corruption */
2977 }
2978
2979 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
2980 /**
2981 * xmlXPathCmpNodesExt:
2982 * @node1: the first node
2983 * @node2: the second node
2984 *
2985 * Compare two nodes w.r.t document order.
2986 * This one is optimized for handling of non-element nodes.
2987 *
2988 * Returns -2 in case of error 1 if first point < second point, 0 if
2989 * it's the same node, -1 otherwise
2990 */
2991 static int
2992 xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
2993 int depth1, depth2;
2994 int misc = 0, precedence1 = 0, precedence2 = 0;
2995 xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
2996 xmlNodePtr cur, root;
2997 long l1, l2;
2998
2999 if ((node1 == NULL) || (node2 == NULL))
3000 return(-2);
3001
3002 if (node1 == node2)
3003 return(0);
3004
3005 /*
3006 * a couple of optimizations which will avoid computations in most cases
3007 */
3008 switch (node1->type) {
3009 case XML_ELEMENT_NODE:
3010 if (node2->type == XML_ELEMENT_NODE) {
3011 if ((0 > (long) node1->content) && /* TODO: Would a != 0 suffice here? */
3012 (0 > (long) node2->content) &&
3013 (node1->doc == node2->doc))
3014 {
3015 l1 = -((long) node1->content);
3016 l2 = -((long) node2->content);
3017 if (l1 < l2)
3018 return(1);
3019 if (l1 > l2)
3020 return(-1);
3021 } else
3022 goto turtle_comparison;
3023 }
3024 break;
3025 case XML_ATTRIBUTE_NODE:
3026 precedence1 = 1; /* element is owner */
3027 miscNode1 = node1;
3028 node1 = node1->parent;
3029 misc = 1;
3030 break;
3031 case XML_TEXT_NODE:
3032 case XML_CDATA_SECTION_NODE:
3033 case XML_COMMENT_NODE:
3034 case XML_PI_NODE: {
3035 miscNode1 = node1;
3036 /*
3037 * Find nearest element node.
3038 */
3039 if (node1->prev != NULL) {
3040 do {
3041 node1 = node1->prev;
3042 if (node1->type == XML_ELEMENT_NODE) {
3043 precedence1 = 3; /* element in prev-sibl axis */
3044 break;
3045 }
3046 if (node1->prev == NULL) {
3047 precedence1 = 2; /* element is parent */
3048 /*
3049 * URGENT TODO: Are there any cases, where the
3050 * parent of such a node is not an element node?
3051 */
3052 node1 = node1->parent;
3053 break;
3054 }
3055 } while (1);
3056 } else {
3057 precedence1 = 2; /* element is parent */
3058 node1 = node1->parent;
3059 }
3060 if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
3061 (0 <= (long) node1->content)) {
3062 /*
3063 * Fallback for whatever case.
3064 */
3065 node1 = miscNode1;
3066 precedence1 = 0;
3067 } else
3068 misc = 1;
3069 }
3070 break;
3071 case XML_NAMESPACE_DECL:
3072 /*
3073 * TODO: why do we return 1 for namespace nodes?
3074 */
3075 return(1);
3076 default:
3077 break;
3078 }
3079 switch (node2->type) {
3080 case XML_ELEMENT_NODE:
3081 break;
3082 case XML_ATTRIBUTE_NODE:
3083 precedence2 = 1; /* element is owner */
3084 miscNode2 = node2;
3085 node2 = node2->parent;
3086 misc = 1;
3087 break;
3088 case XML_TEXT_NODE:
3089 case XML_CDATA_SECTION_NODE:
3090 case XML_COMMENT_NODE:
3091 case XML_PI_NODE: {
3092 miscNode2 = node2;
3093 if (node2->prev != NULL) {
3094 do {
3095 node2 = node2->prev;
3096 if (node2->type == XML_ELEMENT_NODE) {
3097 precedence2 = 3; /* element in prev-sibl axis */
3098 break;
3099 }
3100 if (node2->prev == NULL) {
3101 precedence2 = 2; /* element is parent */
3102 node2 = node2->parent;
3103 break;
3104 }
3105 } while (1);
3106 } else {
3107 precedence2 = 2; /* element is parent */
3108 node2 = node2->parent;
3109 }
3110 if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
3111 (0 <= (long) node1->content))
3112 {
3113 node2 = miscNode2;
3114 precedence2 = 0;
3115 } else
3116 misc = 1;
3117 }
3118 break;
3119 case XML_NAMESPACE_DECL:
3120 return(1);
3121 default:
3122 break;
3123 }
3124 if (misc) {
3125 if (node1 == node2) {
3126 if (precedence1 == precedence2) {
3127 /*
3128 * The ugly case; but normally there aren't many
3129 * adjacent non-element nodes around.
3130 */
3131 cur = miscNode2->prev;
3132 while (cur != NULL) {
3133 if (cur == miscNode1)
3134 return(1);
3135 if (cur->type == XML_ELEMENT_NODE)
3136 return(-1);
3137 cur = cur->prev;
3138 }
3139 return (-1);
3140 } else {
3141 /*
3142 * Evaluate based on higher precedence wrt to the element.
3143 * TODO: This assumes attributes are sorted before content.
3144 * Is this 100% correct?
3145 */
3146 if (precedence1 < precedence2)
3147 return(1);
3148 else
3149 return(-1);
3150 }
3151 }
3152 /*
3153 * Special case: One of the helper-elements is contained by the other.
3154 * <foo>
3155 * <node2>
3156 * <node1>Text-1(precedence1 == 2)</node1>
3157 * </node2>
3158 * Text-6(precedence2 == 3)
3159 * </foo>
3160 */
3161 if ((precedence2 == 3) && (precedence1 > 1)) {
3162 cur = node1->parent;
3163 while (cur) {
3164 if (cur == node2)
3165 return(1);
3166 cur = cur->parent;
3167 }
3168 }
3169 if ((precedence1 == 3) && (precedence2 > 1)) {
3170 cur = node2->parent;
3171 while (cur) {
3172 if (cur == node1)
3173 return(-1);
3174 cur = cur->parent;
3175 }
3176 }
3177 }
3178
3179 /*
3180 * Speedup using document order if availble.
3181 */ 3325 */
3182 if ((node1->type == XML_ELEMENT_NODE) && 3326 if ((node1->type == XML_ELEMENT_NODE) &&
3183 (node2->type == XML_ELEMENT_NODE) && 3327 (node2->type == XML_ELEMENT_NODE) &&
3184 (0 > (long) node1->content) && 3328 (0 > (long) node1->content) &&
3185 (0 > (long) node2->content) && 3329 (0 > (long) node2->content) &&
3186 (node1->doc == node2->doc)) { 3330 (node1->doc == node2->doc)) {
3331 long l1, l2;
3187 3332
3188 l1 = -((long) node1->content); 3333 l1 = -((long) node1->content);
3189 l2 = -((long) node2->content); 3334 l2 = -((long) node2->content);
3190 if (l1 < l2) 3335 if (l1 < l2)
3191 return(1); 3336 return(1);
3192 if (l1 > l2) 3337 if (l1 > l2)
3193 return(-1); 3338 return(-1);
3194 } 3339 }
3195 3340
3196 turtle_comparison:
3197
3198 if (node1 == node2->prev)
3199 return(1);
3200 if (node1 == node2->next)
3201 return(-1);
3202 /* 3341 /*
3203 * compute depth to root 3342 * compute depth to root
3204 */ 3343 */
3205 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) { 3344 for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
3206 if (cur == node1) 3345 if (cur == node1)
3207 return(1); 3346 return(1);
3208 depth2++; 3347 depth2++;
3209 } 3348 }
3210 root = cur; 3349 root = cur;
3211 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) { 3350 for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3245 if (node1 == node2->next) 3384 if (node1 == node2->next)
3246 return(-1); 3385 return(-1);
3247 /* 3386 /*
3248 * Speedup using document order if availble. 3387 * Speedup using document order if availble.
3249 */ 3388 */
3250 if ((node1->type == XML_ELEMENT_NODE) && 3389 if ((node1->type == XML_ELEMENT_NODE) &&
3251 (node2->type == XML_ELEMENT_NODE) && 3390 (node2->type == XML_ELEMENT_NODE) &&
3252 (0 > (long) node1->content) && 3391 (0 > (long) node1->content) &&
3253 (0 > (long) node2->content) && 3392 (0 > (long) node2->content) &&
3254 (node1->doc == node2->doc)) { 3393 (node1->doc == node2->doc)) {
3394 long l1, l2;
3255 3395
3256 l1 = -((long) node1->content); 3396 l1 = -((long) node1->content);
3257 l2 = -((long) node2->content); 3397 l2 = -((long) node2->content);
3258 if (l1 < l2) 3398 if (l1 < l2)
3259 return(1); 3399 return(1);
3260 if (l1 > l2) 3400 if (l1 > l2)
3261 return(-1); 3401 return(-1);
3262 } 3402 }
3263 3403
3264 for (cur = node1->next;cur != NULL;cur = cur->next) 3404 for (cur = node1->next;cur != NULL;cur = cur->next)
3265 if (cur == node2) 3405 if (cur == node2)
3266 return(1); 3406 return(1);
3267 return(-1); /* assume there is no sibling list corruption */ 3407 return(-1); /* assume there is no sibling list corruption */
3268 } 3408 }
3269 #endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */
3270 3409
3271 /** 3410 /**
3272 * xmlXPathNodeSetSort: 3411 * xmlXPathNodeSetSort:
3273 * @set: the node set 3412 * @set: the node set
3274 * 3413 *
3275 * Sort the node set in document order 3414 * Sort the node set in document order
3276 */ 3415 */
3277 void 3416 void
3278 xmlXPathNodeSetSort(xmlNodeSetPtr set) { 3417 xmlXPathNodeSetSort(xmlNodeSetPtr set) {
3418 #ifndef WITH_TIM_SORT
3279 int i, j, incr, len; 3419 int i, j, incr, len;
3280 xmlNodePtr tmp; 3420 xmlNodePtr tmp;
3421 #endif
3281 3422
3282 if (set == NULL) 3423 if (set == NULL)
3283 return; 3424 return;
3284 3425
3285 /* Use Shell's sort to sort the node-set */ 3426 #ifndef WITH_TIM_SORT
3427 /*
3428 * Use the old Shell's sort implementation to sort the node-set
3429 * Timsort ought to be quite faster
3430 */
3286 len = set->nodeNr; 3431 len = set->nodeNr;
3287 for (incr = len / 2; incr > 0; incr /= 2) { 3432 for (incr = len / 2; incr > 0; incr /= 2) {
3288 for (i = incr; i < len; i++) { 3433 for (i = incr; i < len; i++) {
3289 j = i - incr; 3434 j = i - incr;
3290 while (j >= 0) { 3435 while (j >= 0) {
3291 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON 3436 #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
3292 if (xmlXPathCmpNodesExt(set->nodeTab[j], 3437 if (xmlXPathCmpNodesExt(set->nodeTab[j],
3293 set->nodeTab[j + incr]) == -1) 3438 set->nodeTab[j + incr]) == -1)
3294 #else 3439 #else
3295 if (xmlXPathCmpNodes(set->nodeTab[j], 3440 if (xmlXPathCmpNodes(set->nodeTab[j],
3296 set->nodeTab[j + incr]) == -1) 3441 set->nodeTab[j + incr]) == -1)
3297 #endif 3442 #endif
3298 { 3443 {
3299 tmp = set->nodeTab[j]; 3444 tmp = set->nodeTab[j];
3300 set->nodeTab[j] = set->nodeTab[j + incr]; 3445 set->nodeTab[j] = set->nodeTab[j + incr];
3301 set->nodeTab[j + incr] = tmp; 3446 set->nodeTab[j + incr] = tmp;
3302 j -= incr; 3447 j -= incr;
3303 } else 3448 } else
3304 break; 3449 break;
3305 } 3450 }
3306 } 3451 }
3307 } 3452 }
3453 #else /* WITH_TIM_SORT */
3454 libxml_domnode_tim_sort(set->nodeTab, set->nodeNr);
3455 #endif /* WITH_TIM_SORT */
3308 } 3456 }
3309 3457
3310 #define XML_NODESET_DEFAULT 10 3458 #define XML_NODESET_DEFAULT 10
3311 /** 3459 /**
3312 * xmlXPathNodeSetDupNs: 3460 * xmlXPathNodeSetDupNs:
3313 * @node: the parent node of the namespace XPath node 3461 * @node: the parent node of the namespace XPath node
3314 * @ns: the libxml namespace declaration node. 3462 * @ns: the libxml namespace declaration node.
3315 * 3463 *
3316 * Namespace node in libxml don't match the XPath semantic. In a node set 3464 * Namespace node in libxml don't match the XPath semantic. In a node set
3317 * the namespace nodes are duplicated and the next pointer is set to the 3465 * the namespace nodes are duplicated and the next pointer is set to the
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
3476 return(0); 3624 return(0);
3477 } 3625 }
3478 3626
3479 /** 3627 /**
3480 * xmlXPathNodeSetAddNs: 3628 * xmlXPathNodeSetAddNs:
3481 * @cur: the initial node set 3629 * @cur: the initial node set
3482 * @node: the hosting node 3630 * @node: the hosting node
3483 * @ns: a the namespace node 3631 * @ns: a the namespace node
3484 * 3632 *
3485 * add a new namespace node to an existing NodeSet 3633 * add a new namespace node to an existing NodeSet
3634 *
3635 * Returns 0 in case of success and -1 in case of error
3486 */ 3636 */
3487 void 3637 int
3488 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) { 3638 xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
3489 int i; 3639 int i;
3490 3640
3491 3641
3492 if ((cur == NULL) || (ns == NULL) || (node == NULL) || 3642 if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
3493 (ns->type != XML_NAMESPACE_DECL) || 3643 (ns->type != XML_NAMESPACE_DECL) ||
3494 (node->type != XML_ELEMENT_NODE)) 3644 (node->type != XML_ELEMENT_NODE))
3495 » return; 3645 » return(-1);
3496 3646
3497 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ 3647 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3498 /* 3648 /*
3499 * prevent duplicates 3649 * prevent duplicates
3500 */ 3650 */
3501 for (i = 0;i < cur->nodeNr;i++) { 3651 for (i = 0;i < cur->nodeNr;i++) {
3502 if ((cur->nodeTab[i] != NULL) && 3652 if ((cur->nodeTab[i] != NULL) &&
3503 (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) && 3653 (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
3504 (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) && 3654 (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
3505 (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix))) 3655 (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
3506 » return; 3656 » return(0);
3507 } 3657 }
3508 3658
3509 /* 3659 /*
3510 * grow the nodeTab if needed 3660 * grow the nodeTab if needed
3511 */ 3661 */
3512 if (cur->nodeMax == 0) { 3662 if (cur->nodeMax == 0) {
3513 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * 3663 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
3514 sizeof(xmlNodePtr)); 3664 sizeof(xmlNodePtr));
3515 if (cur->nodeTab == NULL) { 3665 if (cur->nodeTab == NULL) {
3516 xmlXPathErrMemory(NULL, "growing nodeset\n"); 3666 xmlXPathErrMemory(NULL, "growing nodeset\n");
3517 » return; 3667 » return(-1);
3518 } 3668 }
3519 memset(cur->nodeTab, 0 , 3669 memset(cur->nodeTab, 0 ,
3520 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); 3670 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
3521 cur->nodeMax = XML_NODESET_DEFAULT; 3671 cur->nodeMax = XML_NODESET_DEFAULT;
3522 } else if (cur->nodeNr == cur->nodeMax) { 3672 } else if (cur->nodeNr == cur->nodeMax) {
3523 xmlNodePtr *temp; 3673 xmlNodePtr *temp;
3524 3674
3525 cur->nodeMax *= 2; 3675 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
3526 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 3676 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
3677 return(-1);
3678 }
3679 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
3527 sizeof(xmlNodePtr)); 3680 sizeof(xmlNodePtr));
3528 if (temp == NULL) { 3681 if (temp == NULL) {
3529 xmlXPathErrMemory(NULL, "growing nodeset\n"); 3682 xmlXPathErrMemory(NULL, "growing nodeset\n");
3530 » return; 3683 » return(-1);
3531 } 3684 }
3685 cur->nodeMax *= 2;
3532 cur->nodeTab = temp; 3686 cur->nodeTab = temp;
3533 } 3687 }
3534 cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns); 3688 cur->nodeTab[cur->nodeNr++] = xmlXPathNodeSetDupNs(node, ns);
3689 return(0);
3535 } 3690 }
3536 3691
3537 /** 3692 /**
3538 * xmlXPathNodeSetAdd: 3693 * xmlXPathNodeSetAdd:
3539 * @cur: the initial node set 3694 * @cur: the initial node set
3540 * @val: a new xmlNodePtr 3695 * @val: a new xmlNodePtr
3541 * 3696 *
3542 * add a new xmlNodePtr to an existing NodeSet 3697 * add a new xmlNodePtr to an existing NodeSet
3698 *
3699 * Returns 0 in case of success, and -1 in case of error
3543 */ 3700 */
3544 void 3701 int
3545 xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) { 3702 xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
3546 int i; 3703 int i;
3547 3704
3548 if ((cur == NULL) || (val == NULL)) return; 3705 if ((cur == NULL) || (val == NULL)) return(-1);
3549
3550 #if 0
3551 if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
3552 » return;»/* an XSLT fake node */
3553 #endif
3554 3706
3555 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ 3707 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3556 /* 3708 /*
3557 * prevent duplcates 3709 * prevent duplcates
3558 */ 3710 */
3559 for (i = 0;i < cur->nodeNr;i++) 3711 for (i = 0;i < cur->nodeNr;i++)
3560 if (cur->nodeTab[i] == val) return; 3712 if (cur->nodeTab[i] == val) return(0);
3561 3713
3562 /* 3714 /*
3563 * grow the nodeTab if needed 3715 * grow the nodeTab if needed
3564 */ 3716 */
3565 if (cur->nodeMax == 0) { 3717 if (cur->nodeMax == 0) {
3566 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * 3718 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
3567 sizeof(xmlNodePtr)); 3719 sizeof(xmlNodePtr));
3568 if (cur->nodeTab == NULL) { 3720 if (cur->nodeTab == NULL) {
3569 xmlXPathErrMemory(NULL, "growing nodeset\n"); 3721 xmlXPathErrMemory(NULL, "growing nodeset\n");
3570 » return; 3722 » return(-1);
3571 } 3723 }
3572 memset(cur->nodeTab, 0 , 3724 memset(cur->nodeTab, 0 ,
3573 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); 3725 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
3574 cur->nodeMax = XML_NODESET_DEFAULT; 3726 cur->nodeMax = XML_NODESET_DEFAULT;
3575 } else if (cur->nodeNr == cur->nodeMax) { 3727 } else if (cur->nodeNr == cur->nodeMax) {
3576 xmlNodePtr *temp; 3728 xmlNodePtr *temp;
3577 3729
3578 cur->nodeMax *= 2; 3730 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
3579 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 3731 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
3732 return(-1);
3733 }
3734 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
3580 sizeof(xmlNodePtr)); 3735 sizeof(xmlNodePtr));
3581 if (temp == NULL) { 3736 if (temp == NULL) {
3582 xmlXPathErrMemory(NULL, "growing nodeset\n"); 3737 xmlXPathErrMemory(NULL, "growing nodeset\n");
3583 » return; 3738 » return(-1);
3584 } 3739 }
3740 cur->nodeMax *= 2;
3585 cur->nodeTab = temp; 3741 cur->nodeTab = temp;
3586 } 3742 }
3587 if (val->type == XML_NAMESPACE_DECL) { 3743 if (val->type == XML_NAMESPACE_DECL) {
3588 xmlNsPtr ns = (xmlNsPtr) val; 3744 xmlNsPtr ns = (xmlNsPtr) val;
3589 3745
3590 cur->nodeTab[cur->nodeNr++] = 3746 cur->nodeTab[cur->nodeNr++] =
3591 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); 3747 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
3592 } else 3748 } else
3593 cur->nodeTab[cur->nodeNr++] = val; 3749 cur->nodeTab[cur->nodeNr++] = val;
3750 return(0);
3594 } 3751 }
3595 3752
3596 /** 3753 /**
3597 * xmlXPathNodeSetAddUnique: 3754 * xmlXPathNodeSetAddUnique:
3598 * @cur: the initial node set 3755 * @cur: the initial node set
3599 * @val: a new xmlNodePtr 3756 * @val: a new xmlNodePtr
3600 * 3757 *
3601 * add a new xmlNodePtr to an existing NodeSet, optimized version 3758 * add a new xmlNodePtr to an existing NodeSet, optimized version
3602 * when we are sure the node is not already in the set. 3759 * when we are sure the node is not already in the set.
3760 *
3761 * Returns 0 in case of success and -1 in case of failure
3603 */ 3762 */
3604 void 3763 int
3605 xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) { 3764 xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
3606 if ((cur == NULL) || (val == NULL)) return; 3765 if ((cur == NULL) || (val == NULL)) return(-1);
3607
3608 #if 0
3609 if ((val->type == XML_ELEMENT_NODE) && (val->name[0] == ' '))
3610 » return;»/* an XSLT fake node */
3611 #endif
3612 3766
3613 /* @@ with_ns to check whether namespace nodes should be looked at @@ */ 3767 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3614 /* 3768 /*
3615 * grow the nodeTab if needed 3769 * grow the nodeTab if needed
3616 */ 3770 */
3617 if (cur->nodeMax == 0) { 3771 if (cur->nodeMax == 0) {
3618 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT * 3772 cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
3619 sizeof(xmlNodePtr)); 3773 sizeof(xmlNodePtr));
3620 if (cur->nodeTab == NULL) { 3774 if (cur->nodeTab == NULL) {
3621 xmlXPathErrMemory(NULL, "growing nodeset\n"); 3775 xmlXPathErrMemory(NULL, "growing nodeset\n");
3622 » return; 3776 » return(-1);
3623 } 3777 }
3624 memset(cur->nodeTab, 0 , 3778 memset(cur->nodeTab, 0 ,
3625 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); 3779 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
3626 cur->nodeMax = XML_NODESET_DEFAULT; 3780 cur->nodeMax = XML_NODESET_DEFAULT;
3627 } else if (cur->nodeNr == cur->nodeMax) { 3781 } else if (cur->nodeNr == cur->nodeMax) {
3628 xmlNodePtr *temp; 3782 xmlNodePtr *temp;
3629 3783
3630 cur->nodeMax *= 2; 3784 if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
3631 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 3785 xmlXPathErrMemory(NULL, "growing nodeset hit limit\n");
3786 return(-1);
3787 }
3788 » temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
3632 sizeof(xmlNodePtr)); 3789 sizeof(xmlNodePtr));
3633 if (temp == NULL) { 3790 if (temp == NULL) {
3634 xmlXPathErrMemory(NULL, "growing nodeset\n"); 3791 xmlXPathErrMemory(NULL, "growing nodeset\n");
3635 » return; 3792 » return(-1);
3636 } 3793 }
3637 cur->nodeTab = temp; 3794 cur->nodeTab = temp;
3795 cur->nodeMax *= 2;
3638 } 3796 }
3639 if (val->type == XML_NAMESPACE_DECL) { 3797 if (val->type == XML_NAMESPACE_DECL) {
3640 xmlNsPtr ns = (xmlNsPtr) val; 3798 xmlNsPtr ns = (xmlNsPtr) val;
3641 3799
3642 cur->nodeTab[cur->nodeNr++] = 3800 cur->nodeTab[cur->nodeNr++] =
3643 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); 3801 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
3644 } else 3802 } else
3645 cur->nodeTab[cur->nodeNr++] = val; 3803 cur->nodeTab[cur->nodeNr++] = val;
3804 return(0);
3646 } 3805 }
3647 3806
3648 /** 3807 /**
3649 * xmlXPathNodeSetMerge: 3808 * xmlXPathNodeSetMerge:
3650 * @val1: the first NodeSet or NULL 3809 * @val1: the first NodeSet or NULL
3651 * @val2: the second NodeSet 3810 * @val2: the second NodeSet
3652 * 3811 *
3653 * Merges two nodesets, all nodes from @val2 are added to @val1 3812 * Merges two nodesets, all nodes from @val2 are added to @val1
3654 * if @val1 is NULL, a new set is created and copied from @val2 3813 * if @val1 is NULL, a new set is created and copied from @val2
3655 * 3814 *
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
3731 if (val1->nodeTab == NULL) { 3890 if (val1->nodeTab == NULL) {
3732 xmlXPathErrMemory(NULL, "merging nodeset\n"); 3891 xmlXPathErrMemory(NULL, "merging nodeset\n");
3733 return(NULL); 3892 return(NULL);
3734 } 3893 }
3735 memset(val1->nodeTab, 0 , 3894 memset(val1->nodeTab, 0 ,
3736 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); 3895 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
3737 val1->nodeMax = XML_NODESET_DEFAULT; 3896 val1->nodeMax = XML_NODESET_DEFAULT;
3738 } else if (val1->nodeNr == val1->nodeMax) { 3897 } else if (val1->nodeNr == val1->nodeMax) {
3739 xmlNodePtr *temp; 3898 xmlNodePtr *temp;
3740 3899
3741 » val1->nodeMax *= 2; 3900 if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
3742 » temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 3901 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
3902 return(NULL);
3903 }
3904 » temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
3743 sizeof(xmlNodePtr)); 3905 sizeof(xmlNodePtr));
3744 if (temp == NULL) { 3906 if (temp == NULL) {
3745 xmlXPathErrMemory(NULL, "merging nodeset\n"); 3907 xmlXPathErrMemory(NULL, "merging nodeset\n");
3746 return(NULL); 3908 return(NULL);
3747 } 3909 }
3748 val1->nodeTab = temp; 3910 val1->nodeTab = temp;
3911 val1->nodeMax *= 2;
3749 } 3912 }
3750 if (n2->type == XML_NAMESPACE_DECL) { 3913 if (n2->type == XML_NAMESPACE_DECL) {
3751 xmlNsPtr ns = (xmlNsPtr) n2; 3914 xmlNsPtr ns = (xmlNsPtr) n2;
3752 3915
3753 val1->nodeTab[val1->nodeNr++] = 3916 val1->nodeTab[val1->nodeNr++] =
3754 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); 3917 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
3755 } else 3918 } else
3756 val1->nodeTab[val1->nodeNr++] = n2; 3919 val1->nodeTab[val1->nodeNr++] = n2;
3757 } 3920 }
3758 3921
3759 return(val1); 3922 return(val1);
3760 } 3923 }
3761 3924
3762 #if 0 /* xmlXPathNodeSetMergeUnique() is currently not used anymore */
3763 /**
3764 * xmlXPathNodeSetMergeUnique:
3765 * @val1: the first NodeSet or NULL
3766 * @val2: the second NodeSet
3767 *
3768 * Merges two nodesets, all nodes from @val2 are added to @val1
3769 * if @val1 is NULL, a new set is created and copied from @val2
3770 *
3771 * Returns @val1 once extended or NULL in case of error.
3772 */
3773 static xmlNodeSetPtr
3774 xmlXPathNodeSetMergeUnique(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
3775 int i;
3776
3777 if (val2 == NULL) return(val1);
3778 if (val1 == NULL) {
3779 val1 = xmlXPathNodeSetCreate(NULL);
3780 }
3781 if (val1 == NULL)
3782 return (NULL);
3783
3784 /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3785
3786 for (i = 0;i < val2->nodeNr;i++) {
3787 /*
3788 * grow the nodeTab if needed
3789 */
3790 if (val1->nodeMax == 0) {
3791 val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
3792 sizeof(xmlNodePtr));
3793 if (val1->nodeTab == NULL) {
3794 xmlXPathErrMemory(NULL, "merging nodeset\n");
3795 return(NULL);
3796 }
3797 memset(val1->nodeTab, 0 ,
3798 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
3799 val1->nodeMax = XML_NODESET_DEFAULT;
3800 } else if (val1->nodeNr == val1->nodeMax) {
3801 xmlNodePtr *temp;
3802
3803 val1->nodeMax *= 2;
3804 temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax *
3805 sizeof(xmlNodePtr));
3806 if (temp == NULL) {
3807 xmlXPathErrMemory(NULL, "merging nodeset\n");
3808 return(NULL);
3809 }
3810 val1->nodeTab = temp;
3811 }
3812 if (val2->nodeTab[i]->type == XML_NAMESPACE_DECL) {
3813 xmlNsPtr ns = (xmlNsPtr) val2->nodeTab[i];
3814
3815 val1->nodeTab[val1->nodeNr++] =
3816 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
3817 } else
3818 val1->nodeTab[val1->nodeNr++] = val2->nodeTab[i];
3819 }
3820
3821 return(val1);
3822 }
3823 #endif /* xmlXPathNodeSetMergeUnique() is currently not used anymore */
3824 3925
3825 /** 3926 /**
3826 * xmlXPathNodeSetMergeAndClear: 3927 * xmlXPathNodeSetMergeAndClear:
3827 * @set1: the first NodeSet or NULL 3928 * @set1: the first NodeSet or NULL
3828 * @set2: the second NodeSet 3929 * @set2: the second NodeSet
3829 * @hasSet2NsNodes: 1 if set2 contains namespaces nodes 3930 * @hasSet2NsNodes: 1 if set2 contains namespaces nodes
3830 * 3931 *
3831 * Merges two nodesets, all nodes from @set2 are added to @set1 3932 * Merges two nodesets, all nodes from @set2 are added to @set1
3832 * if @set1 is NULL, a new set is created and copied from @set2. 3933 * if @set1 is NULL, a new set is created and copied from @set2.
3833 * Checks for duplicate nodes. Clears set2. 3934 * Checks for duplicate nodes. Clears set2.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
3900 if (set1->nodeTab == NULL) { 4001 if (set1->nodeTab == NULL) {
3901 xmlXPathErrMemory(NULL, "merging nodeset\n"); 4002 xmlXPathErrMemory(NULL, "merging nodeset\n");
3902 return(NULL); 4003 return(NULL);
3903 } 4004 }
3904 memset(set1->nodeTab, 0, 4005 memset(set1->nodeTab, 0,
3905 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); 4006 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
3906 set1->nodeMax = XML_NODESET_DEFAULT; 4007 set1->nodeMax = XML_NODESET_DEFAULT;
3907 } else if (set1->nodeNr >= set1->nodeMax) { 4008 } else if (set1->nodeNr >= set1->nodeMax) {
3908 xmlNodePtr *temp; 4009 xmlNodePtr *temp;
3909 4010
3910 » » set1->nodeMax *= 2; 4011 if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
4012 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
4013 return(NULL);
4014 }
3911 temp = (xmlNodePtr *) xmlRealloc( 4015 temp = (xmlNodePtr *) xmlRealloc(
3912 » » set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); 4016 » » set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
3913 if (temp == NULL) { 4017 if (temp == NULL) {
3914 xmlXPathErrMemory(NULL, "merging nodeset\n"); 4018 xmlXPathErrMemory(NULL, "merging nodeset\n");
3915 return(NULL); 4019 return(NULL);
3916 } 4020 }
3917 set1->nodeTab = temp; 4021 set1->nodeTab = temp;
4022 set1->nodeMax *= 2;
3918 } 4023 }
3919 if (n2->type == XML_NAMESPACE_DECL) { 4024 if (n2->type == XML_NAMESPACE_DECL) {
3920 xmlNsPtr ns = (xmlNsPtr) n2; 4025 xmlNsPtr ns = (xmlNsPtr) n2;
3921 4026
3922 set1->nodeTab[set1->nodeNr++] = 4027 set1->nodeTab[set1->nodeNr++] =
3923 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns); 4028 xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
3924 } else 4029 } else
3925 set1->nodeTab[set1->nodeNr++] = n2; 4030 set1->nodeTab[set1->nodeNr++] = n2;
3926 skip_node: 4031 skip_node:
3927 {} 4032 {}
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
3984 if (set1->nodeTab == NULL) { 4089 if (set1->nodeTab == NULL) {
3985 xmlXPathErrMemory(NULL, "merging nodeset\n"); 4090 xmlXPathErrMemory(NULL, "merging nodeset\n");
3986 return(NULL); 4091 return(NULL);
3987 } 4092 }
3988 memset(set1->nodeTab, 0, 4093 memset(set1->nodeTab, 0,
3989 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr)); 4094 XML_NODESET_DEFAULT * (size_t) sizeof(xmlNodePtr));
3990 set1->nodeMax = XML_NODESET_DEFAULT; 4095 set1->nodeMax = XML_NODESET_DEFAULT;
3991 } else if (set1->nodeNr >= set1->nodeMax) { 4096 } else if (set1->nodeNr >= set1->nodeMax) {
3992 xmlNodePtr *temp; 4097 xmlNodePtr *temp;
3993 4098
3994 » » set1->nodeMax *= 2; 4099 if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH) {
4100 xmlXPathErrMemory(NULL, "merging nodeset hit limit\n");
4101 return(NULL);
4102 }
3995 temp = (xmlNodePtr *) xmlRealloc( 4103 temp = (xmlNodePtr *) xmlRealloc(
3996 » » set1->nodeTab, set1->nodeMax * sizeof(xmlNodePtr)); 4104 » » set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
3997 if (temp == NULL) { 4105 if (temp == NULL) {
3998 xmlXPathErrMemory(NULL, "merging nodeset\n"); 4106 xmlXPathErrMemory(NULL, "merging nodeset\n");
3999 return(NULL); 4107 return(NULL);
4000 } 4108 }
4001 set1->nodeTab = temp; 4109 set1->nodeTab = temp;
4110 set1->nodeMax *= 2;
4002 } 4111 }
4003 set1->nodeTab[set1->nodeNr++] = n2; 4112 set1->nodeTab[set1->nodeNr++] = n2;
4004 } 4113 }
4005 } 4114 }
4006 set2->nodeNr = 0; 4115 set2->nodeNr = 0;
4007 return(set1); 4116 return(set1);
4008 } 4117 }
4009 4118
4010 /** 4119 /**
4011 * xmlXPathNodeSetDel: 4120 * xmlXPathNodeSetDel:
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
4282 { 4391 {
4283 xmlXPathObjectPtr ret; 4392 xmlXPathObjectPtr ret;
4284 int i; 4393 int i;
4285 4394
4286 if (val == NULL) 4395 if (val == NULL)
4287 ret = NULL; 4396 ret = NULL;
4288 else if (val->nodeTab == NULL) 4397 else if (val->nodeTab == NULL)
4289 ret = xmlXPathNewNodeSet(NULL); 4398 ret = xmlXPathNewNodeSet(NULL);
4290 else { 4399 else {
4291 ret = xmlXPathNewNodeSet(val->nodeTab[0]); 4400 ret = xmlXPathNewNodeSet(val->nodeTab[0]);
4292 if (ret) 4401 if (ret) {
4293 for (i = 1; i < val->nodeNr; ++i) 4402 for (i = 1; i < val->nodeNr; ++i) {
4294 xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i]); 4403 if (xmlXPathNodeSetAddUnique(ret->nodesetval, val->nodeTab[i])
4404 » » < 0) break;
4405 » }
4406 » }
4295 } 4407 }
4296 4408
4297 return (ret); 4409 return (ret);
4298 } 4410 }
4299 4411
4300 /** 4412 /**
4301 * xmlXPathWrapNodeSet: 4413 * xmlXPathWrapNodeSet:
4302 * @val: the NodePtr value 4414 * @val: the NodePtr value
4303 * 4415 *
4304 * Wrap the Nodeset @val in a new xmlXPathObjectPtr 4416 * Wrap the Nodeset @val in a new xmlXPathObjectPtr
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
4360 return(nodes1); 4472 return(nodes1);
4361 4473
4362 ret = xmlXPathNodeSetCreate(NULL); 4474 ret = xmlXPathNodeSetCreate(NULL);
4363 if (xmlXPathNodeSetIsEmpty(nodes1)) 4475 if (xmlXPathNodeSetIsEmpty(nodes1))
4364 return(ret); 4476 return(ret);
4365 4477
4366 l1 = xmlXPathNodeSetGetLength(nodes1); 4478 l1 = xmlXPathNodeSetGetLength(nodes1);
4367 4479
4368 for (i = 0; i < l1; i++) { 4480 for (i = 0; i < l1; i++) {
4369 cur = xmlXPathNodeSetItem(nodes1, i); 4481 cur = xmlXPathNodeSetItem(nodes1, i);
4370 » if (!xmlXPathNodeSetContains(nodes2, cur)) 4482 » if (!xmlXPathNodeSetContains(nodes2, cur)) {
4371 » xmlXPathNodeSetAddUnique(ret, cur); 4483 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
4484 » break;
4485 » }
4372 } 4486 }
4373 return(ret); 4487 return(ret);
4374 } 4488 }
4375 4489
4376 /** 4490 /**
4377 * xmlXPathIntersection: 4491 * xmlXPathIntersection:
4378 * @nodes1: a node-set 4492 * @nodes1: a node-set
4379 * @nodes2: a node-set 4493 * @nodes2: a node-set
4380 * 4494 *
4381 * Implements the EXSLT - Sets intersection() function: 4495 * Implements the EXSLT - Sets intersection() function:
(...skipping 12 matching lines...) Expand all
4394 return(ret); 4508 return(ret);
4395 if (xmlXPathNodeSetIsEmpty(nodes1)) 4509 if (xmlXPathNodeSetIsEmpty(nodes1))
4396 return(ret); 4510 return(ret);
4397 if (xmlXPathNodeSetIsEmpty(nodes2)) 4511 if (xmlXPathNodeSetIsEmpty(nodes2))
4398 return(ret); 4512 return(ret);
4399 4513
4400 l1 = xmlXPathNodeSetGetLength(nodes1); 4514 l1 = xmlXPathNodeSetGetLength(nodes1);
4401 4515
4402 for (i = 0; i < l1; i++) { 4516 for (i = 0; i < l1; i++) {
4403 cur = xmlXPathNodeSetItem(nodes1, i); 4517 cur = xmlXPathNodeSetItem(nodes1, i);
4404 » if (xmlXPathNodeSetContains(nodes2, cur)) 4518 » if (xmlXPathNodeSetContains(nodes2, cur)) {
4405 » xmlXPathNodeSetAddUnique(ret, cur); 4519 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
4520 » break;
4521 » }
4406 } 4522 }
4407 return(ret); 4523 return(ret);
4408 } 4524 }
4409 4525
4410 /** 4526 /**
4411 * xmlXPathDistinctSorted: 4527 * xmlXPathDistinctSorted:
4412 * @nodes: a node-set, sorted by document order 4528 * @nodes: a node-set, sorted by document order
4413 * 4529 *
4414 * Implements the EXSLT - Sets distinct() function: 4530 * Implements the EXSLT - Sets distinct() function:
4415 * node-set set:distinct (node-set) 4531 * node-set set:distinct (node-set)
(...skipping 15 matching lines...) Expand all
4431 ret = xmlXPathNodeSetCreate(NULL); 4547 ret = xmlXPathNodeSetCreate(NULL);
4432 if (ret == NULL) 4548 if (ret == NULL)
4433 return(ret); 4549 return(ret);
4434 l = xmlXPathNodeSetGetLength(nodes); 4550 l = xmlXPathNodeSetGetLength(nodes);
4435 hash = xmlHashCreate (l); 4551 hash = xmlHashCreate (l);
4436 for (i = 0; i < l; i++) { 4552 for (i = 0; i < l; i++) {
4437 cur = xmlXPathNodeSetItem(nodes, i); 4553 cur = xmlXPathNodeSetItem(nodes, i);
4438 strval = xmlXPathCastNodeToString(cur); 4554 strval = xmlXPathCastNodeToString(cur);
4439 if (xmlHashLookup(hash, strval) == NULL) { 4555 if (xmlHashLookup(hash, strval) == NULL) {
4440 xmlHashAddEntry(hash, strval, strval); 4556 xmlHashAddEntry(hash, strval, strval);
4441 » xmlXPathNodeSetAddUnique(ret, cur); 4557 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
4558 » break;
4442 } else { 4559 } else {
4443 xmlFree(strval); 4560 xmlFree(strval);
4444 } 4561 }
4445 } 4562 }
4446 xmlHashFree(hash, (xmlHashDeallocator) xmlFree); 4563 xmlHashFree(hash, (xmlHashDeallocator) xmlFree);
4447 return(ret); 4564 return(ret);
4448 } 4565 }
4449 4566
4450 /** 4567 /**
4451 * xmlXPathDistinct: 4568 * xmlXPathDistinct:
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
4523 return(ret); 4640 return(ret);
4524 if (xmlXPathNodeSetIsEmpty(nodes) || 4641 if (xmlXPathNodeSetIsEmpty(nodes) ||
4525 (!xmlXPathNodeSetContains(nodes, node))) 4642 (!xmlXPathNodeSetContains(nodes, node)))
4526 return(ret); 4643 return(ret);
4527 4644
4528 l = xmlXPathNodeSetGetLength(nodes); 4645 l = xmlXPathNodeSetGetLength(nodes);
4529 for (i = 0; i < l; i++) { 4646 for (i = 0; i < l; i++) {
4530 cur = xmlXPathNodeSetItem(nodes, i); 4647 cur = xmlXPathNodeSetItem(nodes, i);
4531 if (cur == node) 4648 if (cur == node)
4532 break; 4649 break;
4533 » xmlXPathNodeSetAddUnique(ret, cur); 4650 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
4651 » break;
4534 } 4652 }
4535 return(ret); 4653 return(ret);
4536 } 4654 }
4537 4655
4538 /** 4656 /**
4539 * xmlXPathNodeLeading: 4657 * xmlXPathNodeLeading:
4540 * @nodes: a node-set 4658 * @nodes: a node-set
4541 * @node: a node 4659 * @node: a node
4542 * 4660 *
4543 * Implements the EXSLT - Sets leading() function: 4661 * Implements the EXSLT - Sets leading() function:
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
4627 return(ret); 4745 return(ret);
4628 if (xmlXPathNodeSetIsEmpty(nodes) || 4746 if (xmlXPathNodeSetIsEmpty(nodes) ||
4629 (!xmlXPathNodeSetContains(nodes, node))) 4747 (!xmlXPathNodeSetContains(nodes, node)))
4630 return(ret); 4748 return(ret);
4631 4749
4632 l = xmlXPathNodeSetGetLength(nodes); 4750 l = xmlXPathNodeSetGetLength(nodes);
4633 for (i = l - 1; i >= 0; i--) { 4751 for (i = l - 1; i >= 0; i--) {
4634 cur = xmlXPathNodeSetItem(nodes, i); 4752 cur = xmlXPathNodeSetItem(nodes, i);
4635 if (cur == node) 4753 if (cur == node)
4636 break; 4754 break;
4637 » xmlXPathNodeSetAddUnique(ret, cur); 4755 » if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
4756 » break;
4638 } 4757 }
4639 xmlXPathNodeSetSort(ret); /* bug 413451 */ 4758 xmlXPathNodeSetSort(ret); /* bug 413451 */
4640 return(ret); 4759 return(ret);
4641 } 4760 }
4642 4761
4643 /** 4762 /**
4644 * xmlXPathNodeTrailing: 4763 * xmlXPathNodeTrailing:
4645 * @nodes: a node-set 4764 * @nodes: a node-set
4646 * @node: a node 4765 * @node: a node
4647 * 4766 *
(...skipping 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after
6147 ret->valueTab = (xmlXPathObjectPtr *) 6266 ret->valueTab = (xmlXPathObjectPtr *)
6148 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); 6267 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
6149 if (ret->valueTab == NULL) { 6268 if (ret->valueTab == NULL) {
6150 xmlFree(ret); 6269 xmlFree(ret);
6151 xmlXPathErrMemory(ctxt, "creating evaluation context\n"); 6270 xmlXPathErrMemory(ctxt, "creating evaluation context\n");
6152 return(NULL); 6271 return(NULL);
6153 } 6272 }
6154 ret->valueNr = 0; 6273 ret->valueNr = 0;
6155 ret->valueMax = 10; 6274 ret->valueMax = 10;
6156 ret->value = NULL; 6275 ret->value = NULL;
6276 ret->valueFrame = 0;
6157 6277
6158 ret->context = ctxt; 6278 ret->context = ctxt;
6159 ret->comp = comp; 6279 ret->comp = comp;
6160 6280
6161 return(ret); 6281 return(ret);
6162 } 6282 }
6163 6283
6164 /** 6284 /**
6165 * xmlXPathFreeParserContext: 6285 * xmlXPathFreeParserContext:
6166 * @ctxt: the context to free 6286 * @ctxt: the context to free
(...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after
7649 return(cur->next); 7769 return(cur->next);
7650 cur = cur->next; 7770 cur = cur->next;
7651 do { 7771 do {
7652 cur = cur->next; 7772 cur = cur->next;
7653 } while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE)); 7773 } while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE));
7654 return(cur); 7774 return(cur);
7655 } 7775 }
7656 return(NULL); 7776 return(NULL);
7657 } 7777 }
7658 7778
7779 #if 0
7659 /** 7780 /**
7660 * xmlXPathNextDescendantOrSelfElemParent: 7781 * xmlXPathNextDescendantOrSelfElemParent:
7661 * @ctxt: the XPath Parser context 7782 * @ctxt: the XPath Parser context
7662 * @cur: the current node in the traversal 7783 * @cur: the current node in the traversal
7663 * 7784 *
7664 * Traversal function for the "descendant-or-self" axis. 7785 * Traversal function for the "descendant-or-self" axis.
7665 * Additionally it returns only nodes which can be parents of 7786 * Additionally it returns only nodes which can be parents of
7666 * element nodes. 7787 * element nodes.
7667 * 7788 *
7668 * 7789 *
7669 * Returns the next element following that axis 7790 * Returns the next element following that axis
7670 */ 7791 */
7671 static xmlNodePtr 7792 static xmlNodePtr
7672 xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur, 7793 xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur,
7673 xmlNodePtr contextNode) 7794 xmlNodePtr contextNode)
7674 { 7795 {
7675 if (cur == NULL) { 7796 if (cur == NULL) {
7676 if (contextNode == NULL) 7797 if (contextNode == NULL)
7677 return(NULL); 7798 return(NULL);
7678 switch (contextNode->type) { 7799 switch (contextNode->type) {
7679 case XML_ELEMENT_NODE: 7800 case XML_ELEMENT_NODE:
7680 case XML_XINCLUDE_START: 7801 case XML_XINCLUDE_START:
7681 case XML_DOCUMENT_FRAG_NODE: 7802 case XML_DOCUMENT_FRAG_NODE:
7682 case XML_DOCUMENT_NODE: 7803 case XML_DOCUMENT_NODE:
7683 #ifdef LIBXML_DOCB_ENABLED 7804 #ifdef LIBXML_DOCB_ENABLED
7684 case XML_DOCB_DOCUMENT_NODE: 7805 case XML_DOCB_DOCUMENT_NODE:
7685 #endif 7806 #endif
7686 » case XML_HTML_DOCUMENT_NODE:» 7807 » case XML_HTML_DOCUMENT_NODE:
7687 return(contextNode); 7808 return(contextNode);
7688 default: 7809 default:
7689 return(NULL); 7810 return(NULL);
7690 } 7811 }
7691 return(NULL); 7812 return(NULL);
7692 } else { 7813 } else {
7693 xmlNodePtr start = cur; 7814 xmlNodePtr start = cur;
7694 7815
7695 while (cur != NULL) { 7816 while (cur != NULL) {
7696 switch (cur->type) { 7817 switch (cur->type) {
(...skipping 27 matching lines...) Expand all
7724 if (cur->next != NULL) { 7845 if (cur->next != NULL) {
7725 cur = cur->next; 7846 cur = cur->next;
7726 } else { 7847 } else {
7727 cur = cur->parent; 7848 cur = cur->parent;
7728 goto next_sibling; 7849 goto next_sibling;
7729 } 7850 }
7730 } 7851 }
7731 } 7852 }
7732 return(NULL); 7853 return(NULL);
7733 } 7854 }
7855 #endif
7734 7856
7735 /** 7857 /**
7736 * xmlXPathNextDescendant: 7858 * xmlXPathNextDescendant:
7737 * @ctxt: the XPath Parser context 7859 * @ctxt: the XPath Parser context
7738 * @cur: the current node in the traversal 7860 * @cur: the current node in the traversal
7739 * 7861 *
7740 * Traversal function for the "descendant" direction 7862 * Traversal function for the "descendant" direction
7741 * the descendant axis contains the descendants of the context node in document 7863 * the descendant axis contains the descendants of the context node in document
7742 * order; a descendant is a child or a child of a child and so on. 7864 * order; a descendant is a child or a child of a child and so on.
7743 * 7865 *
7744 * Returns the next element following that axis 7866 * Returns the next element following that axis
7745 */ 7867 */
7746 xmlNodePtr 7868 xmlNodePtr
7747 xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) { 7869 xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7748 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); 7870 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7749 if (cur == NULL) { 7871 if (cur == NULL) {
7750 if (ctxt->context->node == NULL) 7872 if (ctxt->context->node == NULL)
7751 return(NULL); 7873 return(NULL);
7752 if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) || 7874 if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
7753 (ctxt->context->node->type == XML_NAMESPACE_DECL)) 7875 (ctxt->context->node->type == XML_NAMESPACE_DECL))
7754 return(NULL); 7876 return(NULL);
7755 7877
7756 if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc) 7878 if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
7757 return(ctxt->context->doc->children); 7879 return(ctxt->context->doc->children);
7758 return(ctxt->context->node->children); 7880 return(ctxt->context->node->children);
7759 } 7881 }
7760 7882
7883 if (cur->type == XML_NAMESPACE_DECL)
7884 return(NULL);
7761 if (cur->children != NULL) { 7885 if (cur->children != NULL) {
7762 /* 7886 /*
7763 * Do not descend on entities declarations 7887 * Do not descend on entities declarations
7764 */ 7888 */
7765 if (cur->children->type != XML_ENTITY_DECL) { 7889 if (cur->children->type != XML_ENTITY_DECL) {
7766 cur = cur->children; 7890 cur = cur->children;
7767 /* 7891 /*
7768 * Skip DTDs 7892 * Skip DTDs
7769 */ 7893 */
7770 if (cur->type != XML_DTD_NODE) 7894 if (cur->type != XML_DTD_NODE)
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
8133 * @ancestor: the ancestor node 8257 * @ancestor: the ancestor node
8134 * @node: the current node 8258 * @node: the current node
8135 * 8259 *
8136 * Check that @ancestor is a @node's ancestor 8260 * Check that @ancestor is a @node's ancestor
8137 * 8261 *
8138 * returns 1 if @ancestor is a @node's ancestor, 0 otherwise. 8262 * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
8139 */ 8263 */
8140 static int 8264 static int
8141 xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) { 8265 xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
8142 if ((ancestor == NULL) || (node == NULL)) return(0); 8266 if ((ancestor == NULL) || (node == NULL)) return(0);
8267 if (node->type == XML_NAMESPACE_DECL)
8268 return(0);
8269 if (ancestor->type == XML_NAMESPACE_DECL)
8270 return(0);
8143 /* nodes need to be in the same document */ 8271 /* nodes need to be in the same document */
8144 if (ancestor->doc != node->doc) return(0); 8272 if (ancestor->doc != node->doc) return(0);
8145 /* avoid searching if ancestor or node is the root node */ 8273 /* avoid searching if ancestor or node is the root node */
8146 if (ancestor == (xmlNodePtr) node->doc) return(1); 8274 if (ancestor == (xmlNodePtr) node->doc) return(1);
8147 if (node == (xmlNodePtr) ancestor->doc) return(0); 8275 if (node == (xmlNodePtr) ancestor->doc) return(0);
8148 while (node->parent != NULL) { 8276 while (node->parent != NULL) {
8149 if (node->parent == ancestor) 8277 if (node->parent == ancestor)
8150 return(1); 8278 return(1);
8151 node = node->parent; 8279 node = node->parent;
8152 } 8280 }
(...skipping 17 matching lines...) Expand all
8170 xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) 8298 xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
8171 { 8299 {
8172 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); 8300 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
8173 if (cur == NULL) { 8301 if (cur == NULL) {
8174 cur = ctxt->context->node; 8302 cur = ctxt->context->node;
8175 if (cur->type == XML_NAMESPACE_DECL) 8303 if (cur->type == XML_NAMESPACE_DECL)
8176 return(NULL); 8304 return(NULL);
8177 if (cur->type == XML_ATTRIBUTE_NODE) 8305 if (cur->type == XML_ATTRIBUTE_NODE)
8178 return(cur->parent); 8306 return(cur->parent);
8179 } 8307 }
8180 if (cur == NULL) 8308 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
8181 return (NULL); 8309 return (NULL);
8182 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) 8310 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
8183 cur = cur->prev; 8311 cur = cur->prev;
8184 do { 8312 do {
8185 if (cur->prev != NULL) { 8313 if (cur->prev != NULL) {
8186 for (cur = cur->prev; cur->last != NULL; cur = cur->last) ; 8314 for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
8187 return (cur); 8315 return (cur);
8188 } 8316 }
8189 8317
8190 cur = cur->parent; 8318 cur = cur->parent;
(...skipping 26 matching lines...) Expand all
8217 { 8345 {
8218 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL); 8346 if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
8219 if (cur == NULL) { 8347 if (cur == NULL) {
8220 cur = ctxt->context->node; 8348 cur = ctxt->context->node;
8221 if (cur == NULL) 8349 if (cur == NULL)
8222 return (NULL); 8350 return (NULL);
8223 if (cur->type == XML_NAMESPACE_DECL) 8351 if (cur->type == XML_NAMESPACE_DECL)
8224 return (NULL); 8352 return (NULL);
8225 ctxt->ancestor = cur->parent; 8353 ctxt->ancestor = cur->parent;
8226 } 8354 }
8355 if (cur->type == XML_NAMESPACE_DECL)
8356 return(NULL);
8227 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) 8357 if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
8228 cur = cur->prev; 8358 cur = cur->prev;
8229 while (cur->prev == NULL) { 8359 while (cur->prev == NULL) {
8230 cur = cur->parent; 8360 cur = cur->parent;
8231 if (cur == NULL) 8361 if (cur == NULL)
8232 return (NULL); 8362 return (NULL);
8233 if (cur == ctxt->context->doc->children) 8363 if (cur == ctxt->context->doc->children)
8234 return (NULL); 8364 return (NULL);
8235 if (cur != ctxt->ancestor) 8365 if (cur != ctxt->ancestor)
8236 return (cur); 8366 return (cur);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
8424 (double) cur->nodesetval->nodeNr)); 8554 (double) cur->nodesetval->nodeNr));
8425 } else { 8555 } else {
8426 if ((cur->nodesetval->nodeNr != 1) || 8556 if ((cur->nodesetval->nodeNr != 1) ||
8427 (cur->nodesetval->nodeTab == NULL)) { 8557 (cur->nodesetval->nodeTab == NULL)) {
8428 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0)); 8558 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) 0));
8429 } else { 8559 } else {
8430 xmlNodePtr tmp; 8560 xmlNodePtr tmp;
8431 int i = 0; 8561 int i = 0;
8432 8562
8433 tmp = cur->nodesetval->nodeTab[0]; 8563 tmp = cur->nodesetval->nodeTab[0];
8434 » if (tmp != NULL) { 8564 » if ((tmp != NULL) && (tmp->type != XML_NAMESPACE_DECL)) {
8435 tmp = tmp->children; 8565 tmp = tmp->children;
8436 while (tmp != NULL) { 8566 while (tmp != NULL) {
8437 tmp = tmp->next; 8567 tmp = tmp->next;
8438 i++; 8568 i++;
8439 } 8569 }
8440 } 8570 }
8441 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) i)); 8571 valuePush(ctxt, xmlXPathCacheNewFloat(ctxt->context, (double) i));
8442 } 8572 }
8443 } 8573 }
8444 xmlXPathReleaseObject(ctxt->context, cur); 8574 xmlXPathReleaseObject(ctxt->context, cur);
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after
9094 * The substring-before function returns the substring of the first 9224 * The substring-before function returns the substring of the first
9095 * argument string that precedes the first occurrence of the second 9225 * argument string that precedes the first occurrence of the second
9096 * argument string in the first argument string, or the empty string 9226 * argument string in the first argument string, or the empty string
9097 * if the first argument string does not contain the second argument 9227 * if the first argument string does not contain the second argument
9098 * string. For example, substring-before("1999/04/01","/") returns 1999. 9228 * string. For example, substring-before("1999/04/01","/") returns 1999.
9099 */ 9229 */
9100 void 9230 void
9101 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) { 9231 xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
9102 xmlXPathObjectPtr str; 9232 xmlXPathObjectPtr str;
9103 xmlXPathObjectPtr find; 9233 xmlXPathObjectPtr find;
9104 xmlBufferPtr target; 9234 xmlBufPtr target;
9105 const xmlChar *point; 9235 const xmlChar *point;
9106 int offset; 9236 int offset;
9107 9237
9108 CHECK_ARITY(2); 9238 CHECK_ARITY(2);
9109 CAST_TO_STRING; 9239 CAST_TO_STRING;
9110 find = valuePop(ctxt); 9240 find = valuePop(ctxt);
9111 CAST_TO_STRING; 9241 CAST_TO_STRING;
9112 str = valuePop(ctxt); 9242 str = valuePop(ctxt);
9113 9243
9114 target = xmlBufferCreate(); 9244 target = xmlBufCreate();
9115 if (target) { 9245 if (target) {
9116 point = xmlStrstr(str->stringval, find->stringval); 9246 point = xmlStrstr(str->stringval, find->stringval);
9117 if (point) { 9247 if (point) {
9118 offset = (int)(point - str->stringval); 9248 offset = (int)(point - str->stringval);
9119 xmlBufferAdd(target, str->stringval, offset); 9249 xmlBufAdd(target, str->stringval, offset);
9120 } 9250 }
9121 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, 9251 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
9122 » xmlBufferContent(target))); 9252 » xmlBufContent(target)));
9123 xmlBufferFree(target); 9253 xmlBufFree(target);
9124 } 9254 }
9125 xmlXPathReleaseObject(ctxt->context, str); 9255 xmlXPathReleaseObject(ctxt->context, str);
9126 xmlXPathReleaseObject(ctxt->context, find); 9256 xmlXPathReleaseObject(ctxt->context, find);
9127 } 9257 }
9128 9258
9129 /** 9259 /**
9130 * xmlXPathSubstringAfterFunction: 9260 * xmlXPathSubstringAfterFunction:
9131 * @ctxt: the XPath Parser context 9261 * @ctxt: the XPath Parser context
9132 * @nargs: the number of arguments 9262 * @nargs: the number of arguments
9133 * 9263 *
9134 * Implement the substring-after() XPath function 9264 * Implement the substring-after() XPath function
9135 * string substring-after(string, string) 9265 * string substring-after(string, string)
9136 * The substring-after function returns the substring of the first 9266 * The substring-after function returns the substring of the first
9137 * argument string that follows the first occurrence of the second 9267 * argument string that follows the first occurrence of the second
9138 * argument string in the first argument string, or the empty stringi 9268 * argument string in the first argument string, or the empty stringi
9139 * if the first argument string does not contain the second argument 9269 * if the first argument string does not contain the second argument
9140 * string. For example, substring-after("1999/04/01","/") returns 04/01, 9270 * string. For example, substring-after("1999/04/01","/") returns 04/01,
9141 * and substring-after("1999/04/01","19") returns 99/04/01. 9271 * and substring-after("1999/04/01","19") returns 99/04/01.
9142 */ 9272 */
9143 void 9273 void
9144 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) { 9274 xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
9145 xmlXPathObjectPtr str; 9275 xmlXPathObjectPtr str;
9146 xmlXPathObjectPtr find; 9276 xmlXPathObjectPtr find;
9147 xmlBufferPtr target; 9277 xmlBufPtr target;
9148 const xmlChar *point; 9278 const xmlChar *point;
9149 int offset; 9279 int offset;
9150 9280
9151 CHECK_ARITY(2); 9281 CHECK_ARITY(2);
9152 CAST_TO_STRING; 9282 CAST_TO_STRING;
9153 find = valuePop(ctxt); 9283 find = valuePop(ctxt);
9154 CAST_TO_STRING; 9284 CAST_TO_STRING;
9155 str = valuePop(ctxt); 9285 str = valuePop(ctxt);
9156 9286
9157 target = xmlBufferCreate(); 9287 target = xmlBufCreate();
9158 if (target) { 9288 if (target) {
9159 point = xmlStrstr(str->stringval, find->stringval); 9289 point = xmlStrstr(str->stringval, find->stringval);
9160 if (point) { 9290 if (point) {
9161 offset = (int)(point - str->stringval) + xmlStrlen(find->stringval); 9291 offset = (int)(point - str->stringval) + xmlStrlen(find->stringval);
9162 xmlBufferAdd(target, &str->stringval[offset], 9292 xmlBufAdd(target, &str->stringval[offset],
9163 xmlStrlen(str->stringval) - offset); 9293 xmlStrlen(str->stringval) - offset);
9164 } 9294 }
9165 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, 9295 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
9166 » xmlBufferContent(target))); 9296 » xmlBufContent(target)));
9167 xmlBufferFree(target); 9297 xmlBufFree(target);
9168 } 9298 }
9169 xmlXPathReleaseObject(ctxt->context, str); 9299 xmlXPathReleaseObject(ctxt->context, str);
9170 xmlXPathReleaseObject(ctxt->context, find); 9300 xmlXPathReleaseObject(ctxt->context, find);
9171 } 9301 }
9172 9302
9173 /** 9303 /**
9174 * xmlXPathNormalizeFunction: 9304 * xmlXPathNormalizeFunction:
9175 * @ctxt: the XPath Parser context 9305 * @ctxt: the XPath Parser context
9176 * @nargs: the number of arguments 9306 * @nargs: the number of arguments
9177 * 9307 *
9178 * Implement the normalize-space() XPath function 9308 * Implement the normalize-space() XPath function
9179 * string normalize-space(string?) 9309 * string normalize-space(string?)
9180 * The normalize-space function returns the argument string with white 9310 * The normalize-space function returns the argument string with white
9181 * space normalized by stripping leading and trailing whitespace 9311 * space normalized by stripping leading and trailing whitespace
9182 * and replacing sequences of whitespace characters by a single 9312 * and replacing sequences of whitespace characters by a single
9183 * space. Whitespace characters are the same allowed by the S production 9313 * space. Whitespace characters are the same allowed by the S production
9184 * in XML. If the argument is omitted, it defaults to the context 9314 * in XML. If the argument is omitted, it defaults to the context
9185 * node converted to a string, in other words the value of the context node. 9315 * node converted to a string, in other words the value of the context node.
9186 */ 9316 */
9187 void 9317 void
9188 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) { 9318 xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
9189 xmlXPathObjectPtr obj = NULL; 9319 xmlXPathObjectPtr obj = NULL;
9190 xmlChar *source = NULL; 9320 xmlChar *source = NULL;
9191 xmlBufferPtr target; 9321 xmlBufPtr target;
9192 xmlChar blank; 9322 xmlChar blank;
9193 9323
9194 if (ctxt == NULL) return; 9324 if (ctxt == NULL) return;
9195 if (nargs == 0) { 9325 if (nargs == 0) {
9196 /* Use current context node */ 9326 /* Use current context node */
9197 valuePush(ctxt, 9327 valuePush(ctxt,
9198 xmlXPathCacheWrapString(ctxt->context, 9328 xmlXPathCacheWrapString(ctxt->context,
9199 xmlXPathCastNodeToString(ctxt->context->node))); 9329 xmlXPathCastNodeToString(ctxt->context->node)));
9200 nargs = 1; 9330 nargs = 1;
9201 } 9331 }
9202 9332
9203 CHECK_ARITY(1); 9333 CHECK_ARITY(1);
9204 CAST_TO_STRING; 9334 CAST_TO_STRING;
9205 CHECK_TYPE(XPATH_STRING); 9335 CHECK_TYPE(XPATH_STRING);
9206 obj = valuePop(ctxt); 9336 obj = valuePop(ctxt);
9207 source = obj->stringval; 9337 source = obj->stringval;
9208 9338
9209 target = xmlBufferCreate(); 9339 target = xmlBufCreate();
9210 if (target && source) { 9340 if (target && source) {
9211 9341
9212 /* Skip leading whitespaces */ 9342 /* Skip leading whitespaces */
9213 while (IS_BLANK_CH(*source)) 9343 while (IS_BLANK_CH(*source))
9214 source++; 9344 source++;
9215 9345
9216 /* Collapse intermediate whitespaces, and skip trailing whitespaces */ 9346 /* Collapse intermediate whitespaces, and skip trailing whitespaces */
9217 blank = 0; 9347 blank = 0;
9218 while (*source) { 9348 while (*source) {
9219 if (IS_BLANK_CH(*source)) { 9349 if (IS_BLANK_CH(*source)) {
9220 blank = 0x20; 9350 blank = 0x20;
9221 } else { 9351 } else {
9222 if (blank) { 9352 if (blank) {
9223 » xmlBufferAdd(target, &blank, 1); 9353 » xmlBufAdd(target, &blank, 1);
9224 blank = 0; 9354 blank = 0;
9225 } 9355 }
9226 » xmlBufferAdd(target, source, 1); 9356 » xmlBufAdd(target, source, 1);
9227 } 9357 }
9228 source++; 9358 source++;
9229 } 9359 }
9230 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, 9360 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
9231 » xmlBufferContent(target))); 9361 » xmlBufContent(target)));
9232 xmlBufferFree(target); 9362 xmlBufFree(target);
9233 } 9363 }
9234 xmlXPathReleaseObject(ctxt->context, obj); 9364 xmlXPathReleaseObject(ctxt->context, obj);
9235 } 9365 }
9236 9366
9237 /** 9367 /**
9238 * xmlXPathTranslateFunction: 9368 * xmlXPathTranslateFunction:
9239 * @ctxt: the XPath Parser context 9369 * @ctxt: the XPath Parser context
9240 * @nargs: the number of arguments 9370 * @nargs: the number of arguments
9241 * 9371 *
9242 * Implement the translate() XPath function 9372 * Implement the translate() XPath function
(...skipping 10 matching lines...) Expand all
9253 * returns "AAA". If a character occurs more than once in second 9383 * returns "AAA". If a character occurs more than once in second
9254 * argument string, then the first occurrence determines the replacement 9384 * argument string, then the first occurrence determines the replacement
9255 * character. If the third argument string is longer than the second 9385 * character. If the third argument string is longer than the second
9256 * argument string, then excess characters are ignored. 9386 * argument string, then excess characters are ignored.
9257 */ 9387 */
9258 void 9388 void
9259 xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) { 9389 xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
9260 xmlXPathObjectPtr str; 9390 xmlXPathObjectPtr str;
9261 xmlXPathObjectPtr from; 9391 xmlXPathObjectPtr from;
9262 xmlXPathObjectPtr to; 9392 xmlXPathObjectPtr to;
9263 xmlBufferPtr target; 9393 xmlBufPtr target;
9264 int offset, max; 9394 int offset, max;
9265 xmlChar ch; 9395 xmlChar ch;
9266 const xmlChar *point; 9396 const xmlChar *point;
9267 xmlChar *cptr; 9397 xmlChar *cptr;
9268 9398
9269 CHECK_ARITY(3); 9399 CHECK_ARITY(3);
9270 9400
9271 CAST_TO_STRING; 9401 CAST_TO_STRING;
9272 to = valuePop(ctxt); 9402 to = valuePop(ctxt);
9273 CAST_TO_STRING; 9403 CAST_TO_STRING;
9274 from = valuePop(ctxt); 9404 from = valuePop(ctxt);
9275 CAST_TO_STRING; 9405 CAST_TO_STRING;
9276 str = valuePop(ctxt); 9406 str = valuePop(ctxt);
9277 9407
9278 target = xmlBufferCreate(); 9408 target = xmlBufCreate();
9279 if (target) { 9409 if (target) {
9280 max = xmlUTF8Strlen(to->stringval); 9410 max = xmlUTF8Strlen(to->stringval);
9281 for (cptr = str->stringval; (ch=*cptr); ) { 9411 for (cptr = str->stringval; (ch=*cptr); ) {
9282 offset = xmlUTF8Strloc(from->stringval, cptr); 9412 offset = xmlUTF8Strloc(from->stringval, cptr);
9283 if (offset >= 0) { 9413 if (offset >= 0) {
9284 if (offset < max) { 9414 if (offset < max) {
9285 point = xmlUTF8Strpos(to->stringval, offset); 9415 point = xmlUTF8Strpos(to->stringval, offset);
9286 if (point) 9416 if (point)
9287 » » » xmlBufferAdd(target, point, xmlUTF8Strsize(point, 1)); 9417 » » » xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
9288 } 9418 }
9289 } else 9419 } else
9290 » » xmlBufferAdd(target, cptr, xmlUTF8Strsize(cptr, 1)); 9420 » » xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
9291 9421
9292 /* Step to next character in input */ 9422 /* Step to next character in input */
9293 cptr++; 9423 cptr++;
9294 if ( ch & 0x80 ) { 9424 if ( ch & 0x80 ) {
9295 /* if not simple ascii, verify proper format */ 9425 /* if not simple ascii, verify proper format */
9296 if ( (ch & 0xc0) != 0xc0 ) { 9426 if ( (ch & 0xc0) != 0xc0 ) {
9297 xmlGenericError(xmlGenericErrorContext, 9427 xmlGenericError(xmlGenericErrorContext,
9298 "xmlXPathTranslateFunction: Invalid UTF8 string\n"); 9428 "xmlXPathTranslateFunction: Invalid UTF8 string\n");
9429 /* not asserting an XPath error is probably better */
9299 break; 9430 break;
9300 } 9431 }
9301 /* then skip over remaining bytes for this char */ 9432 /* then skip over remaining bytes for this char */
9302 while ( (ch <<= 1) & 0x80 ) 9433 while ( (ch <<= 1) & 0x80 )
9303 if ( (*cptr++ & 0xc0) != 0x80 ) { 9434 if ( (*cptr++ & 0xc0) != 0x80 ) {
9304 xmlGenericError(xmlGenericErrorContext, 9435 xmlGenericError(xmlGenericErrorContext,
9305 "xmlXPathTranslateFunction: Invalid UTF8 string\n"); 9436 "xmlXPathTranslateFunction: Invalid UTF8 string\n");
9437 /* not asserting an XPath error is probably better */
9306 break; 9438 break;
9307 } 9439 }
9308 if (ch & 0x80) /* must have had error encountered */ 9440 if (ch & 0x80) /* must have had error encountered */
9309 break; 9441 break;
9310 } 9442 }
9311 } 9443 }
9312 } 9444 }
9313 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, 9445 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
9314 » xmlBufferContent(target))); 9446 » xmlBufContent(target)));
9315 xmlBufferFree(target); 9447 xmlBufFree(target);
9316 xmlXPathReleaseObject(ctxt->context, str); 9448 xmlXPathReleaseObject(ctxt->context, str);
9317 xmlXPathReleaseObject(ctxt->context, from); 9449 xmlXPathReleaseObject(ctxt->context, from);
9318 xmlXPathReleaseObject(ctxt->context, to); 9450 xmlXPathReleaseObject(ctxt->context, to);
9319 } 9451 }
9320 9452
9321 /** 9453 /**
9322 * xmlXPathBooleanFunction: 9454 * xmlXPathBooleanFunction:
9323 * @ctxt: the XPath Parser context 9455 * @ctxt: the XPath Parser context
9324 * @nargs: the number of arguments 9456 * @nargs: the number of arguments
9325 * 9457 *
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
9812 * 9944 *
9813 * [5] Name ::= (Letter | '_' | ':') (NameChar)* 9945 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
9814 * 9946 *
9815 * Returns the namespace name or NULL 9947 * Returns the namespace name or NULL
9816 */ 9948 */
9817 9949
9818 xmlChar * 9950 xmlChar *
9819 xmlXPathParseName(xmlXPathParserContextPtr ctxt) { 9951 xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
9820 const xmlChar *in; 9952 const xmlChar *in;
9821 xmlChar *ret; 9953 xmlChar *ret;
9822 int count = 0; 9954 size_t count = 0;
9823 9955
9824 if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL); 9956 if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
9825 /* 9957 /*
9826 * Accelerator for simple ASCII names 9958 * Accelerator for simple ASCII names
9827 */ 9959 */
9828 in = ctxt->cur; 9960 in = ctxt->cur;
9829 if (((*in >= 0x61) && (*in <= 0x7A)) || 9961 if (((*in >= 0x61) && (*in <= 0x7A)) ||
9830 ((*in >= 0x41) && (*in <= 0x5A)) || 9962 ((*in >= 0x41) && (*in <= 0x5A)) ||
9831 (*in == '_') || (*in == ':')) { 9963 (*in == '_') || (*in == ':')) {
9832 in++; 9964 in++;
9833 while (((*in >= 0x61) && (*in <= 0x7A)) || 9965 while (((*in >= 0x61) && (*in <= 0x7A)) ||
9834 ((*in >= 0x41) && (*in <= 0x5A)) || 9966 ((*in >= 0x41) && (*in <= 0x5A)) ||
9835 ((*in >= 0x30) && (*in <= 0x39)) || 9967 ((*in >= 0x30) && (*in <= 0x39)) ||
9836 (*in == '_') || (*in == '-') || 9968 (*in == '_') || (*in == '-') ||
9837 (*in == ':') || (*in == '.')) 9969 (*in == ':') || (*in == '.'))
9838 in++; 9970 in++;
9839 if ((*in > 0) && (*in < 0x80)) { 9971 if ((*in > 0) && (*in < 0x80)) {
9840 count = in - ctxt->cur; 9972 count = in - ctxt->cur;
9973 if (count > XML_MAX_NAME_LENGTH) {
9974 ctxt->cur = in;
9975 XP_ERRORNULL(XPATH_EXPR_ERROR);
9976 }
9841 ret = xmlStrndup(ctxt->cur, count); 9977 ret = xmlStrndup(ctxt->cur, count);
9842 ctxt->cur = in; 9978 ctxt->cur = in;
9843 return(ret); 9979 return(ret);
9844 } 9980 }
9845 } 9981 }
9846 return(xmlXPathParseNameComplex(ctxt, 1)); 9982 return(xmlXPathParseNameComplex(ctxt, 1));
9847 } 9983 }
9848 9984
9849 static xmlChar * 9985 static xmlChar *
9850 xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) { 9986 xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
(...skipping 23 matching lines...) Expand all
9874 NEXTL(l); 10010 NEXTL(l);
9875 c = CUR_CHAR(l); 10011 c = CUR_CHAR(l);
9876 if (len >= XML_MAX_NAMELEN) { 10012 if (len >= XML_MAX_NAMELEN) {
9877 /* 10013 /*
9878 * Okay someone managed to make a huge name, so he's ready to pay 10014 * Okay someone managed to make a huge name, so he's ready to pay
9879 * for the processing speed. 10015 * for the processing speed.
9880 */ 10016 */
9881 xmlChar *buffer; 10017 xmlChar *buffer;
9882 int max = len * 2; 10018 int max = len * 2;
9883 10019
10020 if (len > XML_MAX_NAME_LENGTH) {
10021 XP_ERRORNULL(XPATH_EXPR_ERROR);
10022 }
9884 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar)); 10023 buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
9885 if (buffer == NULL) { 10024 if (buffer == NULL) {
9886 XP_ERRORNULL(XPATH_MEMORY_ERROR); 10025 XP_ERRORNULL(XPATH_MEMORY_ERROR);
9887 } 10026 }
9888 memcpy(buffer, buf, len); 10027 memcpy(buffer, buf, len);
9889 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */ 10028 while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
9890 (c == '.') || (c == '-') || 10029 (c == '.') || (c == '-') ||
9891 (c == '_') || ((qualified) && (c == ':')) || 10030 (c == '_') || ((qualified) && (c == ':')) ||
9892 (IS_COMBINING(c)) || 10031 (IS_COMBINING(c)) ||
9893 (IS_EXTENDER(c))) { 10032 (IS_EXTENDER(c))) {
9894 if (len + 10 > max) { 10033 if (len + 10 > max) {
10034 if (max > XML_MAX_NAME_LENGTH) {
10035 XP_ERRORNULL(XPATH_EXPR_ERROR);
10036 }
9895 max *= 2; 10037 max *= 2;
9896 buffer = (xmlChar *) xmlRealloc(buffer, 10038 buffer = (xmlChar *) xmlRealloc(buffer,
9897 max * sizeof(xmlChar)); 10039 max * sizeof(xmlChar));
9898 if (buffer == NULL) { 10040 if (buffer == NULL) {
9899 XP_ERRORNULL(XPATH_MEMORY_ERROR); 10041 XP_ERRORNULL(XPATH_MEMORY_ERROR);
9900 } 10042 }
9901 } 10043 }
9902 COPY_BUF(l,buffer,len,c); 10044 COPY_BUF(l,buffer,len,c);
9903 NEXTL(l); 10045 NEXTL(l);
9904 c = CUR_CHAR(l); 10046 c = CUR_CHAR(l);
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
10037 * | '.' Digits 10179 * | '.' Digits
10038 * [31] Digits ::= [0-9]+ 10180 * [31] Digits ::= [0-9]+
10039 * 10181 *
10040 * Compile a Number, then push it on the stack 10182 * Compile a Number, then push it on the stack
10041 * 10183 *
10042 */ 10184 */
10043 static void 10185 static void
10044 xmlXPathCompNumber(xmlXPathParserContextPtr ctxt) 10186 xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
10045 { 10187 {
10046 double ret = 0.0; 10188 double ret = 0.0;
10047 double mult = 1;
10048 int ok = 0; 10189 int ok = 0;
10049 int exponent = 0; 10190 int exponent = 0;
10050 int is_exponent_negative = 0; 10191 int is_exponent_negative = 0;
10051 #ifdef __GNUC__ 10192 #ifdef __GNUC__
10052 unsigned long tmp = 0; 10193 unsigned long tmp = 0;
10053 double temp; 10194 double temp;
10054 #endif 10195 #endif
10055 10196
10056 CHECK_ERROR; 10197 CHECK_ERROR;
10057 if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) { 10198 if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
(...skipping 15 matching lines...) Expand all
10073 } 10214 }
10074 #else 10215 #else
10075 ret = 0; 10216 ret = 0;
10076 while ((CUR >= '0') && (CUR <= '9')) { 10217 while ((CUR >= '0') && (CUR <= '9')) {
10077 ret = ret * 10 + (CUR - '0'); 10218 ret = ret * 10 + (CUR - '0');
10078 ok = 1; 10219 ok = 1;
10079 NEXT; 10220 NEXT;
10080 } 10221 }
10081 #endif 10222 #endif
10082 if (CUR == '.') { 10223 if (CUR == '.') {
10224 int v, frac = 0;
10225 double fraction = 0;
10226
10083 NEXT; 10227 NEXT;
10084 if (((CUR < '0') || (CUR > '9')) && (!ok)) { 10228 if (((CUR < '0') || (CUR > '9')) && (!ok)) {
10085 XP_ERROR(XPATH_NUMBER_ERROR); 10229 XP_ERROR(XPATH_NUMBER_ERROR);
10086 } 10230 }
10087 while ((CUR >= '0') && (CUR <= '9')) { 10231 while ((CUR >= '0') && (CUR <= '9') && (frac < MAX_FRAC)) {
10088 mult /= 10; 10232 » v = (CUR - '0');
10089 ret = ret + (CUR - '0') * mult; 10233 » fraction = fraction * 10 + v;
10234 » frac = frac + 1;
10090 NEXT; 10235 NEXT;
10091 } 10236 }
10237 fraction /= my_pow10[frac];
10238 ret = ret + fraction;
10239 while ((CUR >= '0') && (CUR <= '9'))
10240 NEXT;
10092 } 10241 }
10093 if ((CUR == 'e') || (CUR == 'E')) { 10242 if ((CUR == 'e') || (CUR == 'E')) {
10094 NEXT; 10243 NEXT;
10095 if (CUR == '-') { 10244 if (CUR == '-') {
10096 is_exponent_negative = 1; 10245 is_exponent_negative = 1;
10097 NEXT; 10246 NEXT;
10098 } else if (CUR == '+') { 10247 } else if (CUR == '+') {
10099 NEXT; 10248 NEXT;
10100 } 10249 }
10101 while ((CUR >= '0') && (CUR <= '9')) { 10250 while ((CUR >= '0') && (CUR <= '9')) {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
10230 NEXT; 10379 NEXT;
10231 name = xmlXPathParseQName(ctxt, &prefix); 10380 name = xmlXPathParseQName(ctxt, &prefix);
10232 if (name == NULL) { 10381 if (name == NULL) {
10233 XP_ERROR(XPATH_VARIABLE_REF_ERROR); 10382 XP_ERROR(XPATH_VARIABLE_REF_ERROR);
10234 } 10383 }
10235 ctxt->comp->last = -1; 10384 ctxt->comp->last = -1;
10236 PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, 10385 PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0,
10237 name, prefix); 10386 name, prefix);
10238 SKIP_BLANKS; 10387 SKIP_BLANKS;
10239 if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) { 10388 if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
10240 » XP_ERROR(XPATH_UNDEF_VARIABLE_ERROR); 10389 » XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
10241 } 10390 }
10242 } 10391 }
10243 10392
10244 /** 10393 /**
10245 * xmlXPathIsNodeType: 10394 * xmlXPathIsNodeType:
10246 * @name: a name string 10395 * @name: a name string
10247 * 10396 *
10248 * Is the name given a NodeType one. 10397 * Is the name given a NodeType one.
10249 * 10398 *
10250 * [38] NodeType ::= 'comment' 10399 * [38] NodeType ::= 'comment'
(...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after
11255 axis = AXIS_CHILD; 11404 axis = AXIS_CHILD;
11256 } 11405 }
11257 } else if (CUR == '@') { 11406 } else if (CUR == '@') {
11258 NEXT; 11407 NEXT;
11259 axis = AXIS_ATTRIBUTE; 11408 axis = AXIS_ATTRIBUTE;
11260 } else { 11409 } else {
11261 axis = AXIS_CHILD; 11410 axis = AXIS_CHILD;
11262 } 11411 }
11263 } 11412 }
11264 11413
11265 » CHECK_ERROR; 11414 if (ctxt->error != XPATH_EXPRESSION_OK) {
11415 xmlFree(name);
11416 return;
11417 }
11266 11418
11267 name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name); 11419 name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
11268 if (test == 0) 11420 if (test == 0)
11269 return; 11421 return;
11270 11422
11271 if ((prefix != NULL) && (ctxt->context != NULL) && 11423 if ((prefix != NULL) && (ctxt->context != NULL) &&
11272 (ctxt->context->flags & XML_XPATH_CHECKNS)) { 11424 (ctxt->context->flags & XML_XPATH_CHECKNS)) {
11273 if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) { 11425 if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) {
11274 xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR); 11426 xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR);
11275 } 11427 }
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
11591 if ((contextNode->type != XML_NAMESPACE_DECL) && 11743 if ((contextNode->type != XML_NAMESPACE_DECL) &&
11592 (contextNode->doc != NULL)) 11744 (contextNode->doc != NULL))
11593 xpctxt->doc = contextNode->doc; 11745 xpctxt->doc = contextNode->doc;
11594 /* 11746 /*
11595 * Evaluate the predicate expression with 1 context node 11747 * Evaluate the predicate expression with 1 context node
11596 * at a time; this node is packaged into a node set; this 11748 * at a time; this node is packaged into a node set; this
11597 * node set is handed over to the evaluation mechanism. 11749 * node set is handed over to the evaluation mechanism.
11598 */ 11750 */
11599 if (contextObj == NULL) 11751 if (contextObj == NULL)
11600 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); 11752 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
11601 » else 11753 » else {
11602 » » xmlXPathNodeSetAddUnique(contextObj->nodesetval, 11754 » » if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
11603 » » contextNode); 11755 » » contextNode) < 0) {
11756 » » ctxt->error = XPATH_MEMORY_ERROR;
11757 » » goto evaluation_exit;
11758 » » }
11759 » }
11604 11760
11605 valuePush(ctxt, contextObj); 11761 valuePush(ctxt, contextObj);
11606 11762
11607 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); 11763 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
11608 11764
11609 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { 11765 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
11610 xmlXPathNodeSetClear(set, hasNsNodes); 11766 xmlXPathNodeSetClear(set, hasNsNodes);
11611 newContextSize = 0; 11767 newContextSize = 0;
11612 goto evaluation_exit; 11768 goto evaluation_exit;
11613 } 11769 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
11694 * TODO: Can this ever happen? 11850 * TODO: Can this ever happen?
11695 */ 11851 */
11696 return (contextSize); 11852 return (contextSize);
11697 } else { 11853 } else {
11698 xmlDocPtr oldContextDoc; 11854 xmlDocPtr oldContextDoc;
11699 int i, pos = 0, newContextSize = 0, contextPos = 0, res; 11855 int i, pos = 0, newContextSize = 0, contextPos = 0, res;
11700 xmlXPathStepOpPtr exprOp; 11856 xmlXPathStepOpPtr exprOp;
11701 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL; 11857 xmlXPathObjectPtr contextObj = NULL, exprRes = NULL;
11702 xmlNodePtr oldContextNode, contextNode = NULL; 11858 xmlNodePtr oldContextNode, contextNode = NULL;
11703 xmlXPathContextPtr xpctxt = ctxt->context; 11859 xmlXPathContextPtr xpctxt = ctxt->context;
11860 int frame;
11704 11861
11705 #ifdef LIBXML_XPTR_ENABLED 11862 #ifdef LIBXML_XPTR_ENABLED
11706 /* 11863 /*
11707 * URGENT TODO: Check the following: 11864 * URGENT TODO: Check the following:
11708 * We don't expect location sets if evaluating prediates, right? 11865 * We don't expect location sets if evaluating prediates, right?
11709 * Only filters should expect location sets, right? 11866 * Only filters should expect location sets, right?
11710 */ 11867 */
11711 #endif /* LIBXML_XPTR_ENABLED */ 11868 #endif /* LIBXML_XPTR_ENABLED */
11712 11869
11713 /* 11870 /*
11714 * Save old context. 11871 * Save old context.
11715 */ 11872 */
11716 oldContextNode = xpctxt->node; 11873 oldContextNode = xpctxt->node;
11717 oldContextDoc = xpctxt->doc; 11874 oldContextDoc = xpctxt->doc;
11718 /* 11875 /*
11719 * Get the expression of this predicate. 11876 * Get the expression of this predicate.
11720 */ 11877 */
11721 exprOp = &ctxt->comp->steps[op->ch2]; 11878 exprOp = &ctxt->comp->steps[op->ch2];
11722 for (i = 0; i < set->nodeNr; i++) { 11879 for (i = 0; i < set->nodeNr; i++) {
11880 xmlXPathObjectPtr tmp;
11881
11723 if (set->nodeTab[i] == NULL) 11882 if (set->nodeTab[i] == NULL)
11724 continue; 11883 continue;
11725 11884
11726 contextNode = set->nodeTab[i]; 11885 contextNode = set->nodeTab[i];
11727 xpctxt->node = contextNode; 11886 xpctxt->node = contextNode;
11728 xpctxt->contextSize = contextSize; 11887 xpctxt->contextSize = contextSize;
11729 xpctxt->proximityPosition = ++contextPos; 11888 xpctxt->proximityPosition = ++contextPos;
11730 11889
11731 /* 11890 /*
11732 * Initialize the new set. 11891 * Initialize the new set.
11733 * Also set the xpath document in case things like 11892 * Also set the xpath document in case things like
11734 * key() evaluation are attempted on the predicate 11893 * key() evaluation are attempted on the predicate
11735 */ 11894 */
11736 if ((contextNode->type != XML_NAMESPACE_DECL) && 11895 if ((contextNode->type != XML_NAMESPACE_DECL) &&
11737 (contextNode->doc != NULL)) 11896 (contextNode->doc != NULL))
11738 xpctxt->doc = contextNode->doc; 11897 xpctxt->doc = contextNode->doc;
11739 /* 11898 /*
11740 * Evaluate the predicate expression with 1 context node 11899 * Evaluate the predicate expression with 1 context node
11741 * at a time; this node is packaged into a node set; this 11900 * at a time; this node is packaged into a node set; this
11742 * node set is handed over to the evaluation mechanism. 11901 * node set is handed over to the evaluation mechanism.
11743 */ 11902 */
11744 if (contextObj == NULL) 11903 if (contextObj == NULL)
11745 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode); 11904 contextObj = xmlXPathCacheNewNodeSet(xpctxt, contextNode);
11746 » else 11905 » else {
11747 » » xmlXPathNodeSetAddUnique(contextObj->nodesetval, 11906 » » if (xmlXPathNodeSetAddUnique(contextObj->nodesetval,
11748 » » contextNode); 11907 » » contextNode) < 0) {
11908 » » ctxt->error = XPATH_MEMORY_ERROR;
11909 » » goto evaluation_exit;
11910 » » }
11911 » }
11749 11912
11913 frame = xmlXPathSetFrame(ctxt);
11750 valuePush(ctxt, contextObj); 11914 valuePush(ctxt, contextObj);
11751 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1); 11915 res = xmlXPathCompOpEvalToBoolean(ctxt, exprOp, 1);
11916 tmp = valuePop(ctxt);
11917 xmlXPathPopFrame(ctxt, frame);
11752 11918
11753 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) { 11919 if ((ctxt->error != XPATH_EXPRESSION_OK) || (res == -1)) {
11754 xmlXPathObjectPtr tmp;
11755 /* pop the result if any */
11756 tmp = valuePop(ctxt);
11757 while (tmp != contextObj) { 11920 while (tmp != contextObj) {
11758 /* 11921 /*
11759 * Free up the result 11922 * Free up the result
11760 * then pop off contextObj, which will be freed later 11923 * then pop off contextObj, which will be freed later
11761 */ 11924 */
11762 xmlXPathReleaseObject(xpctxt, tmp); 11925 xmlXPathReleaseObject(xpctxt, tmp);
11763 tmp = valuePop(ctxt); 11926 tmp = valuePop(ctxt);
11764 } 11927 }
11765 goto evaluation_error; 11928 goto evaluation_error;
11766 } 11929 }
11930 /* push the result back onto the stack */
11931 valuePush(ctxt, tmp);
11767 11932
11768 if (res) 11933 if (res)
11769 pos++; 11934 pos++;
11770 11935
11771 if (res && (pos >= minPos) && (pos <= maxPos)) { 11936 if (res && (pos >= minPos) && (pos <= maxPos)) {
11772 /* 11937 /*
11773 * Fits in the requested range. 11938 * Fits in the requested range.
11774 */ 11939 */
11775 newContextSize++; 11940 newContextSize++;
11776 if (minPos == maxPos) { 11941 if (minPos == maxPos) {
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
11908 static int 12073 static int
11909 xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, 12074 xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
11910 xmlXPathStepOpPtr op, 12075 xmlXPathStepOpPtr op,
11911 xmlNodePtr * first, xmlNodePtr * last, 12076 xmlNodePtr * first, xmlNodePtr * last,
11912 int toBool) 12077 int toBool)
11913 { 12078 {
11914 12079
11915 #define XP_TEST_HIT \ 12080 #define XP_TEST_HIT \
11916 if (hasAxisRange != 0) { \ 12081 if (hasAxisRange != 0) { \
11917 if (++pos == maxPos) { \ 12082 if (++pos == maxPos) { \
11918 » addNode(seq, cur); \ 12083 » if (addNode(seq, cur) < 0) \
11919 » goto axis_range_end; } \ 12084 » ctxt->error = XPATH_MEMORY_ERROR; \
12085 » goto axis_range_end; } \
11920 } else { \ 12086 } else { \
11921 » addNode(seq, cur); \ 12087 » if (addNode(seq, cur) < 0) \
12088 » ctxt->error = XPATH_MEMORY_ERROR; \
11922 if (breakOnFirstHit) goto first_hit; } 12089 if (breakOnFirstHit) goto first_hit; }
11923 12090
11924 #define XP_TEST_HIT_NS \ 12091 #define XP_TEST_HIT_NS \
11925 if (hasAxisRange != 0) { \ 12092 if (hasAxisRange != 0) { \
11926 if (++pos == maxPos) { \ 12093 if (++pos == maxPos) { \
11927 hasNsNodes = 1; \ 12094 hasNsNodes = 1; \
11928 » xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur); \ 12095 » if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
12096 » ctxt->error = XPATH_MEMORY_ERROR; \
11929 goto axis_range_end; } \ 12097 goto axis_range_end; } \
11930 } else { \ 12098 } else { \
11931 hasNsNodes = 1; \ 12099 hasNsNodes = 1; \
11932 » xmlXPathNodeSetAddNs(seq, \ 12100 » if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
11933 » xpctxt->node, (xmlNsPtr) cur); \ 12101 » ctxt->error = XPATH_MEMORY_ERROR; \
11934 if (breakOnFirstHit) goto first_hit; } 12102 if (breakOnFirstHit) goto first_hit; }
11935 12103
11936 xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value; 12104 xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
11937 xmlXPathTestVal test = (xmlXPathTestVal) op->value2; 12105 xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
11938 xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3; 12106 xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
11939 const xmlChar *prefix = op->value4; 12107 const xmlChar *prefix = op->value4;
11940 const xmlChar *name = op->value5; 12108 const xmlChar *name = op->value5;
11941 const xmlChar *URI = NULL; 12109 const xmlChar *URI = NULL;
11942 12110
11943 #ifdef DEBUG_STEP 12111 #ifdef DEBUG_STEP
11944 int nbMatches = 0, prevMatches = 0; 12112 int nbMatches = 0, prevMatches = 0;
11945 #endif 12113 #endif
11946 int total = 0, hasNsNodes = 0; 12114 int total = 0, hasNsNodes = 0;
11947 /* The popped object holding the context nodes */ 12115 /* The popped object holding the context nodes */
11948 xmlXPathObjectPtr obj; 12116 xmlXPathObjectPtr obj;
11949 /* The set of context nodes for the node tests */ 12117 /* The set of context nodes for the node tests */
11950 xmlNodeSetPtr contextSeq; 12118 xmlNodeSetPtr contextSeq;
11951 int contextIdx; 12119 int contextIdx;
11952 xmlNodePtr contextNode; 12120 xmlNodePtr contextNode;
11953 /* The context node for a compound traversal */
11954 xmlNodePtr outerContextNode;
11955 /* The final resulting node set wrt to all context nodes */ 12121 /* The final resulting node set wrt to all context nodes */
11956 xmlNodeSetPtr outSeq; 12122 xmlNodeSetPtr outSeq;
11957 /* 12123 /*
11958 * The temporary resulting node set wrt 1 context node. 12124 * The temporary resulting node set wrt 1 context node.
11959 * Used to feed predicate evaluation. 12125 * Used to feed predicate evaluation.
11960 */ 12126 */
11961 xmlNodeSetPtr seq; 12127 xmlNodeSetPtr seq;
11962 xmlNodePtr cur; 12128 xmlNodePtr cur;
11963 /* First predicate operator */ 12129 /* First predicate operator */
11964 xmlXPathStepOpPtr predOp; 12130 xmlXPathStepOpPtr predOp;
11965 int maxPos; /* The requested position() (when a "[n]" predicate) */ 12131 int maxPos; /* The requested position() (when a "[n]" predicate) */
11966 int hasPredicateRange, hasAxisRange, pos, size, newSize; 12132 int hasPredicateRange, hasAxisRange, pos, size, newSize;
11967 int breakOnFirstHit; 12133 int breakOnFirstHit;
11968 12134
11969 xmlXPathTraversalFunction next = NULL; 12135 xmlXPathTraversalFunction next = NULL;
11970 /* compound axis traversal */ 12136 int (*addNode) (xmlNodeSetPtr, xmlNodePtr);
11971 xmlXPathTraversalFunctionExt outerNext = NULL;
11972 void (*addNode) (xmlNodeSetPtr, xmlNodePtr);
11973 xmlXPathNodeSetMergeFunction mergeAndClear; 12137 xmlXPathNodeSetMergeFunction mergeAndClear;
11974 xmlNodePtr oldContextNode; 12138 xmlNodePtr oldContextNode;
11975 xmlXPathContextPtr xpctxt = ctxt->context; 12139 xmlXPathContextPtr xpctxt = ctxt->context;
11976 12140
11977 12141
11978 CHECK_TYPE0(XPATH_NODESET); 12142 CHECK_TYPE0(XPATH_NODESET);
11979 obj = valuePop(ctxt); 12143 obj = valuePop(ctxt);
11980 /* 12144 /*
11981 * Setup namespaces. 12145 * Setup namespaces.
11982 */ 12146 */
(...skipping 28 matching lines...) Expand all
12011 next = xmlXPathNextAncestorOrSelf; 12175 next = xmlXPathNextAncestorOrSelf;
12012 break; 12176 break;
12013 case AXIS_ATTRIBUTE: 12177 case AXIS_ATTRIBUTE:
12014 first = NULL; 12178 first = NULL;
12015 last = NULL; 12179 last = NULL;
12016 next = xmlXPathNextAttribute; 12180 next = xmlXPathNextAttribute;
12017 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; 12181 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
12018 break; 12182 break;
12019 case AXIS_CHILD: 12183 case AXIS_CHILD:
12020 last = NULL; 12184 last = NULL;
12021 if (op->rewriteType == XP_REWRITE_DOS_CHILD_ELEM) {
12022 /*
12023 * This iterator will give us only nodes which can
12024 * hold element nodes.
12025 */
12026 outerNext = xmlXPathNextDescendantOrSelfElemParent;
12027 }
12028 if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) && 12185 if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) &&
12029 (type == NODE_TYPE_NODE)) 12186 (type == NODE_TYPE_NODE))
12030 { 12187 {
12031 /* 12188 /*
12032 * Optimization if an element node type is 'element'. 12189 * Optimization if an element node type is 'element'.
12033 */ 12190 */
12034 next = xmlXPathNextChildElement; 12191 next = xmlXPathNextChildElement;
12035 } else 12192 } else
12036 next = xmlXPathNextChild; 12193 next = xmlXPathNextChild;
12037 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls; 12194 mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
12147 * - For other axes, the principal node type is element. 12304 * - For other axes, the principal node type is element.
12148 * 12305 *
12149 * A node test * is true for any node of the 12306 * A node test * is true for any node of the
12150 * principal node type. For example, child::* will 12307 * principal node type. For example, child::* will
12151 * select all element children of the context node 12308 * select all element children of the context node
12152 */ 12309 */
12153 oldContextNode = xpctxt->node; 12310 oldContextNode = xpctxt->node;
12154 addNode = xmlXPathNodeSetAddUnique; 12311 addNode = xmlXPathNodeSetAddUnique;
12155 outSeq = NULL; 12312 outSeq = NULL;
12156 seq = NULL; 12313 seq = NULL;
12157 outerContextNode = NULL;
12158 contextNode = NULL; 12314 contextNode = NULL;
12159 contextIdx = 0; 12315 contextIdx = 0;
12160 12316
12161 12317
12162 while ((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) { 12318 while (((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) &&
12163 » if (outerNext != NULL) { 12319 (ctxt->error == XPATH_EXPRESSION_OK)) {
12164 » /* 12320 » xpctxt->node = contextSeq->nodeTab[contextIdx++];
12165 » * This is a compound traversal.
12166 » */
12167 » if (contextNode == NULL) {
12168 » » /*
12169 » » * Set the context for the outer traversal.
12170 » » */
12171 » » outerContextNode = contextSeq->nodeTab[contextIdx++];
12172 » » contextNode = outerNext(NULL, outerContextNode);
12173 » } else
12174 » » contextNode = outerNext(contextNode, outerContextNode);
12175 » if (contextNode == NULL)
12176 » » continue;
12177 » /*
12178 » * Set the context for the main traversal.
12179 » */
12180 » xpctxt->node = contextNode;
12181 » } else
12182 » xpctxt->node = contextSeq->nodeTab[contextIdx++];
12183 12321
12184 if (seq == NULL) { 12322 if (seq == NULL) {
12185 seq = xmlXPathNodeSetCreate(NULL); 12323 seq = xmlXPathNodeSetCreate(NULL);
12186 if (seq == NULL) { 12324 if (seq == NULL) {
12187 total = 0; 12325 total = 0;
12188 goto error; 12326 goto error;
12189 } 12327 }
12190 } 12328 }
12191 /* 12329 /*
12192 * Traverse the axis and test the nodes. 12330 * Traverse the axis and test the nodes.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
12280 if ((cur->type == XML_PI_NODE) && 12418 if ((cur->type == XML_PI_NODE) &&
12281 ((name == NULL) || xmlStrEqual(name, cur->name))) 12419 ((name == NULL) || xmlStrEqual(name, cur->name)))
12282 { 12420 {
12283 XP_TEST_HIT 12421 XP_TEST_HIT
12284 } 12422 }
12285 break; 12423 break;
12286 case NODE_TEST_ALL: 12424 case NODE_TEST_ALL:
12287 if (axis == AXIS_ATTRIBUTE) { 12425 if (axis == AXIS_ATTRIBUTE) {
12288 if (cur->type == XML_ATTRIBUTE_NODE) 12426 if (cur->type == XML_ATTRIBUTE_NODE)
12289 { 12427 {
12290 » » » XP_TEST_HIT 12428 if (prefix == NULL)
12429 » » » {
12430 » » » » XP_TEST_HIT
12431 } else if ((cur->ns != NULL) &&
12432 » » » » (xmlStrEqual(URI, cur->ns->href)))
12433 » » » {
12434 » » » » XP_TEST_HIT
12435 }
12291 } 12436 }
12292 } else if (axis == AXIS_NAMESPACE) { 12437 } else if (axis == AXIS_NAMESPACE) {
12293 if (cur->type == XML_NAMESPACE_DECL) 12438 if (cur->type == XML_NAMESPACE_DECL)
12294 { 12439 {
12295 XP_TEST_HIT_NS 12440 XP_TEST_HIT_NS
12296 } 12441 }
12297 } else { 12442 } else {
12298 if (cur->type == XML_ELEMENT_NODE) { 12443 if (cur->type == XML_ELEMENT_NODE) {
12299 if (prefix == NULL) 12444 if (prefix == NULL)
12300 { 12445 {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
12370 { 12515 {
12371 XP_TEST_HIT_NS 12516 XP_TEST_HIT_NS
12372 } 12517 }
12373 } 12518 }
12374 break; 12519 break;
12375 default: 12520 default:
12376 break; 12521 break;
12377 } 12522 }
12378 break; 12523 break;
12379 } /* switch(test) */ 12524 } /* switch(test) */
12380 } while (cur != NULL); 12525 } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK));
12381 12526
12382 goto apply_predicates; 12527 goto apply_predicates;
12383 12528
12384 axis_range_end: /* ----------------------------------------------------- */ 12529 axis_range_end: /* ----------------------------------------------------- */
12385 /* 12530 /*
12386 * We have a "/foo[n]", and position() = n was reached. 12531 * We have a "/foo[n]", and position() = n was reached.
12387 * Note that we can have as well "/foo/::parent::foo[1]", so 12532 * Note that we can have as well "/foo/::parent::foo[1]", so
12388 * a duplicate-aware merge is still needed. 12533 * a duplicate-aware merge is still needed.
12389 * Merge with the result. 12534 * Merge with the result.
12390 */ 12535 */
(...skipping 20 matching lines...) Expand all
12411 } else 12556 } else
12412 outSeq = mergeAndClear(outSeq, seq, 0); 12557 outSeq = mergeAndClear(outSeq, seq, 0);
12413 break; 12558 break;
12414 12559
12415 #ifdef DEBUG_STEP 12560 #ifdef DEBUG_STEP
12416 if (seq != NULL) 12561 if (seq != NULL)
12417 nbMatches += seq->nodeNr; 12562 nbMatches += seq->nodeNr;
12418 #endif 12563 #endif
12419 12564
12420 apply_predicates: /* --------------------------------------------------- */ 12565 apply_predicates: /* --------------------------------------------------- */
12566 if (ctxt->error != XPATH_EXPRESSION_OK)
12567 goto error;
12568
12421 /* 12569 /*
12422 * Apply predicates. 12570 * Apply predicates.
12423 */ 12571 */
12424 if ((predOp != NULL) && (seq->nodeNr > 0)) { 12572 if ((predOp != NULL) && (seq->nodeNr > 0)) {
12425 /* 12573 /*
12426 * E.g. when we have a "/foo[some expression][n]". 12574 * E.g. when we have a "/foo[some expression][n]".
12427 » */» 12575 » */
12428 /* 12576 /*
12429 * QUESTION TODO: The old predicate evaluation took into 12577 * QUESTION TODO: The old predicate evaluation took into
12430 * account location-sets. 12578 * account location-sets.
12431 * (E.g. ctxt->value->type == XPATH_LOCATIONSET) 12579 * (E.g. ctxt->value->type == XPATH_LOCATIONSET)
12432 * Do we expect such a set here? 12580 * Do we expect such a set here?
12433 * All what I learned now from the evaluation semantics 12581 * All what I learned now from the evaluation semantics
12434 * does not indicate that a location-set will be processed 12582 * does not indicate that a location-set will be processed
12435 * here, so this looks OK. 12583 * here, so this looks OK.
12436 » */» 12584 » */
12437 /* 12585 /*
12438 * Iterate over all predicates, starting with the outermost 12586 * Iterate over all predicates, starting with the outermost
12439 * predicate. 12587 * predicate.
12440 * TODO: Problem: we cannot execute the inner predicates first 12588 * TODO: Problem: we cannot execute the inner predicates first
12441 * since we cannot go back *up* the operator tree! 12589 * since we cannot go back *up* the operator tree!
12442 * Options we have: 12590 * Options we have:
12443 * 1) Use of recursive functions (like is it currently done 12591 * 1) Use of recursive functions (like is it currently done
12444 * via xmlXPathCompOpEval()) 12592 * via xmlXPathCompOpEval())
12445 * 2) Add a predicate evaluation information stack to the 12593 * 2) Add a predicate evaluation information stack to the
12446 * context struct 12594 * context struct
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
12919 * Run the evaluation with a node list made of a 13067 * Run the evaluation with a node list made of a
12920 * single item in the nodelocset. 13068 * single item in the nodelocset.
12921 */ 13069 */
12922 ctxt->context->node = oldlocset->locTab[i]->user; 13070 ctxt->context->node = oldlocset->locTab[i]->user;
12923 ctxt->context->contextSize = oldlocset->locNr; 13071 ctxt->context->contextSize = oldlocset->locNr;
12924 ctxt->context->proximityPosition = i + 1; 13072 ctxt->context->proximityPosition = i + 1;
12925 if (tmp == NULL) { 13073 if (tmp == NULL) {
12926 tmp = xmlXPathCacheNewNodeSet(ctxt->context, 13074 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
12927 ctxt->context->node); 13075 ctxt->context->node);
12928 } else { 13076 } else {
12929 » » xmlXPathNodeSetAddUnique(tmp->nodesetval, 13077 » » if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
12930 » » ctxt->context->node); 13078 » » ctxt->context->node) < 0) {
13079 » » ctxt->error = XPATH_MEMORY_ERROR;
13080 » » }
12931 } 13081 }
12932 valuePush(ctxt, tmp); 13082 valuePush(ctxt, tmp);
12933 if (op->ch2 != -1) 13083 if (op->ch2 != -1)
12934 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); 13084 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
12935 if (ctxt->error != XPATH_EXPRESSION_OK) { 13085 if (ctxt->error != XPATH_EXPRESSION_OK) {
12936 xmlXPathFreeObject(obj); 13086 xmlXPathFreeObject(obj);
12937 return(0); 13087 return(0);
12938 } 13088 }
12939 /* 13089 /*
12940 * The result of the evaluation need to be tested to 13090 * The result of the evaluation need to be tested to
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
13033 * a single item in the nodeset. 13183 * a single item in the nodeset.
13034 */ 13184 */
13035 ctxt->context->node = oldset->nodeTab[i]; 13185 ctxt->context->node = oldset->nodeTab[i];
13036 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && 13186 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) &&
13037 (oldset->nodeTab[i]->doc != NULL)) 13187 (oldset->nodeTab[i]->doc != NULL))
13038 ctxt->context->doc = oldset->nodeTab[i]->doc; 13188 ctxt->context->doc = oldset->nodeTab[i]->doc;
13039 if (tmp == NULL) { 13189 if (tmp == NULL) {
13040 tmp = xmlXPathCacheNewNodeSet(ctxt->context, 13190 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
13041 ctxt->context->node); 13191 ctxt->context->node);
13042 } else { 13192 } else {
13043 » » xmlXPathNodeSetAddUnique(tmp->nodesetval, 13193 » » if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
13044 » » ctxt->context->node); 13194 » » ctxt->context->node) < 0) {
13195 » » ctxt->error = XPATH_MEMORY_ERROR;
13196 » » }
13045 } 13197 }
13046 valuePush(ctxt, tmp); 13198 valuePush(ctxt, tmp);
13047 ctxt->context->contextSize = oldset->nodeNr; 13199 ctxt->context->contextSize = oldset->nodeNr;
13048 ctxt->context->proximityPosition = i + 1; 13200 ctxt->context->proximityPosition = i + 1;
13049 if (op->ch2 != -1) 13201 if (op->ch2 != -1)
13050 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); 13202 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
13051 if (ctxt->error != XPATH_EXPRESSION_OK) { 13203 if (ctxt->error != XPATH_EXPRESSION_OK) {
13052 xmlXPathFreeNodeSet(newset); 13204 xmlXPathFreeNodeSet(newset);
13053 xmlXPathFreeObject(obj); 13205 xmlXPathFreeObject(obj);
13054 return(0); 13206 return(0);
13055 } 13207 }
13056 /* 13208 /*
13057 * The result of the evaluation needs to be tested to 13209 * The result of the evaluation needs to be tested to
13058 * decide whether the filter succeeded or not 13210 * decide whether the filter succeeded or not
13059 */ 13211 */
13060 res = valuePop(ctxt); 13212 res = valuePop(ctxt);
13061 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { 13213 if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
13062 » » xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); 13214 » » if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]) < 0)
13215 » » ctxt->error = XPATH_MEMORY_ERROR;
13063 } 13216 }
13064 /* 13217 /*
13065 * Cleanup 13218 * Cleanup
13066 */ 13219 */
13067 if (res != NULL) { 13220 if (res != NULL) {
13068 xmlXPathReleaseObject(ctxt->context, res); 13221 xmlXPathReleaseObject(ctxt->context, res);
13069 } 13222 }
13070 if (ctxt->value == tmp) { 13223 if (ctxt->value == tmp) {
13071 valuePop(ctxt); 13224 valuePop(ctxt);
13072 /* 13225 /*
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
13361 return(0); 13514 return(0);
13362 } 13515 }
13363 valuePush(ctxt, val); 13516 valuePush(ctxt, val);
13364 } 13517 }
13365 return (total); 13518 return (total);
13366 } 13519 }
13367 case XPATH_OP_FUNCTION:{ 13520 case XPATH_OP_FUNCTION:{
13368 xmlXPathFunction func; 13521 xmlXPathFunction func;
13369 const xmlChar *oldFunc, *oldFuncURI; 13522 const xmlChar *oldFunc, *oldFuncURI;
13370 int i; 13523 int i;
13524 int frame;
13371 13525
13372 if (op->ch1 != -1) 13526 frame = xmlXPathSetFrame(ctxt);
13527 if (op->ch1 != -1) {
13373 total += 13528 total +=
13374 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); 13529 xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
13375 » » if (ctxt->valueNr < op->value) { 13530 if (ctxt->error != XPATH_EXPRESSION_OK) {
13531 xmlXPathPopFrame(ctxt, frame);
13532 return (total);
13533 }
13534 }
13535 » » if (ctxt->valueNr < ctxt->valueFrame + op->value) {
13376 xmlGenericError(xmlGenericErrorContext, 13536 xmlGenericError(xmlGenericErrorContext,
13377 "xmlXPathCompOpEval: parameter error\n"); 13537 "xmlXPathCompOpEval: parameter error\n");
13378 ctxt->error = XPATH_INVALID_OPERAND; 13538 ctxt->error = XPATH_INVALID_OPERAND;
13539 xmlXPathPopFrame(ctxt, frame);
13379 return (total); 13540 return (total);
13380 } 13541 }
13381 » » for (i = 0; i < op->value; i++) 13542 » » for (i = 0; i < op->value; i++) {
13382 if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) { 13543 if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL) {
13383 xmlGenericError(xmlGenericErrorContext, 13544 xmlGenericError(xmlGenericErrorContext,
13384 "xmlXPathCompOpEval: parameter error\n"); 13545 "xmlXPathCompOpEval: parameter error\n");
13385 ctxt->error = XPATH_INVALID_OPERAND; 13546 ctxt->error = XPATH_INVALID_OPERAND;
13547 xmlXPathPopFrame(ctxt, frame);
13386 return (total); 13548 return (total);
13387 } 13549 }
13550 }
13388 if (op->cache != NULL) 13551 if (op->cache != NULL)
13389 XML_CAST_FPTR(func) = op->cache; 13552 XML_CAST_FPTR(func) = op->cache;
13390 else { 13553 else {
13391 const xmlChar *URI = NULL; 13554 const xmlChar *URI = NULL;
13392 13555
13393 if (op->value5 == NULL) 13556 if (op->value5 == NULL)
13394 func = 13557 func =
13395 xmlXPathFunctionLookup(ctxt->context, 13558 xmlXPathFunctionLookup(ctxt->context,
13396 op->value4); 13559 op->value4);
13397 else { 13560 else {
13398 URI = xmlXPathNsLookup(ctxt->context, op->value5); 13561 URI = xmlXPathNsLookup(ctxt->context, op->value5);
13399 if (URI == NULL) { 13562 if (URI == NULL) {
13400 xmlGenericError(xmlGenericErrorContext, 13563 xmlGenericError(xmlGenericErrorContext,
13401 "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n", 13564 "xmlXPathCompOpEval: function %s bound to undefined prefix %s\n",
13402 (char *)op->value4, (char *)op->value5); 13565 (char *)op->value4, (char *)op->value5);
13566 xmlXPathPopFrame(ctxt, frame);
13403 ctxt->error = XPATH_UNDEF_PREFIX_ERROR; 13567 ctxt->error = XPATH_UNDEF_PREFIX_ERROR;
13404 return (total); 13568 return (total);
13405 } 13569 }
13406 func = xmlXPathFunctionLookupNS(ctxt->context, 13570 func = xmlXPathFunctionLookupNS(ctxt->context,
13407 op->value4, URI); 13571 op->value4, URI);
13408 } 13572 }
13409 if (func == NULL) { 13573 if (func == NULL) {
13410 xmlGenericError(xmlGenericErrorContext, 13574 xmlGenericError(xmlGenericErrorContext,
13411 "xmlXPathCompOpEval: function %s not found\n", 13575 "xmlXPathCompOpEval: function %s not found\n",
13412 (char *)op->value4); 13576 (char *)op->value4);
13413 XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR); 13577 XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
13414 } 13578 }
13415 op->cache = XML_CAST_FPTR(func); 13579 op->cache = XML_CAST_FPTR(func);
13416 op->cacheURI = (void *) URI; 13580 op->cacheURI = (void *) URI;
13417 } 13581 }
13418 oldFunc = ctxt->context->function; 13582 oldFunc = ctxt->context->function;
13419 oldFuncURI = ctxt->context->functionURI; 13583 oldFuncURI = ctxt->context->functionURI;
13420 ctxt->context->function = op->value4; 13584 ctxt->context->function = op->value4;
13421 ctxt->context->functionURI = op->cacheURI; 13585 ctxt->context->functionURI = op->cacheURI;
13422 func(ctxt, op->value); 13586 func(ctxt, op->value);
13423 ctxt->context->function = oldFunc; 13587 ctxt->context->function = oldFunc;
13424 ctxt->context->functionURI = oldFuncURI; 13588 ctxt->context->functionURI = oldFuncURI;
13589 xmlXPathPopFrame(ctxt, frame);
13425 return (total); 13590 return (total);
13426 } 13591 }
13427 case XPATH_OP_ARG: 13592 case XPATH_OP_ARG:
13428 bakd = ctxt->context->doc; 13593 bakd = ctxt->context->doc;
13429 bak = ctxt->context->node; 13594 bak = ctxt->context->node;
13430 pp = ctxt->context->proximityPosition; 13595 pp = ctxt->context->proximityPosition;
13431 cs = ctxt->context->contextSize; 13596 cs = ctxt->context->contextSize;
13432 if (op->ch1 != -1) 13597 if (op->ch1 != -1) {
13433 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]); 13598 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
13434 » ctxt->context->contextSize = cs; 13599 ctxt->context->contextSize = cs;
13435 » ctxt->context->proximityPosition = pp; 13600 ctxt->context->proximityPosition = pp;
13436 » ctxt->context->node = bak; 13601 ctxt->context->node = bak;
13437 » ctxt->context->doc = bakd; 13602 ctxt->context->doc = bakd;
13438 » CHECK_ERROR0; 13603 » CHECK_ERROR0;
13604 }
13439 if (op->ch2 != -1) { 13605 if (op->ch2 != -1) {
13440 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]); 13606 total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
13441 » ctxt->context->doc = bakd; 13607 ctxt->context->contextSize = cs;
13442 » ctxt->context->node = bak; 13608 ctxt->context->proximityPosition = pp;
13609 ctxt->context->node = bak;
13610 ctxt->context->doc = bakd;
13443 CHECK_ERROR0; 13611 CHECK_ERROR0;
13444 } 13612 }
13445 return (total); 13613 return (total);
13446 case XPATH_OP_PREDICATE: 13614 case XPATH_OP_PREDICATE:
13447 case XPATH_OP_FILTER:{ 13615 case XPATH_OP_FILTER:{
13448 xmlXPathObjectPtr res; 13616 xmlXPathObjectPtr res;
13449 xmlXPathObjectPtr obj, tmp; 13617 xmlXPathObjectPtr obj, tmp;
13450 xmlNodeSetPtr newset = NULL; 13618 xmlNodeSetPtr newset = NULL;
13451 xmlNodeSetPtr oldset; 13619 xmlNodeSetPtr oldset;
13452 xmlNodePtr oldnode; 13620 xmlNodePtr oldnode;
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
13724 * a single item in the nodeset. 13892 * a single item in the nodeset.
13725 */ 13893 */
13726 ctxt->context->node = oldset->nodeTab[i]; 13894 ctxt->context->node = oldset->nodeTab[i];
13727 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) && 13895 if ((oldset->nodeTab[i]->type != XML_NAMESPACE_DECL) &&
13728 (oldset->nodeTab[i]->doc != NULL)) 13896 (oldset->nodeTab[i]->doc != NULL))
13729 ctxt->context->doc = oldset->nodeTab[i]->doc; 13897 ctxt->context->doc = oldset->nodeTab[i]->doc;
13730 if (tmp == NULL) { 13898 if (tmp == NULL) {
13731 tmp = xmlXPathCacheNewNodeSet(ctxt->context, 13899 tmp = xmlXPathCacheNewNodeSet(ctxt->context,
13732 ctxt->context->node); 13900 ctxt->context->node);
13733 } else { 13901 } else {
13734 » » » xmlXPathNodeSetAddUnique(tmp->nodesetval, 13902 » » » if (xmlXPathNodeSetAddUnique(tmp->nodesetval,
13735 » » » » ctxt->context->node); 13903 » » » » ctxt->context->node) < 0) {
13904 » » » » ctxt->error = XPATH_MEMORY_ERROR;
13905 » » » }
13736 } 13906 }
13737 valuePush(ctxt, tmp); 13907 valuePush(ctxt, tmp);
13738 ctxt->context->contextSize = oldset->nodeNr; 13908 ctxt->context->contextSize = oldset->nodeNr;
13739 ctxt->context->proximityPosition = i + 1; 13909 ctxt->context->proximityPosition = i + 1;
13740 /* 13910 /*
13741 * Evaluate the predicate against the context node. 13911 * Evaluate the predicate against the context node.
13742 * Can/should we optimize position() predicates 13912 * Can/should we optimize position() predicates
13743 * here (e.g. "[1]")? 13913 * here (e.g. "[1]")?
13744 */ 13914 */
13745 if (op->ch2 != -1) 13915 if (op->ch2 != -1)
13746 total += 13916 total +=
13747 xmlXPathCompOpEval(ctxt, 13917 xmlXPathCompOpEval(ctxt,
13748 &comp->steps[op->ch2]); 13918 &comp->steps[op->ch2]);
13749 if (ctxt->error != XPATH_EXPRESSION_OK) { 13919 if (ctxt->error != XPATH_EXPRESSION_OK) {
13750 xmlXPathFreeNodeSet(newset); 13920 xmlXPathFreeNodeSet(newset);
13751 xmlXPathFreeObject(obj); 13921 xmlXPathFreeObject(obj);
13752 return(0); 13922 return(0);
13753 } 13923 }
13754 13924
13755 /* 13925 /*
13756 * The result of the evaluation needs to be tested to 13926 * The result of the evaluation needs to be tested to
13757 * decide whether the filter succeeded or not 13927 * decide whether the filter succeeded or not
13758 */ 13928 */
13759 /* 13929 /*
13760 * OPTIMIZE TODO: Can we use 13930 * OPTIMIZE TODO: Can we use
13761 * xmlXPathNodeSetAdd*Unique()* instead? 13931 * xmlXPathNodeSetAdd*Unique()* instead?
13762 */ 13932 */
13763 res = valuePop(ctxt); 13933 res = valuePop(ctxt);
13764 if (xmlXPathEvaluatePredicateResult(ctxt, res)) { 13934 if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
13765 xmlXPathNodeSetAdd(newset, oldset->nodeTab[i]); 13935 if (xmlXPathNodeSetAdd(newset, oldset->nodeTab[i])
13936 » » » < 0)
13937 » » » » ctxt->error = XPATH_MEMORY_ERROR;
13766 } 13938 }
13767 13939
13768 /* 13940 /*
13769 * Cleanup 13941 * Cleanup
13770 */ 13942 */
13771 if (res != NULL) { 13943 if (res != NULL) {
13772 xmlXPathReleaseObject(ctxt->context, res); 13944 xmlXPathReleaseObject(ctxt->context, res);
13773 } 13945 }
13774 if (ctxt->value == tmp) { 13946 if (ctxt->value == tmp) {
13775 valuePop(ctxt); 13947 valuePop(ctxt);
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
13971 ctxt->context->node = NULL; 14143 ctxt->context->node = NULL;
13972 ctxt->context->contextSize = -1; 14144 ctxt->context->contextSize = -1;
13973 ctxt->context->proximityPosition = -1; 14145 ctxt->context->proximityPosition = -1;
13974 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset)); 14146 valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
13975 return (total); 14147 return (total);
13976 } 14148 }
13977 #endif /* LIBXML_XPTR_ENABLED */ 14149 #endif /* LIBXML_XPTR_ENABLED */
13978 } 14150 }
13979 xmlGenericError(xmlGenericErrorContext, 14151 xmlGenericError(xmlGenericErrorContext,
13980 "XPath: unknown precompiled operation %d\n", op->op); 14152 "XPath: unknown precompiled operation %d\n", op->op);
14153 ctxt->error = XPATH_INVALID_OPERAND;
13981 return (total); 14154 return (total);
13982 } 14155 }
13983 14156
13984 /** 14157 /**
13985 * xmlXPathCompOpEvalToBoolean: 14158 * xmlXPathCompOpEvalToBoolean:
13986 * @ctxt: the XPath parser context 14159 * @ctxt: the XPath parser context
13987 * 14160 *
13988 * Evaluates if the expression evaluates to true. 14161 * Evaluates if the expression evaluates to true.
13989 * 14162 *
13990 * Returns 1 if true, 0 if false and -1 on API or internal errors. 14163 * Returns 1 if true, 0 if false and -1 on API or internal errors.
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
14117 14290
14118 /* 14291 /*
14119 * handle the special cases of "/" amd "." being matched 14292 * handle the special cases of "/" amd "." being matched
14120 */ 14293 */
14121 if (min_depth == 0) { 14294 if (min_depth == 0) {
14122 if (from_root) { 14295 if (from_root) {
14123 /* Select "/" */ 14296 /* Select "/" */
14124 if (toBool) 14297 if (toBool)
14125 return(1); 14298 return(1);
14126 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, 14299 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
14127 » » (xmlNodePtr) ctxt->doc); 14300 » » (xmlNodePtr) ctxt->doc);
14128 } else { 14301 } else {
14129 /* Select "self::node()" */ 14302 /* Select "self::node()" */
14130 if (toBool) 14303 if (toBool)
14131 return(1); 14304 return(1);
14132 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node); 14305 xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, ctxt->node);
14133 } 14306 }
14134 } 14307 }
14135 if (max_depth == 0) { 14308 if (max_depth == 0) {
14136 return(0); 14309 return(0);
14137 } 14310 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
14210 } else if (eval_all_nodes) 14383 } else if (eval_all_nodes)
14211 ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type); 14384 ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type);
14212 else 14385 else
14213 break; 14386 break;
14214 14387
14215 if (ret < 0) { 14388 if (ret < 0) {
14216 /* NOP. */ 14389 /* NOP. */
14217 } else if (ret == 1) { 14390 } else if (ret == 1) {
14218 if (toBool) 14391 if (toBool)
14219 goto return_1; 14392 goto return_1;
14220 » » xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur); 14393 » » if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur)
14394 » » < 0) {
14395 » » » ctxt->lastError.domain = XML_FROM_XPATH;
14396 » » » ctxt->lastError.code = XML_ERR_NO_MEMORY;
14397 » » }
14221 } 14398 }
14222 if ((cur->children == NULL) || (depth >= max_depth)) { 14399 if ((cur->children == NULL) || (depth >= max_depth)) {
14223 ret = xmlStreamPop(patstream); 14400 ret = xmlStreamPop(patstream);
14224 while (cur->next != NULL) { 14401 while (cur->next != NULL) {
14225 cur = cur->next; 14402 cur = cur->next;
14226 if ((cur->type != XML_ENTITY_DECL) && 14403 if ((cur->type != XML_ENTITY_DECL) &&
14227 (cur->type != XML_DTD_NODE)) 14404 (cur->type != XML_DTD_NODE))
14228 goto next_node; 14405 goto next_node;
14229 } 14406 }
14230 } 14407 }
14231 default: 14408 default:
14232 break; 14409 break;
14233 } 14410 }
14234 14411
14235 scan_children: 14412 scan_children:
14413 if (cur->type == XML_NAMESPACE_DECL) break;
14236 if ((cur->children != NULL) && (depth < max_depth)) { 14414 if ((cur->children != NULL) && (depth < max_depth)) {
14237 /* 14415 /*
14238 * Do not descend on entities declarations 14416 * Do not descend on entities declarations
14239 */ 14417 */
14240 if (cur->children->type != XML_ENTITY_DECL) { 14418 if (cur->children->type != XML_ENTITY_DECL) {
14241 cur = cur->children; 14419 cur = cur->children;
14242 depth++; 14420 depth++;
14243 /* 14421 /*
14244 * Skip DTDs 14422 * Skip DTDs
14245 */ 14423 */
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
14318 /* Allocate the value stack */ 14496 /* Allocate the value stack */
14319 ctxt->valueTab = (xmlXPathObjectPtr *) 14497 ctxt->valueTab = (xmlXPathObjectPtr *)
14320 xmlMalloc(10 * sizeof(xmlXPathObjectPtr)); 14498 xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
14321 if (ctxt->valueTab == NULL) { 14499 if (ctxt->valueTab == NULL) {
14322 xmlXPathPErrMemory(ctxt, "creating evaluation context\n"); 14500 xmlXPathPErrMemory(ctxt, "creating evaluation context\n");
14323 xmlFree(ctxt); 14501 xmlFree(ctxt);
14324 } 14502 }
14325 ctxt->valueNr = 0; 14503 ctxt->valueNr = 0;
14326 ctxt->valueMax = 10; 14504 ctxt->valueMax = 10;
14327 ctxt->value = NULL; 14505 ctxt->value = NULL;
14506 ctxt->valueFrame = 0;
14328 } 14507 }
14329 #ifdef XPATH_STREAMING 14508 #ifdef XPATH_STREAMING
14330 if (ctxt->comp->stream) { 14509 if (ctxt->comp->stream) {
14331 int res; 14510 int res;
14332 14511
14333 if (toBool) { 14512 if (toBool) {
14334 /* 14513 /*
14335 * Evaluation to boolean result. 14514 * Evaluation to boolean result.
14336 */ 14515 */
14337 res = xmlXPathRunStreamEval(ctxt->context, 14516 res = xmlXPathRunStreamEval(ctxt->context,
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
14545 if (comp->dict) 14724 if (comp->dict)
14546 xmlDictReference(comp->dict); 14725 xmlDictReference(comp->dict);
14547 return(comp); 14726 return(comp);
14548 } 14727 }
14549 xmlFreePattern(stream); 14728 xmlFreePattern(stream);
14550 } 14729 }
14551 return(NULL); 14730 return(NULL);
14552 } 14731 }
14553 #endif /* XPATH_STREAMING */ 14732 #endif /* XPATH_STREAMING */
14554 14733
14555 static int
14556 xmlXPathCanRewriteDosExpression(xmlChar *expr)
14557 {
14558 if (expr == NULL)
14559 return(0);
14560 do {
14561 if ((*expr == '/') && (*(++expr) == '/'))
14562 return(1);
14563 } while (*expr++);
14564 return(0);
14565 }
14566 static void 14734 static void
14567 xmlXPathRewriteDOSExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op) 14735 xmlXPathOptimizeExpression(xmlXPathCompExprPtr comp, xmlXPathStepOpPtr op)
14568 { 14736 {
14569 /* 14737 /*
14570 * Try to rewrite "descendant-or-self::node()/foo" to an optimized 14738 * Try to rewrite "descendant-or-self::node()/foo" to an optimized
14571 * internal representation. 14739 * internal representation.
14572 */ 14740 */
14573 if (op->ch1 != -1) {
14574 if ((op->op == XPATH_OP_COLLECT /* 11 */) &&
14575 ((xmlXPathAxisVal) op->value == AXIS_CHILD /* 4 */) &&
14576 ((xmlXPathTestVal) op->value2 == NODE_TEST_NAME /* 5 */) &&
14577 ((xmlXPathTypeVal) op->value3 == NODE_TYPE_NODE /* 0 */))
14578 {
14579 /*
14580 * This is a "child::foo"
14581 */
14582 xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
14583 14741
14584 » if ((prevop->op == XPATH_OP_COLLECT /* 11 */) && 14742 if ((op->op == XPATH_OP_COLLECT /* 11 */) &&
14585 » » (prevop->ch1 != -1) && 14743 (op->ch1 != -1) &&
14586 » » ((xmlXPathAxisVal) prevop->value == 14744 (op->ch2 == -1 /* no predicate */))
14587 » » AXIS_DESCENDANT_OR_SELF) && 14745 {
14588 » » (prevop->ch2 == -1) && 14746 xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
14589 » » ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) && 14747
14590 » » ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE) && 14748 if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&
14591 » » (comp->steps[prevop->ch1].op == XPATH_OP_ROOT)) 14749 ((xmlXPathAxisVal) prevop->value ==
14592 » { 14750 AXIS_DESCENDANT_OR_SELF) &&
14593 » » /* 14751 (prevop->ch2 == -1) &&
14594 » » * This is a "/descendant-or-self::node()" without predicates. 14752 ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&
14595 » » * Eliminate it. 14753 ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE))
14596 » » */ 14754 {
14597 » » op->ch1 = prevop->ch1; 14755 /*
14598 » » op->rewriteType = XP_REWRITE_DOS_CHILD_ELEM; 14756 * This is a "descendant-or-self::node()" without predicates.
14599 » } 14757 * Try to eliminate it.
14758 */
14759
14760 switch ((xmlXPathAxisVal) op->value) {
14761 case AXIS_CHILD:
14762 case AXIS_DESCENDANT:
14763 /*
14764 * Convert "descendant-or-self::node()/child::" or
14765 * "descendant-or-self::node()/descendant::" to
14766 * "descendant::"
14767 */
14768 op->ch1 = prevop->ch1;
14769 op->value = AXIS_DESCENDANT;
14770 break;
14771 case AXIS_SELF:
14772 case AXIS_DESCENDANT_OR_SELF:
14773 /*
14774 * Convert "descendant-or-self::node()/self::" or
14775 * "descendant-or-self::node()/descendant-or-self::" to
14776 * to "descendant-or-self::"
14777 */
14778 op->ch1 = prevop->ch1;
14779 op->value = AXIS_DESCENDANT_OR_SELF;
14780 break;
14781 default:
14782 break;
14783 }
14600 } 14784 }
14601 if (op->ch1 != -1)
14602 xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch1]);
14603 } 14785 }
14786
14787 /* Recurse */
14788 if (op->ch1 != -1)
14789 xmlXPathOptimizeExpression(comp, &comp->steps[op->ch1]);
14604 if (op->ch2 != -1) 14790 if (op->ch2 != -1)
14605 » xmlXPathRewriteDOSExpression(comp, &comp->steps[op->ch2]); 14791 » xmlXPathOptimizeExpression(comp, &comp->steps[op->ch2]);
14606 } 14792 }
14607 14793
14608 /** 14794 /**
14609 * xmlXPathCtxtCompile: 14795 * xmlXPathCtxtCompile:
14610 * @ctxt: an XPath context 14796 * @ctxt: an XPath context
14611 * @str: the XPath expression 14797 * @str: the XPath expression
14612 * 14798 *
14613 * Compile an XPath expression 14799 * Compile an XPath expression
14614 * 14800 *
14615 * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL. 14801 * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
14653 pctxt->comp = NULL; 14839 pctxt->comp = NULL;
14654 } 14840 }
14655 xmlXPathFreeParserContext(pctxt); 14841 xmlXPathFreeParserContext(pctxt);
14656 14842
14657 if (comp != NULL) { 14843 if (comp != NULL) {
14658 comp->expr = xmlStrdup(str); 14844 comp->expr = xmlStrdup(str);
14659 #ifdef DEBUG_EVAL_COUNTS 14845 #ifdef DEBUG_EVAL_COUNTS
14660 comp->string = xmlStrdup(str); 14846 comp->string = xmlStrdup(str);
14661 comp->nb = 0; 14847 comp->nb = 0;
14662 #endif 14848 #endif
14663 » if ((comp->expr != NULL) && 14849 » if ((comp->nbStep > 1) && (comp->last >= 0)) {
14664 » (comp->nbStep > 2) && 14850 » xmlXPathOptimizeExpression(comp, &comp->steps[comp->last]);
14665 » (comp->last >= 0) &&
14666 » (xmlXPathCanRewriteDosExpression(comp->expr) == 1))
14667 » {
14668 » xmlXPathRewriteDOSExpression(comp, &comp->steps[comp->last]);
14669 } 14851 }
14670 } 14852 }
14671 return(comp); 14853 return(comp);
14672 } 14854 }
14673 14855
14674 /** 14856 /**
14675 * xmlXPathCompile: 14857 * xmlXPathCompile:
14676 * @str: the XPath expression 14858 * @str: the XPath expression
14677 * 14859 *
14678 * Compile an XPath expression 14860 * Compile an XPath expression
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
14835 if (comp != NULL) { 15017 if (comp != NULL) {
14836 if (ctxt->comp != NULL) 15018 if (ctxt->comp != NULL)
14837 xmlXPathFreeCompExpr(ctxt->comp); 15019 xmlXPathFreeCompExpr(ctxt->comp);
14838 ctxt->comp = comp; 15020 ctxt->comp = comp;
14839 if (ctxt->cur != NULL) 15021 if (ctxt->cur != NULL)
14840 while (*ctxt->cur != 0) ctxt->cur++; 15022 while (*ctxt->cur != 0) ctxt->cur++;
14841 } else 15023 } else
14842 #endif 15024 #endif
14843 { 15025 {
14844 xmlXPathCompileExpr(ctxt, 1); 15026 xmlXPathCompileExpr(ctxt, 1);
14845 /*
14846 * In this scenario the expression string will sit in ctxt->base.
14847 */
14848 if ((ctxt->error == XPATH_EXPRESSION_OK) && 15027 if ((ctxt->error == XPATH_EXPRESSION_OK) &&
14849 (ctxt->comp != NULL) && 15028 (ctxt->comp != NULL) &&
14850 » (ctxt->base != NULL) && 15029 » (ctxt->comp->nbStep > 1) &&
14851 » (ctxt->comp->nbStep > 2) && 15030 » (ctxt->comp->last >= 0))
14852 » (ctxt->comp->last >= 0) &&
14853 » (xmlXPathCanRewriteDosExpression((xmlChar *) ctxt->base) == 1))
14854 { 15031 {
14855 » xmlXPathRewriteDOSExpression(ctxt->comp, 15032 » xmlXPathOptimizeExpression(ctxt->comp,
14856 &ctxt->comp->steps[ctxt->comp->last]); 15033 &ctxt->comp->steps[ctxt->comp->last]);
14857 } 15034 }
14858 } 15035 }
14859 CHECK_ERROR; 15036 CHECK_ERROR;
14860 xmlXPathRunEval(ctxt, 0); 15037 xmlXPathRunEval(ctxt, 0);
14861 } 15038 }
14862 15039
14863 /** 15040 /**
14864 * xmlXPathEval: 15041 * xmlXPathEval:
14865 * @str: the XPath expression 15042 * @str: the XPath expression
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
14916 if (ctxt->error != XPATH_EXPRESSION_OK) { 15093 if (ctxt->error != XPATH_EXPRESSION_OK) {
14917 xmlXPathFreeObject(res); 15094 xmlXPathFreeObject(res);
14918 res = NULL; 15095 res = NULL;
14919 } 15096 }
14920 15097
14921 xmlXPathFreeParserContext(ctxt); 15098 xmlXPathFreeParserContext(ctxt);
14922 return(res); 15099 return(res);
14923 } 15100 }
14924 15101
14925 /** 15102 /**
15103 * xmlXPathSetContextNode:
15104 * @node: the node to to use as the context node
15105 * @ctx: the XPath context
15106 *
15107 * Sets 'node' as the context node. The node must be in the same
15108 * document as that associated with the context.
15109 *
15110 * Returns -1 in case of error or 0 if successful
15111 */
15112 int
15113 xmlXPathSetContextNode(xmlNodePtr node, xmlXPathContextPtr ctx) {
15114 if ((node == NULL) || (ctx == NULL))
15115 return(-1);
15116
15117 if (node->doc == ctx->doc) {
15118 ctx->node = node;
15119 return(0);
15120 }
15121 return(-1);
15122 }
15123
15124 /**
15125 * xmlXPathNodeEval:
15126 * @node: the node to to use as the context node
15127 * @str: the XPath expression
15128 * @ctx: the XPath context
15129 *
15130 * Evaluate the XPath Location Path in the given context. The node 'node'
15131 * is set as the context node. The context node is not restored.
15132 *
15133 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
15134 * the caller has to free the object.
15135 */
15136 xmlXPathObjectPtr
15137 xmlXPathNodeEval(xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx) {
15138 if (str == NULL)
15139 return(NULL);
15140 if (xmlXPathSetContextNode(node, ctx) < 0)
15141 return(NULL);
15142 return(xmlXPathEval(str, ctx));
15143 }
15144
15145 /**
14926 * xmlXPathEvalExpression: 15146 * xmlXPathEvalExpression:
14927 * @str: the XPath expression 15147 * @str: the XPath expression
14928 * @ctxt: the XPath context 15148 * @ctxt: the XPath context
14929 * 15149 *
14930 * Evaluate the XPath expression in the given context. 15150 * Evaluate the XPath expression in the given context.
14931 * 15151 *
14932 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL. 15152 * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
14933 * the caller has to free the object. 15153 * the caller has to free the object.
14934 */ 15154 */
14935 xmlXPathObjectPtr 15155 xmlXPathObjectPtr
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
15019 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2 0Angeles#ocean"), true()) 15239 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2 0Angeles#ocean"), true())
15020 * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia% 2FLos%20Angeles%23ocean" 15240 * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia% 2FLos%20Angeles%23ocean"
15021 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2 0Angeles#ocean"), false()) 15241 * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%2 0Angeles#ocean"), false())
15022 * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angele s%23ocean" 15242 * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angele s%23ocean"
15023 * 15243 *
15024 */ 15244 */
15025 static void 15245 static void
15026 xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) { 15246 xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
15027 xmlXPathObjectPtr str; 15247 xmlXPathObjectPtr str;
15028 int escape_reserved; 15248 int escape_reserved;
15029 xmlBufferPtr target; 15249 xmlBufPtr target;
15030 xmlChar *cptr; 15250 xmlChar *cptr;
15031 xmlChar escape[4]; 15251 xmlChar escape[4];
15032 15252
15033 CHECK_ARITY(2); 15253 CHECK_ARITY(2);
15034 15254
15035 escape_reserved = xmlXPathPopBoolean(ctxt); 15255 escape_reserved = xmlXPathPopBoolean(ctxt);
15036 15256
15037 CAST_TO_STRING; 15257 CAST_TO_STRING;
15038 str = valuePop(ctxt); 15258 str = valuePop(ctxt);
15039 15259
15040 target = xmlBufferCreate(); 15260 target = xmlBufCreate();
15041 15261
15042 escape[0] = '%'; 15262 escape[0] = '%';
15043 escape[3] = 0; 15263 escape[3] = 0;
15044 15264
15045 if (target) { 15265 if (target) {
15046 for (cptr = str->stringval; *cptr; cptr++) { 15266 for (cptr = str->stringval; *cptr; cptr++) {
15047 if ((*cptr >= 'A' && *cptr <= 'Z') || 15267 if ((*cptr >= 'A' && *cptr <= 'Z') ||
15048 (*cptr >= 'a' && *cptr <= 'z') || 15268 (*cptr >= 'a' && *cptr <= 'z') ||
15049 (*cptr >= '0' && *cptr <= '9') || 15269 (*cptr >= '0' && *cptr <= '9') ||
15050 *cptr == '-' || *cptr == '_' || *cptr == '.' || 15270 *cptr == '-' || *cptr == '_' || *cptr == '.' ||
15051 *cptr == '!' || *cptr == '~' || *cptr == '*' || 15271 *cptr == '!' || *cptr == '~' || *cptr == '*' ||
15052 *cptr == '\''|| *cptr == '(' || *cptr == ')' || 15272 *cptr == '\''|| *cptr == '(' || *cptr == ')' ||
15053 (*cptr == '%' && 15273 (*cptr == '%' &&
15054 ((cptr[1] >= 'A' && cptr[1] <= 'F') || 15274 ((cptr[1] >= 'A' && cptr[1] <= 'F') ||
15055 (cptr[1] >= 'a' && cptr[1] <= 'f') || 15275 (cptr[1] >= 'a' && cptr[1] <= 'f') ||
15056 (cptr[1] >= '0' && cptr[1] <= '9')) && 15276 (cptr[1] >= '0' && cptr[1] <= '9')) &&
15057 ((cptr[2] >= 'A' && cptr[2] <= 'F') || 15277 ((cptr[2] >= 'A' && cptr[2] <= 'F') ||
15058 (cptr[2] >= 'a' && cptr[2] <= 'f') || 15278 (cptr[2] >= 'a' && cptr[2] <= 'f') ||
15059 (cptr[2] >= '0' && cptr[2] <= '9'))) || 15279 (cptr[2] >= '0' && cptr[2] <= '9'))) ||
15060 (!escape_reserved && 15280 (!escape_reserved &&
15061 (*cptr == ';' || *cptr == '/' || *cptr == '?' || 15281 (*cptr == ';' || *cptr == '/' || *cptr == '?' ||
15062 *cptr == ':' || *cptr == '@' || *cptr == '&' || 15282 *cptr == ':' || *cptr == '@' || *cptr == '&' ||
15063 *cptr == '=' || *cptr == '+' || *cptr == '$' || 15283 *cptr == '=' || *cptr == '+' || *cptr == '$' ||
15064 *cptr == ','))) { 15284 *cptr == ','))) {
15065 » » xmlBufferAdd(target, cptr, 1); 15285 » » xmlBufAdd(target, cptr, 1);
15066 } else { 15286 } else {
15067 if ((*cptr >> 4) < 10) 15287 if ((*cptr >> 4) < 10)
15068 escape[1] = '0' + (*cptr >> 4); 15288 escape[1] = '0' + (*cptr >> 4);
15069 else 15289 else
15070 escape[1] = 'A' - 10 + (*cptr >> 4); 15290 escape[1] = 'A' - 10 + (*cptr >> 4);
15071 if ((*cptr & 0xF) < 10) 15291 if ((*cptr & 0xF) < 10)
15072 escape[2] = '0' + (*cptr & 0xF); 15292 escape[2] = '0' + (*cptr & 0xF);
15073 else 15293 else
15074 escape[2] = 'A' - 10 + (*cptr & 0xF); 15294 escape[2] = 'A' - 10 + (*cptr & 0xF);
15075 15295
15076 » » xmlBufferAdd(target, &escape[0], 3); 15296 » » xmlBufAdd(target, &escape[0], 3);
15077 } 15297 }
15078 } 15298 }
15079 } 15299 }
15080 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context, 15300 valuePush(ctxt, xmlXPathCacheNewString(ctxt->context,
15081 » xmlBufferContent(target))); 15301 » xmlBufContent(target)));
15082 xmlBufferFree(target); 15302 xmlBufFree(target);
15083 xmlXPathReleaseObject(ctxt->context, str); 15303 xmlXPathReleaseObject(ctxt->context, str);
15084 } 15304 }
15085 15305
15086 /** 15306 /**
15087 * xmlXPathRegisterAllFunctions: 15307 * xmlXPathRegisterAllFunctions:
15088 * @ctxt: the XPath context 15308 * @ctxt: the XPath context
15089 * 15309 *
15090 * Registers all default XPath functions in this context 15310 * Registers all default XPath functions in this context
15091 */ 15311 */
15092 void 15312 void
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
15148 xmlXPathTranslateFunction); 15368 xmlXPathTranslateFunction);
15149 15369
15150 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", 15370 xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
15151 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", 15371 (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
15152 xmlXPathEscapeUriFunction); 15372 xmlXPathEscapeUriFunction);
15153 } 15373 }
15154 15374
15155 #endif /* LIBXML_XPATH_ENABLED */ 15375 #endif /* LIBXML_XPATH_ENABLED */
15156 #define bottom_xpath 15376 #define bottom_xpath
15157 #include "elfgcchack.h" 15377 #include "elfgcchack.h"
OLDNEW
« no previous file with comments | « third_party/libxml/src/xmlwriter.c ('k') | third_party/libxml/src/xpointer.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698