pocjenkixx 0.30.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pocjenkixx might be problematic. Click here for more details.

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +122 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,2969 @@
1
+ /*
2
+ * xpointer.c : Code to handle XML Pointer
3
+ *
4
+ * Base implementation was made accordingly to
5
+ * W3C Candidate Recommendation 7 June 2000
6
+ * http://www.w3.org/TR/2000/CR-xptr-20000607
7
+ *
8
+ * Added support for the element() scheme described in:
9
+ * W3C Proposed Recommendation 13 November 2002
10
+ * http://www.w3.org/TR/2002/PR-xptr-element-20021113/
11
+ *
12
+ * See Copyright for the status of this software.
13
+ *
14
+ * daniel@veillard.com
15
+ */
16
+
17
+ /* To avoid EBCDIC trouble when parsing on zOS */
18
+ #if defined(__MVS__)
19
+ #pragma convert("ISO8859-1")
20
+ #endif
21
+
22
+ #define IN_LIBXML
23
+ #include "libxml.h"
24
+
25
+ /*
26
+ * TODO: better handling of error cases, the full expression should
27
+ * be parsed beforehand instead of a progressive evaluation
28
+ * TODO: Access into entities references are not supported now ...
29
+ * need a start to be able to pop out of entities refs since
30
+ * parent is the entity declaration, not the ref.
31
+ */
32
+
33
+ #include <string.h>
34
+ #include <libxml/xpointer.h>
35
+ #include <libxml/xmlmemory.h>
36
+ #include <libxml/parserInternals.h>
37
+ #include <libxml/uri.h>
38
+ #include <libxml/xpath.h>
39
+ #include <libxml/xpathInternals.h>
40
+ #include <libxml/xmlerror.h>
41
+ #include <libxml/globals.h>
42
+
43
+ #ifdef LIBXML_XPTR_ENABLED
44
+
45
+ /* Add support of the xmlns() xpointer scheme to initialize the namespaces */
46
+ #define XPTR_XMLNS_SCHEME
47
+
48
+ /* #define DEBUG_RANGES */
49
+ #ifdef DEBUG_RANGES
50
+ #ifdef LIBXML_DEBUG_ENABLED
51
+ #include <libxml/debugXML.h>
52
+ #endif
53
+ #endif
54
+
55
+ #define TODO \
56
+ xmlGenericError(xmlGenericErrorContext, \
57
+ "Unimplemented block at %s:%d\n", \
58
+ __FILE__, __LINE__);
59
+
60
+ #define STRANGE \
61
+ xmlGenericError(xmlGenericErrorContext, \
62
+ "Internal error at %s:%d\n", \
63
+ __FILE__, __LINE__);
64
+
65
+ /************************************************************************
66
+ * *
67
+ * Some factorized error routines *
68
+ * *
69
+ ************************************************************************/
70
+
71
+ /**
72
+ * xmlXPtrErrMemory:
73
+ * @extra: extra information
74
+ *
75
+ * Handle a redefinition of attribute error
76
+ */
77
+ static void
78
+ xmlXPtrErrMemory(const char *extra)
79
+ {
80
+ __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_XPOINTER,
81
+ XML_ERR_NO_MEMORY, XML_ERR_ERROR, NULL, 0, extra,
82
+ NULL, NULL, 0, 0,
83
+ "Memory allocation failed : %s\n", extra);
84
+ }
85
+
86
+ /**
87
+ * xmlXPtrErr:
88
+ * @ctxt: an XPTR evaluation context
89
+ * @extra: extra information
90
+ *
91
+ * Handle a redefinition of attribute error
92
+ */
93
+ static void LIBXML_ATTR_FORMAT(3,0)
94
+ xmlXPtrErr(xmlXPathParserContextPtr ctxt, int error,
95
+ const char * msg, const xmlChar *extra)
96
+ {
97
+ if (ctxt != NULL)
98
+ ctxt->error = error;
99
+ if ((ctxt == NULL) || (ctxt->context == NULL)) {
100
+ __xmlRaiseError(NULL, NULL, NULL,
101
+ NULL, NULL, XML_FROM_XPOINTER, error,
102
+ XML_ERR_ERROR, NULL, 0,
103
+ (const char *) extra, NULL, NULL, 0, 0,
104
+ msg, extra);
105
+ return;
106
+ }
107
+
108
+ /* cleanup current last error */
109
+ xmlResetError(&ctxt->context->lastError);
110
+
111
+ ctxt->context->lastError.domain = XML_FROM_XPOINTER;
112
+ ctxt->context->lastError.code = error;
113
+ ctxt->context->lastError.level = XML_ERR_ERROR;
114
+ ctxt->context->lastError.str1 = (char *) xmlStrdup(ctxt->base);
115
+ ctxt->context->lastError.int1 = ctxt->cur - ctxt->base;
116
+ ctxt->context->lastError.node = ctxt->context->debugNode;
117
+ if (ctxt->context->error != NULL) {
118
+ ctxt->context->error(ctxt->context->userData,
119
+ &ctxt->context->lastError);
120
+ } else {
121
+ __xmlRaiseError(NULL, NULL, NULL,
122
+ NULL, ctxt->context->debugNode, XML_FROM_XPOINTER,
123
+ error, XML_ERR_ERROR, NULL, 0,
124
+ (const char *) extra, (const char *) ctxt->base, NULL,
125
+ ctxt->cur - ctxt->base, 0,
126
+ msg, extra);
127
+ }
128
+ }
129
+
130
+ /************************************************************************
131
+ * *
132
+ * A few helper functions for child sequences *
133
+ * *
134
+ ************************************************************************/
135
+ /* xmlXPtrAdvanceNode is a private function, but used by xinclude.c */
136
+ xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur, int *level);
137
+ /**
138
+ * xmlXPtrGetArity:
139
+ * @cur: the node
140
+ *
141
+ * Returns the number of child for an element, -1 in case of error
142
+ */
143
+ static int
144
+ xmlXPtrGetArity(xmlNodePtr cur) {
145
+ int i;
146
+ if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
147
+ return(-1);
148
+ cur = cur->children;
149
+ for (i = 0;cur != NULL;cur = cur->next) {
150
+ if ((cur->type == XML_ELEMENT_NODE) ||
151
+ (cur->type == XML_DOCUMENT_NODE) ||
152
+ (cur->type == XML_HTML_DOCUMENT_NODE)) {
153
+ i++;
154
+ }
155
+ }
156
+ return(i);
157
+ }
158
+
159
+ /**
160
+ * xmlXPtrGetIndex:
161
+ * @cur: the node
162
+ *
163
+ * Returns the index of the node in its parent children list, -1
164
+ * in case of error
165
+ */
166
+ static int
167
+ xmlXPtrGetIndex(xmlNodePtr cur) {
168
+ int i;
169
+ if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
170
+ return(-1);
171
+ for (i = 1;cur != NULL;cur = cur->prev) {
172
+ if ((cur->type == XML_ELEMENT_NODE) ||
173
+ (cur->type == XML_DOCUMENT_NODE) ||
174
+ (cur->type == XML_HTML_DOCUMENT_NODE)) {
175
+ i++;
176
+ }
177
+ }
178
+ return(i);
179
+ }
180
+
181
+ /**
182
+ * xmlXPtrGetNthChild:
183
+ * @cur: the node
184
+ * @no: the child number
185
+ *
186
+ * Returns the @no'th element child of @cur or NULL
187
+ */
188
+ static xmlNodePtr
189
+ xmlXPtrGetNthChild(xmlNodePtr cur, int no) {
190
+ int i;
191
+ if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
192
+ return(cur);
193
+ cur = cur->children;
194
+ for (i = 0;i <= no;cur = cur->next) {
195
+ if (cur == NULL)
196
+ return(cur);
197
+ if ((cur->type == XML_ELEMENT_NODE) ||
198
+ (cur->type == XML_DOCUMENT_NODE) ||
199
+ (cur->type == XML_HTML_DOCUMENT_NODE)) {
200
+ i++;
201
+ if (i == no)
202
+ break;
203
+ }
204
+ }
205
+ return(cur);
206
+ }
207
+
208
+ /************************************************************************
209
+ * *
210
+ * Handling of XPointer specific types *
211
+ * *
212
+ ************************************************************************/
213
+
214
+ /**
215
+ * xmlXPtrCmpPoints:
216
+ * @node1: the first node
217
+ * @index1: the first index
218
+ * @node2: the second node
219
+ * @index2: the second index
220
+ *
221
+ * Compare two points w.r.t document order
222
+ *
223
+ * Returns -2 in case of error 1 if first point < second point, 0 if
224
+ * that's the same point, -1 otherwise
225
+ */
226
+ static int
227
+ xmlXPtrCmpPoints(xmlNodePtr node1, int index1, xmlNodePtr node2, int index2) {
228
+ if ((node1 == NULL) || (node2 == NULL))
229
+ return(-2);
230
+ /*
231
+ * a couple of optimizations which will avoid computations in most cases
232
+ */
233
+ if (node1 == node2) {
234
+ if (index1 < index2)
235
+ return(1);
236
+ if (index1 > index2)
237
+ return(-1);
238
+ return(0);
239
+ }
240
+ return(xmlXPathCmpNodes(node1, node2));
241
+ }
242
+
243
+ /**
244
+ * xmlXPtrNewPoint:
245
+ * @node: the xmlNodePtr
246
+ * @indx: the indx within the node
247
+ *
248
+ * Create a new xmlXPathObjectPtr of type point
249
+ *
250
+ * Returns the newly created object.
251
+ */
252
+ static xmlXPathObjectPtr
253
+ xmlXPtrNewPoint(xmlNodePtr node, int indx) {
254
+ xmlXPathObjectPtr ret;
255
+
256
+ if (node == NULL)
257
+ return(NULL);
258
+ if (indx < 0)
259
+ return(NULL);
260
+
261
+ ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
262
+ if (ret == NULL) {
263
+ xmlXPtrErrMemory("allocating point");
264
+ return(NULL);
265
+ }
266
+ memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
267
+ ret->type = XPATH_POINT;
268
+ ret->user = (void *) node;
269
+ ret->index = indx;
270
+ return(ret);
271
+ }
272
+
273
+ /**
274
+ * xmlXPtrRangeCheckOrder:
275
+ * @range: an object range
276
+ *
277
+ * Make sure the points in the range are in the right order
278
+ */
279
+ static void
280
+ xmlXPtrRangeCheckOrder(xmlXPathObjectPtr range) {
281
+ int tmp;
282
+ xmlNodePtr tmp2;
283
+ if (range == NULL)
284
+ return;
285
+ if (range->type != XPATH_RANGE)
286
+ return;
287
+ if (range->user2 == NULL)
288
+ return;
289
+ tmp = xmlXPtrCmpPoints(range->user, range->index,
290
+ range->user2, range->index2);
291
+ if (tmp == -1) {
292
+ tmp2 = range->user;
293
+ range->user = range->user2;
294
+ range->user2 = tmp2;
295
+ tmp = range->index;
296
+ range->index = range->index2;
297
+ range->index2 = tmp;
298
+ }
299
+ }
300
+
301
+ /**
302
+ * xmlXPtrRangesEqual:
303
+ * @range1: the first range
304
+ * @range2: the second range
305
+ *
306
+ * Compare two ranges
307
+ *
308
+ * Returns 1 if equal, 0 otherwise
309
+ */
310
+ static int
311
+ xmlXPtrRangesEqual(xmlXPathObjectPtr range1, xmlXPathObjectPtr range2) {
312
+ if (range1 == range2)
313
+ return(1);
314
+ if ((range1 == NULL) || (range2 == NULL))
315
+ return(0);
316
+ if (range1->type != range2->type)
317
+ return(0);
318
+ if (range1->type != XPATH_RANGE)
319
+ return(0);
320
+ if (range1->user != range2->user)
321
+ return(0);
322
+ if (range1->index != range2->index)
323
+ return(0);
324
+ if (range1->user2 != range2->user2)
325
+ return(0);
326
+ if (range1->index2 != range2->index2)
327
+ return(0);
328
+ return(1);
329
+ }
330
+
331
+ /**
332
+ * xmlXPtrNewRangeInternal:
333
+ * @start: the starting node
334
+ * @startindex: the start index
335
+ * @end: the ending point
336
+ * @endindex: the ending index
337
+ *
338
+ * Internal function to create a new xmlXPathObjectPtr of type range
339
+ *
340
+ * Returns the newly created object.
341
+ */
342
+ static xmlXPathObjectPtr
343
+ xmlXPtrNewRangeInternal(xmlNodePtr start, int startindex,
344
+ xmlNodePtr end, int endindex) {
345
+ xmlXPathObjectPtr ret;
346
+
347
+ /*
348
+ * Namespace nodes must be copied (see xmlXPathNodeSetDupNs).
349
+ * Disallow them for now.
350
+ */
351
+ if ((start != NULL) && (start->type == XML_NAMESPACE_DECL))
352
+ return(NULL);
353
+ if ((end != NULL) && (end->type == XML_NAMESPACE_DECL))
354
+ return(NULL);
355
+
356
+ ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
357
+ if (ret == NULL) {
358
+ xmlXPtrErrMemory("allocating range");
359
+ return(NULL);
360
+ }
361
+ memset(ret, 0, sizeof(xmlXPathObject));
362
+ ret->type = XPATH_RANGE;
363
+ ret->user = start;
364
+ ret->index = startindex;
365
+ ret->user2 = end;
366
+ ret->index2 = endindex;
367
+ return(ret);
368
+ }
369
+
370
+ /**
371
+ * xmlXPtrNewRange:
372
+ * @start: the starting node
373
+ * @startindex: the start index
374
+ * @end: the ending point
375
+ * @endindex: the ending index
376
+ *
377
+ * Create a new xmlXPathObjectPtr of type range
378
+ *
379
+ * Returns the newly created object.
380
+ */
381
+ xmlXPathObjectPtr
382
+ xmlXPtrNewRange(xmlNodePtr start, int startindex,
383
+ xmlNodePtr end, int endindex) {
384
+ xmlXPathObjectPtr ret;
385
+
386
+ if (start == NULL)
387
+ return(NULL);
388
+ if (end == NULL)
389
+ return(NULL);
390
+ if (startindex < 0)
391
+ return(NULL);
392
+ if (endindex < 0)
393
+ return(NULL);
394
+
395
+ ret = xmlXPtrNewRangeInternal(start, startindex, end, endindex);
396
+ xmlXPtrRangeCheckOrder(ret);
397
+ return(ret);
398
+ }
399
+
400
+ /**
401
+ * xmlXPtrNewRangePoints:
402
+ * @start: the starting point
403
+ * @end: the ending point
404
+ *
405
+ * Create a new xmlXPathObjectPtr of type range using 2 Points
406
+ *
407
+ * Returns the newly created object.
408
+ */
409
+ xmlXPathObjectPtr
410
+ xmlXPtrNewRangePoints(xmlXPathObjectPtr start, xmlXPathObjectPtr end) {
411
+ xmlXPathObjectPtr ret;
412
+
413
+ if (start == NULL)
414
+ return(NULL);
415
+ if (end == NULL)
416
+ return(NULL);
417
+ if (start->type != XPATH_POINT)
418
+ return(NULL);
419
+ if (end->type != XPATH_POINT)
420
+ return(NULL);
421
+
422
+ ret = xmlXPtrNewRangeInternal(start->user, start->index, end->user,
423
+ end->index);
424
+ xmlXPtrRangeCheckOrder(ret);
425
+ return(ret);
426
+ }
427
+
428
+ /**
429
+ * xmlXPtrNewRangePointNode:
430
+ * @start: the starting point
431
+ * @end: the ending node
432
+ *
433
+ * Create a new xmlXPathObjectPtr of type range from a point to a node
434
+ *
435
+ * Returns the newly created object.
436
+ */
437
+ xmlXPathObjectPtr
438
+ xmlXPtrNewRangePointNode(xmlXPathObjectPtr start, xmlNodePtr end) {
439
+ xmlXPathObjectPtr ret;
440
+
441
+ if (start == NULL)
442
+ return(NULL);
443
+ if (end == NULL)
444
+ return(NULL);
445
+ if (start->type != XPATH_POINT)
446
+ return(NULL);
447
+
448
+ ret = xmlXPtrNewRangeInternal(start->user, start->index, end, -1);
449
+ xmlXPtrRangeCheckOrder(ret);
450
+ return(ret);
451
+ }
452
+
453
+ /**
454
+ * xmlXPtrNewRangeNodePoint:
455
+ * @start: the starting node
456
+ * @end: the ending point
457
+ *
458
+ * Create a new xmlXPathObjectPtr of type range from a node to a point
459
+ *
460
+ * Returns the newly created object.
461
+ */
462
+ xmlXPathObjectPtr
463
+ xmlXPtrNewRangeNodePoint(xmlNodePtr start, xmlXPathObjectPtr end) {
464
+ xmlXPathObjectPtr ret;
465
+
466
+ if (start == NULL)
467
+ return(NULL);
468
+ if (end == NULL)
469
+ return(NULL);
470
+ if (end->type != XPATH_POINT)
471
+ return(NULL);
472
+
473
+ ret = xmlXPtrNewRangeInternal(start, -1, end->user, end->index);
474
+ xmlXPtrRangeCheckOrder(ret);
475
+ return(ret);
476
+ }
477
+
478
+ /**
479
+ * xmlXPtrNewRangeNodes:
480
+ * @start: the starting node
481
+ * @end: the ending node
482
+ *
483
+ * Create a new xmlXPathObjectPtr of type range using 2 nodes
484
+ *
485
+ * Returns the newly created object.
486
+ */
487
+ xmlXPathObjectPtr
488
+ xmlXPtrNewRangeNodes(xmlNodePtr start, xmlNodePtr end) {
489
+ xmlXPathObjectPtr ret;
490
+
491
+ if (start == NULL)
492
+ return(NULL);
493
+ if (end == NULL)
494
+ return(NULL);
495
+
496
+ ret = xmlXPtrNewRangeInternal(start, -1, end, -1);
497
+ xmlXPtrRangeCheckOrder(ret);
498
+ return(ret);
499
+ }
500
+
501
+ /**
502
+ * xmlXPtrNewCollapsedRange:
503
+ * @start: the starting and ending node
504
+ *
505
+ * Create a new xmlXPathObjectPtr of type range using a single nodes
506
+ *
507
+ * Returns the newly created object.
508
+ */
509
+ xmlXPathObjectPtr
510
+ xmlXPtrNewCollapsedRange(xmlNodePtr start) {
511
+ xmlXPathObjectPtr ret;
512
+
513
+ if (start == NULL)
514
+ return(NULL);
515
+
516
+ ret = xmlXPtrNewRangeInternal(start, -1, NULL, -1);
517
+ return(ret);
518
+ }
519
+
520
+ /**
521
+ * xmlXPtrNewRangeNodeObject:
522
+ * @start: the starting node
523
+ * @end: the ending object
524
+ *
525
+ * Create a new xmlXPathObjectPtr of type range from a not to an object
526
+ *
527
+ * Returns the newly created object.
528
+ */
529
+ xmlXPathObjectPtr
530
+ xmlXPtrNewRangeNodeObject(xmlNodePtr start, xmlXPathObjectPtr end) {
531
+ xmlNodePtr endNode;
532
+ int endIndex;
533
+ xmlXPathObjectPtr ret;
534
+
535
+ if (start == NULL)
536
+ return(NULL);
537
+ if (end == NULL)
538
+ return(NULL);
539
+ switch (end->type) {
540
+ case XPATH_POINT:
541
+ endNode = end->user;
542
+ endIndex = end->index;
543
+ break;
544
+ case XPATH_RANGE:
545
+ endNode = end->user2;
546
+ endIndex = end->index2;
547
+ break;
548
+ case XPATH_NODESET:
549
+ /*
550
+ * Empty set ...
551
+ */
552
+ if ((end->nodesetval == NULL) || (end->nodesetval->nodeNr <= 0))
553
+ return(NULL);
554
+ endNode = end->nodesetval->nodeTab[end->nodesetval->nodeNr - 1];
555
+ endIndex = -1;
556
+ break;
557
+ default:
558
+ /* TODO */
559
+ return(NULL);
560
+ }
561
+
562
+ ret = xmlXPtrNewRangeInternal(start, -1, endNode, endIndex);
563
+ xmlXPtrRangeCheckOrder(ret);
564
+ return(ret);
565
+ }
566
+
567
+ #define XML_RANGESET_DEFAULT 10
568
+
569
+ /**
570
+ * xmlXPtrLocationSetCreate:
571
+ * @val: an initial xmlXPathObjectPtr, or NULL
572
+ *
573
+ * Create a new xmlLocationSetPtr of type double and of value @val
574
+ *
575
+ * Returns the newly created object.
576
+ */
577
+ xmlLocationSetPtr
578
+ xmlXPtrLocationSetCreate(xmlXPathObjectPtr val) {
579
+ xmlLocationSetPtr ret;
580
+
581
+ ret = (xmlLocationSetPtr) xmlMalloc(sizeof(xmlLocationSet));
582
+ if (ret == NULL) {
583
+ xmlXPtrErrMemory("allocating locationset");
584
+ return(NULL);
585
+ }
586
+ memset(ret, 0 , (size_t) sizeof(xmlLocationSet));
587
+ if (val != NULL) {
588
+ ret->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
589
+ sizeof(xmlXPathObjectPtr));
590
+ if (ret->locTab == NULL) {
591
+ xmlXPtrErrMemory("allocating locationset");
592
+ xmlFree(ret);
593
+ return(NULL);
594
+ }
595
+ memset(ret->locTab, 0 ,
596
+ XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
597
+ ret->locMax = XML_RANGESET_DEFAULT;
598
+ ret->locTab[ret->locNr++] = val;
599
+ }
600
+ return(ret);
601
+ }
602
+
603
+ /**
604
+ * xmlXPtrLocationSetAdd:
605
+ * @cur: the initial range set
606
+ * @val: a new xmlXPathObjectPtr
607
+ *
608
+ * add a new xmlXPathObjectPtr to an existing LocationSet
609
+ * If the location already exist in the set @val is freed.
610
+ */
611
+ void
612
+ xmlXPtrLocationSetAdd(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
613
+ int i;
614
+
615
+ if ((cur == NULL) || (val == NULL)) return;
616
+
617
+ /*
618
+ * check against doublons
619
+ */
620
+ for (i = 0;i < cur->locNr;i++) {
621
+ if (xmlXPtrRangesEqual(cur->locTab[i], val)) {
622
+ xmlXPathFreeObject(val);
623
+ return;
624
+ }
625
+ }
626
+
627
+ /*
628
+ * grow the locTab if needed
629
+ */
630
+ if (cur->locMax == 0) {
631
+ cur->locTab = (xmlXPathObjectPtr *) xmlMalloc(XML_RANGESET_DEFAULT *
632
+ sizeof(xmlXPathObjectPtr));
633
+ if (cur->locTab == NULL) {
634
+ xmlXPtrErrMemory("adding location to set");
635
+ return;
636
+ }
637
+ memset(cur->locTab, 0 ,
638
+ XML_RANGESET_DEFAULT * (size_t) sizeof(xmlXPathObjectPtr));
639
+ cur->locMax = XML_RANGESET_DEFAULT;
640
+ } else if (cur->locNr == cur->locMax) {
641
+ xmlXPathObjectPtr *temp;
642
+
643
+ cur->locMax *= 2;
644
+ temp = (xmlXPathObjectPtr *) xmlRealloc(cur->locTab, cur->locMax *
645
+ sizeof(xmlXPathObjectPtr));
646
+ if (temp == NULL) {
647
+ xmlXPtrErrMemory("adding location to set");
648
+ return;
649
+ }
650
+ cur->locTab = temp;
651
+ }
652
+ cur->locTab[cur->locNr++] = val;
653
+ }
654
+
655
+ /**
656
+ * xmlXPtrLocationSetMerge:
657
+ * @val1: the first LocationSet
658
+ * @val2: the second LocationSet
659
+ *
660
+ * Merges two rangesets, all ranges from @val2 are added to @val1
661
+ *
662
+ * Returns val1 once extended or NULL in case of error.
663
+ */
664
+ xmlLocationSetPtr
665
+ xmlXPtrLocationSetMerge(xmlLocationSetPtr val1, xmlLocationSetPtr val2) {
666
+ int i;
667
+
668
+ if (val1 == NULL) return(NULL);
669
+ if (val2 == NULL) return(val1);
670
+
671
+ /*
672
+ * !!!!! this can be optimized a lot, knowing that both
673
+ * val1 and val2 already have unicity of their values.
674
+ */
675
+
676
+ for (i = 0;i < val2->locNr;i++)
677
+ xmlXPtrLocationSetAdd(val1, val2->locTab[i]);
678
+
679
+ return(val1);
680
+ }
681
+
682
+ /**
683
+ * xmlXPtrLocationSetDel:
684
+ * @cur: the initial range set
685
+ * @val: an xmlXPathObjectPtr
686
+ *
687
+ * Removes an xmlXPathObjectPtr from an existing LocationSet
688
+ */
689
+ void
690
+ xmlXPtrLocationSetDel(xmlLocationSetPtr cur, xmlXPathObjectPtr val) {
691
+ int i;
692
+
693
+ if (cur == NULL) return;
694
+ if (val == NULL) return;
695
+
696
+ /*
697
+ * check against doublons
698
+ */
699
+ for (i = 0;i < cur->locNr;i++)
700
+ if (cur->locTab[i] == val) break;
701
+
702
+ if (i >= cur->locNr) {
703
+ #ifdef DEBUG
704
+ xmlGenericError(xmlGenericErrorContext,
705
+ "xmlXPtrLocationSetDel: Range wasn't found in RangeList\n");
706
+ #endif
707
+ return;
708
+ }
709
+ cur->locNr--;
710
+ for (;i < cur->locNr;i++)
711
+ cur->locTab[i] = cur->locTab[i + 1];
712
+ cur->locTab[cur->locNr] = NULL;
713
+ }
714
+
715
+ /**
716
+ * xmlXPtrLocationSetRemove:
717
+ * @cur: the initial range set
718
+ * @val: the index to remove
719
+ *
720
+ * Removes an entry from an existing LocationSet list.
721
+ */
722
+ void
723
+ xmlXPtrLocationSetRemove(xmlLocationSetPtr cur, int val) {
724
+ if (cur == NULL) return;
725
+ if (val >= cur->locNr) return;
726
+ cur->locNr--;
727
+ for (;val < cur->locNr;val++)
728
+ cur->locTab[val] = cur->locTab[val + 1];
729
+ cur->locTab[cur->locNr] = NULL;
730
+ }
731
+
732
+ /**
733
+ * xmlXPtrFreeLocationSet:
734
+ * @obj: the xmlLocationSetPtr to free
735
+ *
736
+ * Free the LocationSet compound (not the actual ranges !).
737
+ */
738
+ void
739
+ xmlXPtrFreeLocationSet(xmlLocationSetPtr obj) {
740
+ int i;
741
+
742
+ if (obj == NULL) return;
743
+ if (obj->locTab != NULL) {
744
+ for (i = 0;i < obj->locNr; i++) {
745
+ xmlXPathFreeObject(obj->locTab[i]);
746
+ }
747
+ xmlFree(obj->locTab);
748
+ }
749
+ xmlFree(obj);
750
+ }
751
+
752
+ /**
753
+ * xmlXPtrNewLocationSetNodes:
754
+ * @start: the start NodePtr value
755
+ * @end: the end NodePtr value or NULL
756
+ *
757
+ * Create a new xmlXPathObjectPtr of type LocationSet and initialize
758
+ * it with the single range made of the two nodes @start and @end
759
+ *
760
+ * Returns the newly created object.
761
+ */
762
+ xmlXPathObjectPtr
763
+ xmlXPtrNewLocationSetNodes(xmlNodePtr start, xmlNodePtr end) {
764
+ xmlXPathObjectPtr ret;
765
+
766
+ ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
767
+ if (ret == NULL) {
768
+ xmlXPtrErrMemory("allocating locationset");
769
+ return(NULL);
770
+ }
771
+ memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
772
+ ret->type = XPATH_LOCATIONSET;
773
+ if (end == NULL)
774
+ ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewCollapsedRange(start));
775
+ else
776
+ ret->user = xmlXPtrLocationSetCreate(xmlXPtrNewRangeNodes(start,end));
777
+ return(ret);
778
+ }
779
+
780
+ /**
781
+ * xmlXPtrNewLocationSetNodeSet:
782
+ * @set: a node set
783
+ *
784
+ * Create a new xmlXPathObjectPtr of type LocationSet and initialize
785
+ * it with all the nodes from @set
786
+ *
787
+ * Returns the newly created object.
788
+ */
789
+ xmlXPathObjectPtr
790
+ xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set) {
791
+ xmlXPathObjectPtr ret;
792
+
793
+ ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
794
+ if (ret == NULL) {
795
+ xmlXPtrErrMemory("allocating locationset");
796
+ return(NULL);
797
+ }
798
+ memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
799
+ ret->type = XPATH_LOCATIONSET;
800
+ if (set != NULL) {
801
+ int i;
802
+ xmlLocationSetPtr newset;
803
+
804
+ newset = xmlXPtrLocationSetCreate(NULL);
805
+ if (newset == NULL)
806
+ return(ret);
807
+
808
+ for (i = 0;i < set->nodeNr;i++)
809
+ xmlXPtrLocationSetAdd(newset,
810
+ xmlXPtrNewCollapsedRange(set->nodeTab[i]));
811
+
812
+ ret->user = (void *) newset;
813
+ }
814
+ return(ret);
815
+ }
816
+
817
+ /**
818
+ * xmlXPtrWrapLocationSet:
819
+ * @val: the LocationSet value
820
+ *
821
+ * Wrap the LocationSet @val in a new xmlXPathObjectPtr
822
+ *
823
+ * Returns the newly created object.
824
+ */
825
+ xmlXPathObjectPtr
826
+ xmlXPtrWrapLocationSet(xmlLocationSetPtr val) {
827
+ xmlXPathObjectPtr ret;
828
+
829
+ ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
830
+ if (ret == NULL) {
831
+ xmlXPtrErrMemory("allocating locationset");
832
+ return(NULL);
833
+ }
834
+ memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
835
+ ret->type = XPATH_LOCATIONSET;
836
+ ret->user = (void *) val;
837
+ return(ret);
838
+ }
839
+
840
+ /************************************************************************
841
+ * *
842
+ * The parser *
843
+ * *
844
+ ************************************************************************/
845
+
846
+ static void xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name);
847
+
848
+ /*
849
+ * Macros for accessing the content. Those should be used only by the parser,
850
+ * and not exported.
851
+ *
852
+ * Dirty macros, i.e. one need to make assumption on the context to use them
853
+ *
854
+ * CUR_PTR return the current pointer to the xmlChar to be parsed.
855
+ * CUR returns the current xmlChar value, i.e. a 8 bit value
856
+ * in ISO-Latin or UTF-8.
857
+ * This should be used internally by the parser
858
+ * only to compare to ASCII values otherwise it would break when
859
+ * running with UTF-8 encoding.
860
+ * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
861
+ * to compare on ASCII based substring.
862
+ * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
863
+ * strings within the parser.
864
+ * CURRENT Returns the current char value, with the full decoding of
865
+ * UTF-8 if we are using this mode. It returns an int.
866
+ * NEXT Skip to the next character, this does the proper decoding
867
+ * in UTF-8 mode. It also pop-up unfinished entities on the fly.
868
+ * It returns the pointer to the current xmlChar.
869
+ */
870
+
871
+ #define CUR (*ctxt->cur)
872
+ #define SKIP(val) ctxt->cur += (val)
873
+ #define NXT(val) ctxt->cur[(val)]
874
+ #define CUR_PTR ctxt->cur
875
+
876
+ #define SKIP_BLANKS \
877
+ while (IS_BLANK_CH(*(ctxt->cur))) NEXT
878
+
879
+ #define CURRENT (*ctxt->cur)
880
+ #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
881
+
882
+ /*
883
+ * xmlXPtrGetChildNo:
884
+ * @ctxt: the XPointer Parser context
885
+ * @index: the child number
886
+ *
887
+ * Move the current node of the nodeset on the stack to the
888
+ * given child if found
889
+ */
890
+ static void
891
+ xmlXPtrGetChildNo(xmlXPathParserContextPtr ctxt, int indx) {
892
+ xmlNodePtr cur = NULL;
893
+ xmlXPathObjectPtr obj;
894
+ xmlNodeSetPtr oldset;
895
+
896
+ CHECK_TYPE(XPATH_NODESET);
897
+ obj = valuePop(ctxt);
898
+ oldset = obj->nodesetval;
899
+ if ((indx <= 0) || (oldset == NULL) || (oldset->nodeNr != 1)) {
900
+ xmlXPathFreeObject(obj);
901
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
902
+ return;
903
+ }
904
+ cur = xmlXPtrGetNthChild(oldset->nodeTab[0], indx);
905
+ if (cur == NULL) {
906
+ xmlXPathFreeObject(obj);
907
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
908
+ return;
909
+ }
910
+ oldset->nodeTab[0] = cur;
911
+ valuePush(ctxt, obj);
912
+ }
913
+
914
+ /**
915
+ * xmlXPtrEvalXPtrPart:
916
+ * @ctxt: the XPointer Parser context
917
+ * @name: the preparsed Scheme for the XPtrPart
918
+ *
919
+ * XPtrPart ::= 'xpointer' '(' XPtrExpr ')'
920
+ * | Scheme '(' SchemeSpecificExpr ')'
921
+ *
922
+ * Scheme ::= NCName - 'xpointer' [VC: Non-XPointer schemes]
923
+ *
924
+ * SchemeSpecificExpr ::= StringWithBalancedParens
925
+ *
926
+ * StringWithBalancedParens ::=
927
+ * [^()]* ('(' StringWithBalancedParens ')' [^()]*)*
928
+ * [VC: Parenthesis escaping]
929
+ *
930
+ * XPtrExpr ::= Expr [VC: Parenthesis escaping]
931
+ *
932
+ * VC: Parenthesis escaping:
933
+ * The end of an XPointer part is signaled by the right parenthesis ")"
934
+ * character that is balanced with the left parenthesis "(" character
935
+ * that began the part. Any unbalanced parenthesis character inside the
936
+ * expression, even within literals, must be escaped with a circumflex (^)
937
+ * character preceding it. If the expression contains any literal
938
+ * occurrences of the circumflex, each must be escaped with an additional
939
+ * circumflex (that is, ^^). If the unescaped parentheses in the expression
940
+ * are not balanced, a syntax error results.
941
+ *
942
+ * Parse and evaluate an XPtrPart. Basically it generates the unescaped
943
+ * string and if the scheme is 'xpointer' it will call the XPath interpreter.
944
+ *
945
+ * TODO: there is no new scheme registration mechanism
946
+ */
947
+
948
+ static void
949
+ xmlXPtrEvalXPtrPart(xmlXPathParserContextPtr ctxt, xmlChar *name) {
950
+ xmlChar *buffer, *cur;
951
+ int len;
952
+ int level;
953
+
954
+ if (name == NULL)
955
+ name = xmlXPathParseName(ctxt);
956
+ if (name == NULL)
957
+ XP_ERROR(XPATH_EXPR_ERROR);
958
+
959
+ if (CUR != '(') {
960
+ xmlFree(name);
961
+ XP_ERROR(XPATH_EXPR_ERROR);
962
+ }
963
+ NEXT;
964
+ level = 1;
965
+
966
+ len = xmlStrlen(ctxt->cur);
967
+ len++;
968
+ buffer = (xmlChar *) xmlMallocAtomic(len * sizeof (xmlChar));
969
+ if (buffer == NULL) {
970
+ xmlXPtrErrMemory("allocating buffer");
971
+ xmlFree(name);
972
+ return;
973
+ }
974
+
975
+ cur = buffer;
976
+ while (CUR != 0) {
977
+ if (CUR == ')') {
978
+ level--;
979
+ if (level == 0) {
980
+ NEXT;
981
+ break;
982
+ }
983
+ } else if (CUR == '(') {
984
+ level++;
985
+ } else if (CUR == '^') {
986
+ if ((NXT(1) == ')') || (NXT(1) == '(') || (NXT(1) == '^')) {
987
+ NEXT;
988
+ }
989
+ }
990
+ *cur++ = CUR;
991
+ NEXT;
992
+ }
993
+ *cur = 0;
994
+
995
+ if ((level != 0) && (CUR == 0)) {
996
+ xmlFree(name);
997
+ xmlFree(buffer);
998
+ XP_ERROR(XPTR_SYNTAX_ERROR);
999
+ }
1000
+
1001
+ if (xmlStrEqual(name, (xmlChar *) "xpointer")) {
1002
+ const xmlChar *left = CUR_PTR;
1003
+
1004
+ CUR_PTR = buffer;
1005
+ /*
1006
+ * To evaluate an xpointer scheme element (4.3) we need:
1007
+ * context initialized to the root
1008
+ * context position initialized to 1
1009
+ * context size initialized to 1
1010
+ */
1011
+ ctxt->context->node = (xmlNodePtr)ctxt->context->doc;
1012
+ ctxt->context->proximityPosition = 1;
1013
+ ctxt->context->contextSize = 1;
1014
+ xmlXPathEvalExpr(ctxt);
1015
+ CUR_PTR=left;
1016
+ } else if (xmlStrEqual(name, (xmlChar *) "element")) {
1017
+ const xmlChar *left = CUR_PTR;
1018
+ xmlChar *name2;
1019
+
1020
+ CUR_PTR = buffer;
1021
+ if (buffer[0] == '/') {
1022
+ xmlXPathRoot(ctxt);
1023
+ xmlXPtrEvalChildSeq(ctxt, NULL);
1024
+ } else {
1025
+ name2 = xmlXPathParseName(ctxt);
1026
+ if (name2 == NULL) {
1027
+ CUR_PTR = left;
1028
+ xmlFree(buffer);
1029
+ xmlFree(name);
1030
+ XP_ERROR(XPATH_EXPR_ERROR);
1031
+ }
1032
+ xmlXPtrEvalChildSeq(ctxt, name2);
1033
+ }
1034
+ CUR_PTR = left;
1035
+ #ifdef XPTR_XMLNS_SCHEME
1036
+ } else if (xmlStrEqual(name, (xmlChar *) "xmlns")) {
1037
+ const xmlChar *left = CUR_PTR;
1038
+ xmlChar *prefix;
1039
+ xmlChar *URI;
1040
+ xmlURIPtr value;
1041
+
1042
+ CUR_PTR = buffer;
1043
+ prefix = xmlXPathParseNCName(ctxt);
1044
+ if (prefix == NULL) {
1045
+ xmlFree(buffer);
1046
+ xmlFree(name);
1047
+ XP_ERROR(XPTR_SYNTAX_ERROR);
1048
+ }
1049
+ SKIP_BLANKS;
1050
+ if (CUR != '=') {
1051
+ xmlFree(prefix);
1052
+ xmlFree(buffer);
1053
+ xmlFree(name);
1054
+ XP_ERROR(XPTR_SYNTAX_ERROR);
1055
+ }
1056
+ NEXT;
1057
+ SKIP_BLANKS;
1058
+ /* @@ check escaping in the XPointer WD */
1059
+
1060
+ value = xmlParseURI((const char *)ctxt->cur);
1061
+ if (value == NULL) {
1062
+ xmlFree(prefix);
1063
+ xmlFree(buffer);
1064
+ xmlFree(name);
1065
+ XP_ERROR(XPTR_SYNTAX_ERROR);
1066
+ }
1067
+ URI = xmlSaveUri(value);
1068
+ xmlFreeURI(value);
1069
+ if (URI == NULL) {
1070
+ xmlFree(prefix);
1071
+ xmlFree(buffer);
1072
+ xmlFree(name);
1073
+ XP_ERROR(XPATH_MEMORY_ERROR);
1074
+ }
1075
+
1076
+ xmlXPathRegisterNs(ctxt->context, prefix, URI);
1077
+ CUR_PTR = left;
1078
+ xmlFree(URI);
1079
+ xmlFree(prefix);
1080
+ #endif /* XPTR_XMLNS_SCHEME */
1081
+ } else {
1082
+ xmlXPtrErr(ctxt, XML_XPTR_UNKNOWN_SCHEME,
1083
+ "unsupported scheme '%s'\n", name);
1084
+ }
1085
+ xmlFree(buffer);
1086
+ xmlFree(name);
1087
+ }
1088
+
1089
+ /**
1090
+ * xmlXPtrEvalFullXPtr:
1091
+ * @ctxt: the XPointer Parser context
1092
+ * @name: the preparsed Scheme for the first XPtrPart
1093
+ *
1094
+ * FullXPtr ::= XPtrPart (S? XPtrPart)*
1095
+ *
1096
+ * As the specs says:
1097
+ * -----------
1098
+ * When multiple XPtrParts are provided, they must be evaluated in
1099
+ * left-to-right order. If evaluation of one part fails, the nexti
1100
+ * is evaluated. The following conditions cause XPointer part failure:
1101
+ *
1102
+ * - An unknown scheme
1103
+ * - A scheme that does not locate any sub-resource present in the resource
1104
+ * - A scheme that is not applicable to the media type of the resource
1105
+ *
1106
+ * The XPointer application must consume a failed XPointer part and
1107
+ * attempt to evaluate the next one, if any. The result of the first
1108
+ * XPointer part whose evaluation succeeds is taken to be the fragment
1109
+ * located by the XPointer as a whole. If all the parts fail, the result
1110
+ * for the XPointer as a whole is a sub-resource error.
1111
+ * -----------
1112
+ *
1113
+ * Parse and evaluate a Full XPtr i.e. possibly a cascade of XPath based
1114
+ * expressions or other schemes.
1115
+ */
1116
+ static void
1117
+ xmlXPtrEvalFullXPtr(xmlXPathParserContextPtr ctxt, xmlChar *name) {
1118
+ if (name == NULL)
1119
+ name = xmlXPathParseName(ctxt);
1120
+ if (name == NULL)
1121
+ XP_ERROR(XPATH_EXPR_ERROR);
1122
+ while (name != NULL) {
1123
+ ctxt->error = XPATH_EXPRESSION_OK;
1124
+ xmlXPtrEvalXPtrPart(ctxt, name);
1125
+
1126
+ /* in case of syntax error, break here */
1127
+ if ((ctxt->error != XPATH_EXPRESSION_OK) &&
1128
+ (ctxt->error != XML_XPTR_UNKNOWN_SCHEME))
1129
+ return;
1130
+
1131
+ /*
1132
+ * If the returned value is a non-empty nodeset
1133
+ * or location set, return here.
1134
+ */
1135
+ if (ctxt->value != NULL) {
1136
+ xmlXPathObjectPtr obj = ctxt->value;
1137
+
1138
+ switch (obj->type) {
1139
+ case XPATH_LOCATIONSET: {
1140
+ xmlLocationSetPtr loc = ctxt->value->user;
1141
+ if ((loc != NULL) && (loc->locNr > 0))
1142
+ return;
1143
+ break;
1144
+ }
1145
+ case XPATH_NODESET: {
1146
+ xmlNodeSetPtr loc = ctxt->value->nodesetval;
1147
+ if ((loc != NULL) && (loc->nodeNr > 0))
1148
+ return;
1149
+ break;
1150
+ }
1151
+ default:
1152
+ break;
1153
+ }
1154
+
1155
+ /*
1156
+ * Evaluating to improper values is equivalent to
1157
+ * a sub-resource error, clean-up the stack
1158
+ */
1159
+ do {
1160
+ obj = valuePop(ctxt);
1161
+ if (obj != NULL) {
1162
+ xmlXPathFreeObject(obj);
1163
+ }
1164
+ } while (obj != NULL);
1165
+ }
1166
+
1167
+ /*
1168
+ * Is there another XPointer part.
1169
+ */
1170
+ SKIP_BLANKS;
1171
+ name = xmlXPathParseName(ctxt);
1172
+ }
1173
+ }
1174
+
1175
+ /**
1176
+ * xmlXPtrEvalChildSeq:
1177
+ * @ctxt: the XPointer Parser context
1178
+ * @name: a possible ID name of the child sequence
1179
+ *
1180
+ * ChildSeq ::= '/1' ('/' [0-9]*)*
1181
+ * | Name ('/' [0-9]*)+
1182
+ *
1183
+ * Parse and evaluate a Child Sequence. This routine also handle the
1184
+ * case of a Bare Name used to get a document ID.
1185
+ */
1186
+ static void
1187
+ xmlXPtrEvalChildSeq(xmlXPathParserContextPtr ctxt, xmlChar *name) {
1188
+ /*
1189
+ * XPointer don't allow by syntax to address in multirooted trees
1190
+ * this might prove useful in some cases, warn about it.
1191
+ */
1192
+ if ((name == NULL) && (CUR == '/') && (NXT(1) != '1')) {
1193
+ xmlXPtrErr(ctxt, XML_XPTR_CHILDSEQ_START,
1194
+ "warning: ChildSeq not starting by /1\n", NULL);
1195
+ }
1196
+
1197
+ if (name != NULL) {
1198
+ valuePush(ctxt, xmlXPathNewString(name));
1199
+ xmlFree(name);
1200
+ xmlXPathIdFunction(ctxt, 1);
1201
+ CHECK_ERROR;
1202
+ }
1203
+
1204
+ while (CUR == '/') {
1205
+ int child = 0, overflow = 0;
1206
+ NEXT;
1207
+
1208
+ while ((CUR >= '0') && (CUR <= '9')) {
1209
+ int d = CUR - '0';
1210
+ if (child > INT_MAX / 10)
1211
+ overflow = 1;
1212
+ else
1213
+ child *= 10;
1214
+ if (child > INT_MAX - d)
1215
+ overflow = 1;
1216
+ else
1217
+ child += d;
1218
+ NEXT;
1219
+ }
1220
+ if (overflow)
1221
+ child = 0;
1222
+ xmlXPtrGetChildNo(ctxt, child);
1223
+ }
1224
+ }
1225
+
1226
+
1227
+ /**
1228
+ * xmlXPtrEvalXPointer:
1229
+ * @ctxt: the XPointer Parser context
1230
+ *
1231
+ * XPointer ::= Name
1232
+ * | ChildSeq
1233
+ * | FullXPtr
1234
+ *
1235
+ * Parse and evaluate an XPointer
1236
+ */
1237
+ static void
1238
+ xmlXPtrEvalXPointer(xmlXPathParserContextPtr ctxt) {
1239
+ if (ctxt->valueTab == NULL) {
1240
+ /* Allocate the value stack */
1241
+ ctxt->valueTab = (xmlXPathObjectPtr *)
1242
+ xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
1243
+ if (ctxt->valueTab == NULL) {
1244
+ xmlXPtrErrMemory("allocating evaluation context");
1245
+ return;
1246
+ }
1247
+ ctxt->valueNr = 0;
1248
+ ctxt->valueMax = 10;
1249
+ ctxt->value = NULL;
1250
+ ctxt->valueFrame = 0;
1251
+ }
1252
+ SKIP_BLANKS;
1253
+ if (CUR == '/') {
1254
+ xmlXPathRoot(ctxt);
1255
+ xmlXPtrEvalChildSeq(ctxt, NULL);
1256
+ } else {
1257
+ xmlChar *name;
1258
+
1259
+ name = xmlXPathParseName(ctxt);
1260
+ if (name == NULL)
1261
+ XP_ERROR(XPATH_EXPR_ERROR);
1262
+ if (CUR == '(') {
1263
+ xmlXPtrEvalFullXPtr(ctxt, name);
1264
+ /* Short evaluation */
1265
+ return;
1266
+ } else {
1267
+ /* this handle both Bare Names and Child Sequences */
1268
+ xmlXPtrEvalChildSeq(ctxt, name);
1269
+ }
1270
+ }
1271
+ SKIP_BLANKS;
1272
+ if (CUR != 0)
1273
+ XP_ERROR(XPATH_EXPR_ERROR);
1274
+ }
1275
+
1276
+
1277
+ /************************************************************************
1278
+ * *
1279
+ * General routines *
1280
+ * *
1281
+ ************************************************************************/
1282
+
1283
+ static
1284
+ void xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);
1285
+ static
1286
+ void xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs);
1287
+ static
1288
+ void xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs);
1289
+ static
1290
+ void xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs);
1291
+ static
1292
+ void xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs);
1293
+ static
1294
+ void xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs);
1295
+ static
1296
+ void xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs);
1297
+
1298
+ /**
1299
+ * xmlXPtrNewContext:
1300
+ * @doc: the XML document
1301
+ * @here: the node that directly contains the XPointer being evaluated or NULL
1302
+ * @origin: the element from which a user or program initiated traversal of
1303
+ * the link, or NULL.
1304
+ *
1305
+ * Create a new XPointer context
1306
+ *
1307
+ * Returns the xmlXPathContext just allocated.
1308
+ */
1309
+ xmlXPathContextPtr
1310
+ xmlXPtrNewContext(xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin) {
1311
+ xmlXPathContextPtr ret;
1312
+
1313
+ ret = xmlXPathNewContext(doc);
1314
+ if (ret == NULL)
1315
+ return(ret);
1316
+ ret->xptr = 1;
1317
+ ret->here = here;
1318
+ ret->origin = origin;
1319
+
1320
+ xmlXPathRegisterFunc(ret, (xmlChar *)"range",
1321
+ xmlXPtrRangeFunction);
1322
+ xmlXPathRegisterFunc(ret, (xmlChar *)"range-inside",
1323
+ xmlXPtrRangeInsideFunction);
1324
+ xmlXPathRegisterFunc(ret, (xmlChar *)"string-range",
1325
+ xmlXPtrStringRangeFunction);
1326
+ xmlXPathRegisterFunc(ret, (xmlChar *)"start-point",
1327
+ xmlXPtrStartPointFunction);
1328
+ xmlXPathRegisterFunc(ret, (xmlChar *)"end-point",
1329
+ xmlXPtrEndPointFunction);
1330
+ xmlXPathRegisterFunc(ret, (xmlChar *)"here",
1331
+ xmlXPtrHereFunction);
1332
+ xmlXPathRegisterFunc(ret, (xmlChar *)" origin",
1333
+ xmlXPtrOriginFunction);
1334
+
1335
+ return(ret);
1336
+ }
1337
+
1338
+ /**
1339
+ * xmlXPtrEval:
1340
+ * @str: the XPointer expression
1341
+ * @ctx: the XPointer context
1342
+ *
1343
+ * Evaluate the XPath Location Path in the given context.
1344
+ *
1345
+ * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
1346
+ * the caller has to free the object.
1347
+ */
1348
+ xmlXPathObjectPtr
1349
+ xmlXPtrEval(const xmlChar *str, xmlXPathContextPtr ctx) {
1350
+ xmlXPathParserContextPtr ctxt;
1351
+ xmlXPathObjectPtr res = NULL, tmp;
1352
+ xmlXPathObjectPtr init = NULL;
1353
+ int stack = 0;
1354
+
1355
+ xmlInitParser();
1356
+
1357
+ if ((ctx == NULL) || (str == NULL))
1358
+ return(NULL);
1359
+
1360
+ ctxt = xmlXPathNewParserContext(str, ctx);
1361
+ if (ctxt == NULL)
1362
+ return(NULL);
1363
+ ctxt->xptr = 1;
1364
+ xmlXPtrEvalXPointer(ctxt);
1365
+
1366
+ if ((ctxt->value != NULL) &&
1367
+ (ctxt->value->type != XPATH_NODESET) &&
1368
+ (ctxt->value->type != XPATH_LOCATIONSET)) {
1369
+ xmlXPtrErr(ctxt, XML_XPTR_EVAL_FAILED,
1370
+ "xmlXPtrEval: evaluation failed to return a node set\n",
1371
+ NULL);
1372
+ } else {
1373
+ res = valuePop(ctxt);
1374
+ }
1375
+
1376
+ do {
1377
+ tmp = valuePop(ctxt);
1378
+ if (tmp != NULL) {
1379
+ if (tmp != init) {
1380
+ if (tmp->type == XPATH_NODESET) {
1381
+ /*
1382
+ * Evaluation may push a root nodeset which is unused
1383
+ */
1384
+ xmlNodeSetPtr set;
1385
+ set = tmp->nodesetval;
1386
+ if ((set == NULL) || (set->nodeNr != 1) ||
1387
+ (set->nodeTab[0] != (xmlNodePtr) ctx->doc))
1388
+ stack++;
1389
+ } else
1390
+ stack++;
1391
+ }
1392
+ xmlXPathFreeObject(tmp);
1393
+ }
1394
+ } while (tmp != NULL);
1395
+ if (stack != 0) {
1396
+ xmlXPtrErr(ctxt, XML_XPTR_EXTRA_OBJECTS,
1397
+ "xmlXPtrEval: object(s) left on the eval stack\n",
1398
+ NULL);
1399
+ }
1400
+ if (ctxt->error != XPATH_EXPRESSION_OK) {
1401
+ xmlXPathFreeObject(res);
1402
+ res = NULL;
1403
+ }
1404
+
1405
+ xmlXPathFreeParserContext(ctxt);
1406
+ return(res);
1407
+ }
1408
+
1409
+ /**
1410
+ * xmlXPtrBuildRangeNodeList:
1411
+ * @range: a range object
1412
+ *
1413
+ * Build a node list tree copy of the range
1414
+ *
1415
+ * Returns an xmlNodePtr list or NULL.
1416
+ * the caller has to free the node tree.
1417
+ */
1418
+ static xmlNodePtr
1419
+ xmlXPtrBuildRangeNodeList(xmlXPathObjectPtr range) {
1420
+ /* pointers to generated nodes */
1421
+ xmlNodePtr list = NULL, last = NULL, parent = NULL, tmp;
1422
+ /* pointers to traversal nodes */
1423
+ xmlNodePtr start, cur, end;
1424
+ int index1, index2;
1425
+
1426
+ if (range == NULL)
1427
+ return(NULL);
1428
+ if (range->type != XPATH_RANGE)
1429
+ return(NULL);
1430
+ start = (xmlNodePtr) range->user;
1431
+
1432
+ if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
1433
+ return(NULL);
1434
+ end = range->user2;
1435
+ if (end == NULL)
1436
+ return(xmlCopyNode(start, 1));
1437
+ if (end->type == XML_NAMESPACE_DECL)
1438
+ return(NULL);
1439
+
1440
+ cur = start;
1441
+ index1 = range->index;
1442
+ index2 = range->index2;
1443
+ while (cur != NULL) {
1444
+ if (cur == end) {
1445
+ if (cur->type == XML_TEXT_NODE) {
1446
+ const xmlChar *content = cur->content;
1447
+ int len;
1448
+
1449
+ if (content == NULL) {
1450
+ tmp = xmlNewTextLen(NULL, 0);
1451
+ } else {
1452
+ len = index2;
1453
+ if ((cur == start) && (index1 > 1)) {
1454
+ content += (index1 - 1);
1455
+ len -= (index1 - 1);
1456
+ index1 = 0;
1457
+ } else {
1458
+ len = index2;
1459
+ }
1460
+ tmp = xmlNewTextLen(content, len);
1461
+ }
1462
+ /* single sub text node selection */
1463
+ if (list == NULL)
1464
+ return(tmp);
1465
+ /* prune and return full set */
1466
+ if (last != NULL)
1467
+ xmlAddNextSibling(last, tmp);
1468
+ else
1469
+ xmlAddChild(parent, tmp);
1470
+ return(list);
1471
+ } else {
1472
+ tmp = xmlCopyNode(cur, 0);
1473
+ if (list == NULL)
1474
+ list = tmp;
1475
+ else {
1476
+ if (last != NULL)
1477
+ xmlAddNextSibling(last, tmp);
1478
+ else
1479
+ xmlAddChild(parent, tmp);
1480
+ }
1481
+ last = NULL;
1482
+ parent = tmp;
1483
+
1484
+ if (index2 > 1) {
1485
+ end = xmlXPtrGetNthChild(cur, index2 - 1);
1486
+ index2 = 0;
1487
+ }
1488
+ if ((cur == start) && (index1 > 1)) {
1489
+ cur = xmlXPtrGetNthChild(cur, index1 - 1);
1490
+ index1 = 0;
1491
+ } else {
1492
+ cur = cur->children;
1493
+ }
1494
+ /*
1495
+ * Now gather the remaining nodes from cur to end
1496
+ */
1497
+ continue; /* while */
1498
+ }
1499
+ } else if ((cur == start) &&
1500
+ (list == NULL) /* looks superfluous but ... */ ) {
1501
+ if ((cur->type == XML_TEXT_NODE) ||
1502
+ (cur->type == XML_CDATA_SECTION_NODE)) {
1503
+ const xmlChar *content = cur->content;
1504
+
1505
+ if (content == NULL) {
1506
+ tmp = xmlNewTextLen(NULL, 0);
1507
+ } else {
1508
+ if (index1 > 1) {
1509
+ content += (index1 - 1);
1510
+ }
1511
+ tmp = xmlNewText(content);
1512
+ }
1513
+ last = list = tmp;
1514
+ } else {
1515
+ if ((cur == start) && (index1 > 1)) {
1516
+ tmp = xmlCopyNode(cur, 0);
1517
+ list = tmp;
1518
+ parent = tmp;
1519
+ last = NULL;
1520
+ cur = xmlXPtrGetNthChild(cur, index1 - 1);
1521
+ index1 = 0;
1522
+ /*
1523
+ * Now gather the remaining nodes from cur to end
1524
+ */
1525
+ continue; /* while */
1526
+ }
1527
+ tmp = xmlCopyNode(cur, 1);
1528
+ list = tmp;
1529
+ parent = NULL;
1530
+ last = tmp;
1531
+ }
1532
+ } else {
1533
+ tmp = NULL;
1534
+ switch (cur->type) {
1535
+ case XML_DTD_NODE:
1536
+ case XML_ELEMENT_DECL:
1537
+ case XML_ATTRIBUTE_DECL:
1538
+ case XML_ENTITY_NODE:
1539
+ /* Do not copy DTD information */
1540
+ break;
1541
+ case XML_ENTITY_DECL:
1542
+ TODO /* handle crossing entities -> stack needed */
1543
+ break;
1544
+ case XML_XINCLUDE_START:
1545
+ case XML_XINCLUDE_END:
1546
+ /* don't consider it part of the tree content */
1547
+ break;
1548
+ case XML_ATTRIBUTE_NODE:
1549
+ /* Humm, should not happen ! */
1550
+ STRANGE
1551
+ break;
1552
+ default:
1553
+ tmp = xmlCopyNode(cur, 1);
1554
+ break;
1555
+ }
1556
+ if (tmp != NULL) {
1557
+ if ((list == NULL) || ((last == NULL) && (parent == NULL))) {
1558
+ STRANGE
1559
+ return(NULL);
1560
+ }
1561
+ if (last != NULL)
1562
+ xmlAddNextSibling(last, tmp);
1563
+ else {
1564
+ xmlAddChild(parent, tmp);
1565
+ last = tmp;
1566
+ }
1567
+ }
1568
+ }
1569
+ /*
1570
+ * Skip to next node in document order
1571
+ */
1572
+ if ((list == NULL) || ((last == NULL) && (parent == NULL))) {
1573
+ STRANGE
1574
+ return(NULL);
1575
+ }
1576
+ cur = xmlXPtrAdvanceNode(cur, NULL);
1577
+ }
1578
+ return(list);
1579
+ }
1580
+
1581
+ /**
1582
+ * xmlXPtrBuildNodeList:
1583
+ * @obj: the XPointer result from the evaluation.
1584
+ *
1585
+ * Build a node list tree copy of the XPointer result.
1586
+ * This will drop Attributes and Namespace declarations.
1587
+ *
1588
+ * Returns an xmlNodePtr list or NULL.
1589
+ * the caller has to free the node tree.
1590
+ */
1591
+ xmlNodePtr
1592
+ xmlXPtrBuildNodeList(xmlXPathObjectPtr obj) {
1593
+ xmlNodePtr list = NULL, last = NULL;
1594
+ int i;
1595
+
1596
+ if (obj == NULL)
1597
+ return(NULL);
1598
+ switch (obj->type) {
1599
+ case XPATH_NODESET: {
1600
+ xmlNodeSetPtr set = obj->nodesetval;
1601
+ if (set == NULL)
1602
+ return(NULL);
1603
+ for (i = 0;i < set->nodeNr;i++) {
1604
+ if (set->nodeTab[i] == NULL)
1605
+ continue;
1606
+ switch (set->nodeTab[i]->type) {
1607
+ case XML_TEXT_NODE:
1608
+ case XML_CDATA_SECTION_NODE:
1609
+ case XML_ELEMENT_NODE:
1610
+ case XML_ENTITY_REF_NODE:
1611
+ case XML_ENTITY_NODE:
1612
+ case XML_PI_NODE:
1613
+ case XML_COMMENT_NODE:
1614
+ case XML_DOCUMENT_NODE:
1615
+ case XML_HTML_DOCUMENT_NODE:
1616
+ #ifdef LIBXML_DOCB_ENABLED
1617
+ case XML_DOCB_DOCUMENT_NODE:
1618
+ #endif
1619
+ case XML_XINCLUDE_START:
1620
+ case XML_XINCLUDE_END:
1621
+ break;
1622
+ case XML_ATTRIBUTE_NODE:
1623
+ case XML_NAMESPACE_DECL:
1624
+ case XML_DOCUMENT_TYPE_NODE:
1625
+ case XML_DOCUMENT_FRAG_NODE:
1626
+ case XML_NOTATION_NODE:
1627
+ case XML_DTD_NODE:
1628
+ case XML_ELEMENT_DECL:
1629
+ case XML_ATTRIBUTE_DECL:
1630
+ case XML_ENTITY_DECL:
1631
+ continue; /* for */
1632
+ }
1633
+ if (last == NULL)
1634
+ list = last = xmlCopyNode(set->nodeTab[i], 1);
1635
+ else {
1636
+ xmlAddNextSibling(last, xmlCopyNode(set->nodeTab[i], 1));
1637
+ if (last->next != NULL)
1638
+ last = last->next;
1639
+ }
1640
+ }
1641
+ break;
1642
+ }
1643
+ case XPATH_LOCATIONSET: {
1644
+ xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
1645
+ if (set == NULL)
1646
+ return(NULL);
1647
+ for (i = 0;i < set->locNr;i++) {
1648
+ if (last == NULL)
1649
+ list = last = xmlXPtrBuildNodeList(set->locTab[i]);
1650
+ else
1651
+ xmlAddNextSibling(last,
1652
+ xmlXPtrBuildNodeList(set->locTab[i]));
1653
+ if (last != NULL) {
1654
+ while (last->next != NULL)
1655
+ last = last->next;
1656
+ }
1657
+ }
1658
+ break;
1659
+ }
1660
+ case XPATH_RANGE:
1661
+ return(xmlXPtrBuildRangeNodeList(obj));
1662
+ case XPATH_POINT:
1663
+ return(xmlCopyNode(obj->user, 0));
1664
+ default:
1665
+ break;
1666
+ }
1667
+ return(list);
1668
+ }
1669
+
1670
+ /************************************************************************
1671
+ * *
1672
+ * XPointer functions *
1673
+ * *
1674
+ ************************************************************************/
1675
+
1676
+ /**
1677
+ * xmlXPtrNbLocChildren:
1678
+ * @node: an xmlNodePtr
1679
+ *
1680
+ * Count the number of location children of @node or the length of the
1681
+ * string value in case of text/PI/Comments nodes
1682
+ *
1683
+ * Returns the number of location children
1684
+ */
1685
+ static int
1686
+ xmlXPtrNbLocChildren(xmlNodePtr node) {
1687
+ int ret = 0;
1688
+ if (node == NULL)
1689
+ return(-1);
1690
+ switch (node->type) {
1691
+ case XML_HTML_DOCUMENT_NODE:
1692
+ case XML_DOCUMENT_NODE:
1693
+ case XML_ELEMENT_NODE:
1694
+ node = node->children;
1695
+ while (node != NULL) {
1696
+ if (node->type == XML_ELEMENT_NODE)
1697
+ ret++;
1698
+ node = node->next;
1699
+ }
1700
+ break;
1701
+ case XML_ATTRIBUTE_NODE:
1702
+ return(-1);
1703
+
1704
+ case XML_PI_NODE:
1705
+ case XML_COMMENT_NODE:
1706
+ case XML_TEXT_NODE:
1707
+ case XML_CDATA_SECTION_NODE:
1708
+ case XML_ENTITY_REF_NODE:
1709
+ ret = xmlStrlen(node->content);
1710
+ break;
1711
+ default:
1712
+ return(-1);
1713
+ }
1714
+ return(ret);
1715
+ }
1716
+
1717
+ /**
1718
+ * xmlXPtrHereFunction:
1719
+ * @ctxt: the XPointer Parser context
1720
+ * @nargs: the number of args
1721
+ *
1722
+ * Function implementing here() operation
1723
+ * as described in 5.4.3
1724
+ */
1725
+ static void
1726
+ xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1727
+ CHECK_ARITY(0);
1728
+
1729
+ if (ctxt->context->here == NULL)
1730
+ XP_ERROR(XPTR_SYNTAX_ERROR);
1731
+
1732
+ valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->here, NULL));
1733
+ }
1734
+
1735
+ /**
1736
+ * xmlXPtrOriginFunction:
1737
+ * @ctxt: the XPointer Parser context
1738
+ * @nargs: the number of args
1739
+ *
1740
+ * Function implementing origin() operation
1741
+ * as described in 5.4.3
1742
+ */
1743
+ static void
1744
+ xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1745
+ CHECK_ARITY(0);
1746
+
1747
+ if (ctxt->context->origin == NULL)
1748
+ XP_ERROR(XPTR_SYNTAX_ERROR);
1749
+
1750
+ valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->origin, NULL));
1751
+ }
1752
+
1753
+ /**
1754
+ * xmlXPtrStartPointFunction:
1755
+ * @ctxt: the XPointer Parser context
1756
+ * @nargs: the number of args
1757
+ *
1758
+ * Function implementing start-point() operation
1759
+ * as described in 5.4.3
1760
+ * ----------------
1761
+ * location-set start-point(location-set)
1762
+ *
1763
+ * For each location x in the argument location-set, start-point adds a
1764
+ * location of type point to the result location-set. That point represents
1765
+ * the start point of location x and is determined by the following rules:
1766
+ *
1767
+ * - If x is of type point, the start point is x.
1768
+ * - If x is of type range, the start point is the start point of x.
1769
+ * - If x is of type root, element, text, comment, or processing instruction,
1770
+ * - the container node of the start point is x and the index is 0.
1771
+ * - If x is of type attribute or namespace, the function must signal a
1772
+ * syntax error.
1773
+ * ----------------
1774
+ *
1775
+ */
1776
+ static void
1777
+ xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1778
+ xmlXPathObjectPtr tmp, obj, point;
1779
+ xmlLocationSetPtr newset = NULL;
1780
+ xmlLocationSetPtr oldset = NULL;
1781
+
1782
+ CHECK_ARITY(1);
1783
+ if ((ctxt->value == NULL) ||
1784
+ ((ctxt->value->type != XPATH_LOCATIONSET) &&
1785
+ (ctxt->value->type != XPATH_NODESET)))
1786
+ XP_ERROR(XPATH_INVALID_TYPE)
1787
+
1788
+ obj = valuePop(ctxt);
1789
+ if (obj->type == XPATH_NODESET) {
1790
+ /*
1791
+ * First convert to a location set
1792
+ */
1793
+ tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval);
1794
+ xmlXPathFreeObject(obj);
1795
+ if (tmp == NULL)
1796
+ XP_ERROR(XPATH_MEMORY_ERROR)
1797
+ obj = tmp;
1798
+ }
1799
+
1800
+ newset = xmlXPtrLocationSetCreate(NULL);
1801
+ if (newset == NULL) {
1802
+ xmlXPathFreeObject(obj);
1803
+ XP_ERROR(XPATH_MEMORY_ERROR);
1804
+ }
1805
+ oldset = (xmlLocationSetPtr) obj->user;
1806
+ if (oldset != NULL) {
1807
+ int i;
1808
+
1809
+ for (i = 0; i < oldset->locNr; i++) {
1810
+ tmp = oldset->locTab[i];
1811
+ if (tmp == NULL)
1812
+ continue;
1813
+ point = NULL;
1814
+ switch (tmp->type) {
1815
+ case XPATH_POINT:
1816
+ point = xmlXPtrNewPoint(tmp->user, tmp->index);
1817
+ break;
1818
+ case XPATH_RANGE: {
1819
+ xmlNodePtr node = tmp->user;
1820
+ if (node != NULL) {
1821
+ if ((node->type == XML_ATTRIBUTE_NODE) ||
1822
+ (node->type == XML_NAMESPACE_DECL)) {
1823
+ xmlXPathFreeObject(obj);
1824
+ xmlXPtrFreeLocationSet(newset);
1825
+ XP_ERROR(XPTR_SYNTAX_ERROR);
1826
+ }
1827
+ point = xmlXPtrNewPoint(node, tmp->index);
1828
+ }
1829
+ break;
1830
+ }
1831
+ default:
1832
+ /*** Should we raise an error ?
1833
+ xmlXPathFreeObject(obj);
1834
+ xmlXPathFreeObject(newset);
1835
+ XP_ERROR(XPATH_INVALID_TYPE)
1836
+ ***/
1837
+ break;
1838
+ }
1839
+ if (point != NULL)
1840
+ xmlXPtrLocationSetAdd(newset, point);
1841
+ }
1842
+ }
1843
+ xmlXPathFreeObject(obj);
1844
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
1845
+ }
1846
+
1847
+ /**
1848
+ * xmlXPtrEndPointFunction:
1849
+ * @ctxt: the XPointer Parser context
1850
+ * @nargs: the number of args
1851
+ *
1852
+ * Function implementing end-point() operation
1853
+ * as described in 5.4.3
1854
+ * ----------------------------
1855
+ * location-set end-point(location-set)
1856
+ *
1857
+ * For each location x in the argument location-set, end-point adds a
1858
+ * location of type point to the result location-set. That point represents
1859
+ * the end point of location x and is determined by the following rules:
1860
+ *
1861
+ * - If x is of type point, the resulting point is x.
1862
+ * - If x is of type range, the resulting point is the end point of x.
1863
+ * - If x is of type root or element, the container node of the resulting
1864
+ * point is x and the index is the number of location children of x.
1865
+ * - If x is of type text, comment, or processing instruction, the container
1866
+ * node of the resulting point is x and the index is the length of the
1867
+ * string-value of x.
1868
+ * - If x is of type attribute or namespace, the function must signal a
1869
+ * syntax error.
1870
+ * ----------------------------
1871
+ */
1872
+ static void
1873
+ xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1874
+ xmlXPathObjectPtr tmp, obj, point;
1875
+ xmlLocationSetPtr newset = NULL;
1876
+ xmlLocationSetPtr oldset = NULL;
1877
+
1878
+ CHECK_ARITY(1);
1879
+ if ((ctxt->value == NULL) ||
1880
+ ((ctxt->value->type != XPATH_LOCATIONSET) &&
1881
+ (ctxt->value->type != XPATH_NODESET)))
1882
+ XP_ERROR(XPATH_INVALID_TYPE)
1883
+
1884
+ obj = valuePop(ctxt);
1885
+ if (obj->type == XPATH_NODESET) {
1886
+ /*
1887
+ * First convert to a location set
1888
+ */
1889
+ tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval);
1890
+ xmlXPathFreeObject(obj);
1891
+ if (tmp == NULL)
1892
+ XP_ERROR(XPATH_MEMORY_ERROR)
1893
+ obj = tmp;
1894
+ }
1895
+
1896
+ newset = xmlXPtrLocationSetCreate(NULL);
1897
+ if (newset == NULL) {
1898
+ xmlXPathFreeObject(obj);
1899
+ XP_ERROR(XPATH_MEMORY_ERROR);
1900
+ }
1901
+ oldset = (xmlLocationSetPtr) obj->user;
1902
+ if (oldset != NULL) {
1903
+ int i;
1904
+
1905
+ for (i = 0; i < oldset->locNr; i++) {
1906
+ tmp = oldset->locTab[i];
1907
+ if (tmp == NULL)
1908
+ continue;
1909
+ point = NULL;
1910
+ switch (tmp->type) {
1911
+ case XPATH_POINT:
1912
+ point = xmlXPtrNewPoint(tmp->user, tmp->index);
1913
+ break;
1914
+ case XPATH_RANGE: {
1915
+ xmlNodePtr node = tmp->user2;
1916
+ if (node != NULL) {
1917
+ if ((node->type == XML_ATTRIBUTE_NODE) ||
1918
+ (node->type == XML_NAMESPACE_DECL)) {
1919
+ xmlXPathFreeObject(obj);
1920
+ xmlXPtrFreeLocationSet(newset);
1921
+ XP_ERROR(XPTR_SYNTAX_ERROR);
1922
+ }
1923
+ point = xmlXPtrNewPoint(node, tmp->index2);
1924
+ } else if (tmp->user == NULL) {
1925
+ point = xmlXPtrNewPoint(node,
1926
+ xmlXPtrNbLocChildren(node));
1927
+ }
1928
+ break;
1929
+ }
1930
+ default:
1931
+ /*** Should we raise an error ?
1932
+ xmlXPathFreeObject(obj);
1933
+ xmlXPathFreeObject(newset);
1934
+ XP_ERROR(XPATH_INVALID_TYPE)
1935
+ ***/
1936
+ break;
1937
+ }
1938
+ if (point != NULL)
1939
+ xmlXPtrLocationSetAdd(newset, point);
1940
+ }
1941
+ }
1942
+ xmlXPathFreeObject(obj);
1943
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
1944
+ }
1945
+
1946
+
1947
+ /**
1948
+ * xmlXPtrCoveringRange:
1949
+ * @ctxt: the XPointer Parser context
1950
+ * @loc: the location for which the covering range must be computed
1951
+ *
1952
+ * A covering range is a range that wholly encompasses a location
1953
+ * Section 5.3.3. Covering Ranges for All Location Types
1954
+ * http://www.w3.org/TR/xptr#N2267
1955
+ *
1956
+ * Returns a new location or NULL in case of error
1957
+ */
1958
+ static xmlXPathObjectPtr
1959
+ xmlXPtrCoveringRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
1960
+ if (loc == NULL)
1961
+ return(NULL);
1962
+ if ((ctxt == NULL) || (ctxt->context == NULL) ||
1963
+ (ctxt->context->doc == NULL))
1964
+ return(NULL);
1965
+ switch (loc->type) {
1966
+ case XPATH_POINT:
1967
+ return(xmlXPtrNewRange(loc->user, loc->index,
1968
+ loc->user, loc->index));
1969
+ case XPATH_RANGE:
1970
+ if (loc->user2 != NULL) {
1971
+ return(xmlXPtrNewRange(loc->user, loc->index,
1972
+ loc->user2, loc->index2));
1973
+ } else {
1974
+ xmlNodePtr node = (xmlNodePtr) loc->user;
1975
+ if (node == (xmlNodePtr) ctxt->context->doc) {
1976
+ return(xmlXPtrNewRange(node, 0, node,
1977
+ xmlXPtrGetArity(node)));
1978
+ } else {
1979
+ switch (node->type) {
1980
+ case XML_ATTRIBUTE_NODE:
1981
+ /* !!! our model is slightly different than XPath */
1982
+ return(xmlXPtrNewRange(node, 0, node,
1983
+ xmlXPtrGetArity(node)));
1984
+ case XML_ELEMENT_NODE:
1985
+ case XML_TEXT_NODE:
1986
+ case XML_CDATA_SECTION_NODE:
1987
+ case XML_ENTITY_REF_NODE:
1988
+ case XML_PI_NODE:
1989
+ case XML_COMMENT_NODE:
1990
+ case XML_DOCUMENT_NODE:
1991
+ case XML_NOTATION_NODE:
1992
+ case XML_HTML_DOCUMENT_NODE: {
1993
+ int indx = xmlXPtrGetIndex(node);
1994
+
1995
+ node = node->parent;
1996
+ return(xmlXPtrNewRange(node, indx - 1,
1997
+ node, indx + 1));
1998
+ }
1999
+ default:
2000
+ return(NULL);
2001
+ }
2002
+ }
2003
+ }
2004
+ default:
2005
+ TODO /* missed one case ??? */
2006
+ }
2007
+ return(NULL);
2008
+ }
2009
+
2010
+ /**
2011
+ * xmlXPtrRangeFunction:
2012
+ * @ctxt: the XPointer Parser context
2013
+ * @nargs: the number of args
2014
+ *
2015
+ * Function implementing the range() function 5.4.3
2016
+ * location-set range(location-set )
2017
+ *
2018
+ * The range function returns ranges covering the locations in
2019
+ * the argument location-set. For each location x in the argument
2020
+ * location-set, a range location representing the covering range of
2021
+ * x is added to the result location-set.
2022
+ */
2023
+ static void
2024
+ xmlXPtrRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2025
+ int i;
2026
+ xmlXPathObjectPtr set;
2027
+ xmlLocationSetPtr oldset;
2028
+ xmlLocationSetPtr newset;
2029
+
2030
+ CHECK_ARITY(1);
2031
+ if ((ctxt->value == NULL) ||
2032
+ ((ctxt->value->type != XPATH_LOCATIONSET) &&
2033
+ (ctxt->value->type != XPATH_NODESET)))
2034
+ XP_ERROR(XPATH_INVALID_TYPE)
2035
+
2036
+ set = valuePop(ctxt);
2037
+ if (set->type == XPATH_NODESET) {
2038
+ xmlXPathObjectPtr tmp;
2039
+
2040
+ /*
2041
+ * First convert to a location set
2042
+ */
2043
+ tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2044
+ xmlXPathFreeObject(set);
2045
+ if (tmp == NULL)
2046
+ XP_ERROR(XPATH_MEMORY_ERROR)
2047
+ set = tmp;
2048
+ }
2049
+ oldset = (xmlLocationSetPtr) set->user;
2050
+
2051
+ /*
2052
+ * The loop is to compute the covering range for each item and add it
2053
+ */
2054
+ newset = xmlXPtrLocationSetCreate(NULL);
2055
+ if (newset == NULL) {
2056
+ xmlXPathFreeObject(set);
2057
+ XP_ERROR(XPATH_MEMORY_ERROR);
2058
+ }
2059
+ if (oldset != NULL) {
2060
+ for (i = 0;i < oldset->locNr;i++) {
2061
+ xmlXPtrLocationSetAdd(newset,
2062
+ xmlXPtrCoveringRange(ctxt, oldset->locTab[i]));
2063
+ }
2064
+ }
2065
+
2066
+ /*
2067
+ * Save the new value and cleanup
2068
+ */
2069
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2070
+ xmlXPathFreeObject(set);
2071
+ }
2072
+
2073
+ /**
2074
+ * xmlXPtrInsideRange:
2075
+ * @ctxt: the XPointer Parser context
2076
+ * @loc: the location for which the inside range must be computed
2077
+ *
2078
+ * A inside range is a range described in the range-inside() description
2079
+ *
2080
+ * Returns a new location or NULL in case of error
2081
+ */
2082
+ static xmlXPathObjectPtr
2083
+ xmlXPtrInsideRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
2084
+ if (loc == NULL)
2085
+ return(NULL);
2086
+ if ((ctxt == NULL) || (ctxt->context == NULL) ||
2087
+ (ctxt->context->doc == NULL))
2088
+ return(NULL);
2089
+ switch (loc->type) {
2090
+ case XPATH_POINT: {
2091
+ xmlNodePtr node = (xmlNodePtr) loc->user;
2092
+ switch (node->type) {
2093
+ case XML_PI_NODE:
2094
+ case XML_COMMENT_NODE:
2095
+ case XML_TEXT_NODE:
2096
+ case XML_CDATA_SECTION_NODE: {
2097
+ if (node->content == NULL) {
2098
+ return(xmlXPtrNewRange(node, 0, node, 0));
2099
+ } else {
2100
+ return(xmlXPtrNewRange(node, 0, node,
2101
+ xmlStrlen(node->content)));
2102
+ }
2103
+ }
2104
+ case XML_ATTRIBUTE_NODE:
2105
+ case XML_ELEMENT_NODE:
2106
+ case XML_ENTITY_REF_NODE:
2107
+ case XML_DOCUMENT_NODE:
2108
+ case XML_NOTATION_NODE:
2109
+ case XML_HTML_DOCUMENT_NODE: {
2110
+ return(xmlXPtrNewRange(node, 0, node,
2111
+ xmlXPtrGetArity(node)));
2112
+ }
2113
+ default:
2114
+ break;
2115
+ }
2116
+ return(NULL);
2117
+ }
2118
+ case XPATH_RANGE: {
2119
+ xmlNodePtr node = (xmlNodePtr) loc->user;
2120
+ if (loc->user2 != NULL) {
2121
+ return(xmlXPtrNewRange(node, loc->index,
2122
+ loc->user2, loc->index2));
2123
+ } else {
2124
+ switch (node->type) {
2125
+ case XML_PI_NODE:
2126
+ case XML_COMMENT_NODE:
2127
+ case XML_TEXT_NODE:
2128
+ case XML_CDATA_SECTION_NODE: {
2129
+ if (node->content == NULL) {
2130
+ return(xmlXPtrNewRange(node, 0, node, 0));
2131
+ } else {
2132
+ return(xmlXPtrNewRange(node, 0, node,
2133
+ xmlStrlen(node->content)));
2134
+ }
2135
+ }
2136
+ case XML_ATTRIBUTE_NODE:
2137
+ case XML_ELEMENT_NODE:
2138
+ case XML_ENTITY_REF_NODE:
2139
+ case XML_DOCUMENT_NODE:
2140
+ case XML_NOTATION_NODE:
2141
+ case XML_HTML_DOCUMENT_NODE: {
2142
+ return(xmlXPtrNewRange(node, 0, node,
2143
+ xmlXPtrGetArity(node)));
2144
+ }
2145
+ default:
2146
+ break;
2147
+ }
2148
+ return(NULL);
2149
+ }
2150
+ }
2151
+ default:
2152
+ TODO /* missed one case ??? */
2153
+ }
2154
+ return(NULL);
2155
+ }
2156
+
2157
+ /**
2158
+ * xmlXPtrRangeInsideFunction:
2159
+ * @ctxt: the XPointer Parser context
2160
+ * @nargs: the number of args
2161
+ *
2162
+ * Function implementing the range-inside() function 5.4.3
2163
+ * location-set range-inside(location-set )
2164
+ *
2165
+ * The range-inside function returns ranges covering the contents of
2166
+ * the locations in the argument location-set. For each location x in
2167
+ * the argument location-set, a range location is added to the result
2168
+ * location-set. If x is a range location, then x is added to the
2169
+ * result location-set. If x is not a range location, then x is used
2170
+ * as the container location of the start and end points of the range
2171
+ * location to be added; the index of the start point of the range is
2172
+ * zero; if the end point is a character point then its index is the
2173
+ * length of the string-value of x, and otherwise is the number of
2174
+ * location children of x.
2175
+ *
2176
+ */
2177
+ static void
2178
+ xmlXPtrRangeInsideFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2179
+ int i;
2180
+ xmlXPathObjectPtr set;
2181
+ xmlLocationSetPtr oldset;
2182
+ xmlLocationSetPtr newset;
2183
+
2184
+ CHECK_ARITY(1);
2185
+ if ((ctxt->value == NULL) ||
2186
+ ((ctxt->value->type != XPATH_LOCATIONSET) &&
2187
+ (ctxt->value->type != XPATH_NODESET)))
2188
+ XP_ERROR(XPATH_INVALID_TYPE)
2189
+
2190
+ set = valuePop(ctxt);
2191
+ if (set->type == XPATH_NODESET) {
2192
+ xmlXPathObjectPtr tmp;
2193
+
2194
+ /*
2195
+ * First convert to a location set
2196
+ */
2197
+ tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2198
+ xmlXPathFreeObject(set);
2199
+ if (tmp == NULL)
2200
+ XP_ERROR(XPATH_MEMORY_ERROR)
2201
+ set = tmp;
2202
+ }
2203
+
2204
+ /*
2205
+ * The loop is to compute the covering range for each item and add it
2206
+ */
2207
+ newset = xmlXPtrLocationSetCreate(NULL);
2208
+ if (newset == NULL) {
2209
+ xmlXPathFreeObject(set);
2210
+ XP_ERROR(XPATH_MEMORY_ERROR);
2211
+ }
2212
+ oldset = (xmlLocationSetPtr) set->user;
2213
+ if (oldset != NULL) {
2214
+ for (i = 0;i < oldset->locNr;i++) {
2215
+ xmlXPtrLocationSetAdd(newset,
2216
+ xmlXPtrInsideRange(ctxt, oldset->locTab[i]));
2217
+ }
2218
+ }
2219
+
2220
+ /*
2221
+ * Save the new value and cleanup
2222
+ */
2223
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2224
+ xmlXPathFreeObject(set);
2225
+ }
2226
+
2227
+ /**
2228
+ * xmlXPtrRangeToFunction:
2229
+ * @ctxt: the XPointer Parser context
2230
+ * @nargs: the number of args
2231
+ *
2232
+ * Implement the range-to() XPointer function
2233
+ *
2234
+ * Obsolete. range-to is not a real function but a special type of location
2235
+ * step which is handled in xpath.c.
2236
+ */
2237
+ void
2238
+ xmlXPtrRangeToFunction(xmlXPathParserContextPtr ctxt,
2239
+ int nargs ATTRIBUTE_UNUSED) {
2240
+ XP_ERROR(XPATH_EXPR_ERROR);
2241
+ }
2242
+
2243
+ /**
2244
+ * xmlXPtrAdvanceNode:
2245
+ * @cur: the node
2246
+ * @level: incremented/decremented to show level in tree
2247
+ *
2248
+ * Advance to the next element or text node in document order
2249
+ * TODO: add a stack for entering/exiting entities
2250
+ *
2251
+ * Returns -1 in case of failure, 0 otherwise
2252
+ */
2253
+ xmlNodePtr
2254
+ xmlXPtrAdvanceNode(xmlNodePtr cur, int *level) {
2255
+ next:
2256
+ if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2257
+ return(NULL);
2258
+ if (cur->children != NULL) {
2259
+ cur = cur->children ;
2260
+ if (level != NULL)
2261
+ (*level)++;
2262
+ goto found;
2263
+ }
2264
+ skip: /* This label should only be needed if something is wrong! */
2265
+ if (cur->next != NULL) {
2266
+ cur = cur->next;
2267
+ goto found;
2268
+ }
2269
+ do {
2270
+ cur = cur->parent;
2271
+ if (level != NULL)
2272
+ (*level)--;
2273
+ if (cur == NULL) return(NULL);
2274
+ if (cur->next != NULL) {
2275
+ cur = cur->next;
2276
+ goto found;
2277
+ }
2278
+ } while (cur != NULL);
2279
+
2280
+ found:
2281
+ if ((cur->type != XML_ELEMENT_NODE) &&
2282
+ (cur->type != XML_TEXT_NODE) &&
2283
+ (cur->type != XML_DOCUMENT_NODE) &&
2284
+ (cur->type != XML_HTML_DOCUMENT_NODE) &&
2285
+ (cur->type != XML_CDATA_SECTION_NODE)) {
2286
+ if (cur->type == XML_ENTITY_REF_NODE) { /* Shouldn't happen */
2287
+ TODO
2288
+ goto skip;
2289
+ }
2290
+ goto next;
2291
+ }
2292
+ return(cur);
2293
+ }
2294
+
2295
+ /**
2296
+ * xmlXPtrAdvanceChar:
2297
+ * @node: the node
2298
+ * @indx: the indx
2299
+ * @bytes: the number of bytes
2300
+ *
2301
+ * Advance a point of the associated number of bytes (not UTF8 chars)
2302
+ *
2303
+ * Returns -1 in case of failure, 0 otherwise
2304
+ */
2305
+ static int
2306
+ xmlXPtrAdvanceChar(xmlNodePtr *node, int *indx, int bytes) {
2307
+ xmlNodePtr cur;
2308
+ int pos;
2309
+ int len;
2310
+
2311
+ if ((node == NULL) || (indx == NULL))
2312
+ return(-1);
2313
+ cur = *node;
2314
+ if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
2315
+ return(-1);
2316
+ pos = *indx;
2317
+
2318
+ while (bytes >= 0) {
2319
+ /*
2320
+ * First position to the beginning of the first text node
2321
+ * corresponding to this point
2322
+ */
2323
+ while ((cur != NULL) &&
2324
+ ((cur->type == XML_ELEMENT_NODE) ||
2325
+ (cur->type == XML_DOCUMENT_NODE) ||
2326
+ (cur->type == XML_HTML_DOCUMENT_NODE))) {
2327
+ if (pos > 0) {
2328
+ cur = xmlXPtrGetNthChild(cur, pos);
2329
+ pos = 0;
2330
+ } else {
2331
+ cur = xmlXPtrAdvanceNode(cur, NULL);
2332
+ pos = 0;
2333
+ }
2334
+ }
2335
+
2336
+ if (cur == NULL) {
2337
+ *node = NULL;
2338
+ *indx = 0;
2339
+ return(-1);
2340
+ }
2341
+
2342
+ /*
2343
+ * if there is no move needed return the current value.
2344
+ */
2345
+ if (pos == 0) pos = 1;
2346
+ if (bytes == 0) {
2347
+ *node = cur;
2348
+ *indx = pos;
2349
+ return(0);
2350
+ }
2351
+ /*
2352
+ * We should have a text (or cdata) node ...
2353
+ */
2354
+ len = 0;
2355
+ if ((cur->type != XML_ELEMENT_NODE) &&
2356
+ (cur->content != NULL)) {
2357
+ len = xmlStrlen(cur->content);
2358
+ }
2359
+ if (pos > len) {
2360
+ /* Strange, the indx in the text node is greater than it's len */
2361
+ STRANGE
2362
+ pos = len;
2363
+ }
2364
+ if (pos + bytes >= len) {
2365
+ bytes -= (len - pos);
2366
+ cur = xmlXPtrAdvanceNode(cur, NULL);
2367
+ pos = 0;
2368
+ } else if (pos + bytes < len) {
2369
+ pos += bytes;
2370
+ *node = cur;
2371
+ *indx = pos;
2372
+ return(0);
2373
+ }
2374
+ }
2375
+ return(-1);
2376
+ }
2377
+
2378
+ /**
2379
+ * xmlXPtrMatchString:
2380
+ * @string: the string to search
2381
+ * @start: the start textnode
2382
+ * @startindex: the start index
2383
+ * @end: the end textnode IN/OUT
2384
+ * @endindex: the end index IN/OUT
2385
+ *
2386
+ * Check whether the document contains @string at the position
2387
+ * (@start, @startindex) and limited by the (@end, @endindex) point
2388
+ *
2389
+ * Returns -1 in case of failure, 0 if not found, 1 if found in which case
2390
+ * (@start, @startindex) will indicate the position of the beginning
2391
+ * of the range and (@end, @endindex) will indicate the end
2392
+ * of the range
2393
+ */
2394
+ static int
2395
+ xmlXPtrMatchString(const xmlChar *string, xmlNodePtr start, int startindex,
2396
+ xmlNodePtr *end, int *endindex) {
2397
+ xmlNodePtr cur;
2398
+ int pos; /* 0 based */
2399
+ int len; /* in bytes */
2400
+ int stringlen; /* in bytes */
2401
+ int match;
2402
+
2403
+ if (string == NULL)
2404
+ return(-1);
2405
+ if ((start == NULL) || (start->type == XML_NAMESPACE_DECL))
2406
+ return(-1);
2407
+ if ((end == NULL) || (*end == NULL) ||
2408
+ ((*end)->type == XML_NAMESPACE_DECL) || (endindex == NULL))
2409
+ return(-1);
2410
+ cur = start;
2411
+ pos = startindex - 1;
2412
+ stringlen = xmlStrlen(string);
2413
+
2414
+ while (stringlen > 0) {
2415
+ if ((cur == *end) && (pos + stringlen > *endindex))
2416
+ return(0);
2417
+
2418
+ if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
2419
+ len = xmlStrlen(cur->content);
2420
+ if (len >= pos + stringlen) {
2421
+ match = (!xmlStrncmp(&cur->content[pos], string, stringlen));
2422
+ if (match) {
2423
+ #ifdef DEBUG_RANGES
2424
+ xmlGenericError(xmlGenericErrorContext,
2425
+ "found range %d bytes at index %d of ->",
2426
+ stringlen, pos + 1);
2427
+ xmlDebugDumpString(stdout, cur->content);
2428
+ xmlGenericError(xmlGenericErrorContext, "\n");
2429
+ #endif
2430
+ *end = cur;
2431
+ *endindex = pos + stringlen;
2432
+ return(1);
2433
+ } else {
2434
+ return(0);
2435
+ }
2436
+ } else {
2437
+ int sub = len - pos;
2438
+ match = (!xmlStrncmp(&cur->content[pos], string, sub));
2439
+ if (match) {
2440
+ #ifdef DEBUG_RANGES
2441
+ xmlGenericError(xmlGenericErrorContext,
2442
+ "found subrange %d bytes at index %d of ->",
2443
+ sub, pos + 1);
2444
+ xmlDebugDumpString(stdout, cur->content);
2445
+ xmlGenericError(xmlGenericErrorContext, "\n");
2446
+ #endif
2447
+ string = &string[sub];
2448
+ stringlen -= sub;
2449
+ } else {
2450
+ return(0);
2451
+ }
2452
+ }
2453
+ }
2454
+ cur = xmlXPtrAdvanceNode(cur, NULL);
2455
+ if (cur == NULL)
2456
+ return(0);
2457
+ pos = 0;
2458
+ }
2459
+ return(1);
2460
+ }
2461
+
2462
+ /**
2463
+ * xmlXPtrSearchString:
2464
+ * @string: the string to search
2465
+ * @start: the start textnode IN/OUT
2466
+ * @startindex: the start index IN/OUT
2467
+ * @end: the end textnode
2468
+ * @endindex: the end index
2469
+ *
2470
+ * Search the next occurrence of @string within the document content
2471
+ * until the (@end, @endindex) point is reached
2472
+ *
2473
+ * Returns -1 in case of failure, 0 if not found, 1 if found in which case
2474
+ * (@start, @startindex) will indicate the position of the beginning
2475
+ * of the range and (@end, @endindex) will indicate the end
2476
+ * of the range
2477
+ */
2478
+ static int
2479
+ xmlXPtrSearchString(const xmlChar *string, xmlNodePtr *start, int *startindex,
2480
+ xmlNodePtr *end, int *endindex) {
2481
+ xmlNodePtr cur;
2482
+ const xmlChar *str;
2483
+ int pos; /* 0 based */
2484
+ int len; /* in bytes */
2485
+ xmlChar first;
2486
+
2487
+ if (string == NULL)
2488
+ return(-1);
2489
+ if ((start == NULL) || (*start == NULL) ||
2490
+ ((*start)->type == XML_NAMESPACE_DECL) || (startindex == NULL))
2491
+ return(-1);
2492
+ if ((end == NULL) || (endindex == NULL))
2493
+ return(-1);
2494
+ cur = *start;
2495
+ pos = *startindex - 1;
2496
+ first = string[0];
2497
+
2498
+ while (cur != NULL) {
2499
+ if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) {
2500
+ len = xmlStrlen(cur->content);
2501
+ while (pos <= len) {
2502
+ if (first != 0) {
2503
+ str = xmlStrchr(&cur->content[pos], first);
2504
+ if (str != NULL) {
2505
+ pos = (str - (xmlChar *)(cur->content));
2506
+ #ifdef DEBUG_RANGES
2507
+ xmlGenericError(xmlGenericErrorContext,
2508
+ "found '%c' at index %d of ->",
2509
+ first, pos + 1);
2510
+ xmlDebugDumpString(stdout, cur->content);
2511
+ xmlGenericError(xmlGenericErrorContext, "\n");
2512
+ #endif
2513
+ if (xmlXPtrMatchString(string, cur, pos + 1,
2514
+ end, endindex)) {
2515
+ *start = cur;
2516
+ *startindex = pos + 1;
2517
+ return(1);
2518
+ }
2519
+ pos++;
2520
+ } else {
2521
+ pos = len + 1;
2522
+ }
2523
+ } else {
2524
+ /*
2525
+ * An empty string is considered to match before each
2526
+ * character of the string-value and after the final
2527
+ * character.
2528
+ */
2529
+ #ifdef DEBUG_RANGES
2530
+ xmlGenericError(xmlGenericErrorContext,
2531
+ "found '' at index %d of ->",
2532
+ pos + 1);
2533
+ xmlDebugDumpString(stdout, cur->content);
2534
+ xmlGenericError(xmlGenericErrorContext, "\n");
2535
+ #endif
2536
+ *start = cur;
2537
+ *startindex = pos + 1;
2538
+ *end = cur;
2539
+ *endindex = pos + 1;
2540
+ return(1);
2541
+ }
2542
+ }
2543
+ }
2544
+ if ((cur == *end) && (pos >= *endindex))
2545
+ return(0);
2546
+ cur = xmlXPtrAdvanceNode(cur, NULL);
2547
+ if (cur == NULL)
2548
+ return(0);
2549
+ pos = 1;
2550
+ }
2551
+ return(0);
2552
+ }
2553
+
2554
+ /**
2555
+ * xmlXPtrGetLastChar:
2556
+ * @node: the node
2557
+ * @index: the index
2558
+ *
2559
+ * Computes the point coordinates of the last char of this point
2560
+ *
2561
+ * Returns -1 in case of failure, 0 otherwise
2562
+ */
2563
+ static int
2564
+ xmlXPtrGetLastChar(xmlNodePtr *node, int *indx) {
2565
+ xmlNodePtr cur;
2566
+ int pos, len = 0;
2567
+
2568
+ if ((node == NULL) || (*node == NULL) ||
2569
+ ((*node)->type == XML_NAMESPACE_DECL) || (indx == NULL))
2570
+ return(-1);
2571
+ cur = *node;
2572
+ pos = *indx;
2573
+
2574
+ if ((cur->type == XML_ELEMENT_NODE) ||
2575
+ (cur->type == XML_DOCUMENT_NODE) ||
2576
+ (cur->type == XML_HTML_DOCUMENT_NODE)) {
2577
+ if (pos > 0) {
2578
+ cur = xmlXPtrGetNthChild(cur, pos);
2579
+ }
2580
+ }
2581
+ while (cur != NULL) {
2582
+ if (cur->last != NULL)
2583
+ cur = cur->last;
2584
+ else if ((cur->type != XML_ELEMENT_NODE) &&
2585
+ (cur->content != NULL)) {
2586
+ len = xmlStrlen(cur->content);
2587
+ break;
2588
+ } else {
2589
+ return(-1);
2590
+ }
2591
+ }
2592
+ if (cur == NULL)
2593
+ return(-1);
2594
+ *node = cur;
2595
+ *indx = len;
2596
+ return(0);
2597
+ }
2598
+
2599
+ /**
2600
+ * xmlXPtrGetStartPoint:
2601
+ * @obj: an range
2602
+ * @node: the resulting node
2603
+ * @indx: the resulting index
2604
+ *
2605
+ * read the object and return the start point coordinates.
2606
+ *
2607
+ * Returns -1 in case of failure, 0 otherwise
2608
+ */
2609
+ static int
2610
+ xmlXPtrGetStartPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *indx) {
2611
+ if ((obj == NULL) || (node == NULL) || (indx == NULL))
2612
+ return(-1);
2613
+
2614
+ switch (obj->type) {
2615
+ case XPATH_POINT:
2616
+ *node = obj->user;
2617
+ if (obj->index <= 0)
2618
+ *indx = 0;
2619
+ else
2620
+ *indx = obj->index;
2621
+ return(0);
2622
+ case XPATH_RANGE:
2623
+ *node = obj->user;
2624
+ if (obj->index <= 0)
2625
+ *indx = 0;
2626
+ else
2627
+ *indx = obj->index;
2628
+ return(0);
2629
+ default:
2630
+ break;
2631
+ }
2632
+ return(-1);
2633
+ }
2634
+
2635
+ /**
2636
+ * xmlXPtrGetEndPoint:
2637
+ * @obj: an range
2638
+ * @node: the resulting node
2639
+ * @indx: the resulting indx
2640
+ *
2641
+ * read the object and return the end point coordinates.
2642
+ *
2643
+ * Returns -1 in case of failure, 0 otherwise
2644
+ */
2645
+ static int
2646
+ xmlXPtrGetEndPoint(xmlXPathObjectPtr obj, xmlNodePtr *node, int *indx) {
2647
+ if ((obj == NULL) || (node == NULL) || (indx == NULL))
2648
+ return(-1);
2649
+
2650
+ switch (obj->type) {
2651
+ case XPATH_POINT:
2652
+ *node = obj->user;
2653
+ if (obj->index <= 0)
2654
+ *indx = 0;
2655
+ else
2656
+ *indx = obj->index;
2657
+ return(0);
2658
+ case XPATH_RANGE:
2659
+ *node = obj->user;
2660
+ if (obj->index <= 0)
2661
+ *indx = 0;
2662
+ else
2663
+ *indx = obj->index;
2664
+ return(0);
2665
+ default:
2666
+ break;
2667
+ }
2668
+ return(-1);
2669
+ }
2670
+
2671
+ /**
2672
+ * xmlXPtrStringRangeFunction:
2673
+ * @ctxt: the XPointer Parser context
2674
+ * @nargs: the number of args
2675
+ *
2676
+ * Function implementing the string-range() function
2677
+ * range as described in 5.4.2
2678
+ *
2679
+ * ------------------------------
2680
+ * [Definition: For each location in the location-set argument,
2681
+ * string-range returns a set of string ranges, a set of substrings in a
2682
+ * string. Specifically, the string-value of the location is searched for
2683
+ * substrings that match the string argument, and the resulting location-set
2684
+ * will contain a range location for each non-overlapping match.]
2685
+ * An empty string is considered to match before each character of the
2686
+ * string-value and after the final character. Whitespace in a string
2687
+ * is matched literally, with no normalization except that provided by
2688
+ * XML for line ends. The third argument gives the position of the first
2689
+ * character to be in the resulting range, relative to the start of the
2690
+ * match. The default value is 1, which makes the range start immediately
2691
+ * before the first character of the matched string. The fourth argument
2692
+ * gives the number of characters in the range; the default is that the
2693
+ * range extends to the end of the matched string.
2694
+ *
2695
+ * Element boundaries, as well as entire embedded nodes such as processing
2696
+ * instructions and comments, are ignored as defined in [XPath].
2697
+ *
2698
+ * If the string in the second argument is not found in the string-value
2699
+ * of the location, or if a value in the third or fourth argument indicates
2700
+ * a string that is beyond the beginning or end of the document, the
2701
+ * expression fails.
2702
+ *
2703
+ * The points of the range-locations in the returned location-set will
2704
+ * all be character points.
2705
+ * ------------------------------
2706
+ */
2707
+ static void
2708
+ xmlXPtrStringRangeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
2709
+ int i, startindex, endindex = 0, fendindex;
2710
+ xmlNodePtr start, end = 0, fend;
2711
+ xmlXPathObjectPtr set = NULL;
2712
+ xmlLocationSetPtr oldset;
2713
+ xmlLocationSetPtr newset = NULL;
2714
+ xmlXPathObjectPtr string = NULL;
2715
+ xmlXPathObjectPtr position = NULL;
2716
+ xmlXPathObjectPtr number = NULL;
2717
+ int found, pos = 0, num = 0;
2718
+
2719
+ /*
2720
+ * Grab the arguments
2721
+ */
2722
+ if ((nargs < 2) || (nargs > 4))
2723
+ XP_ERROR(XPATH_INVALID_ARITY);
2724
+
2725
+ if (nargs >= 4) {
2726
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
2727
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2728
+ goto error;
2729
+ }
2730
+ number = valuePop(ctxt);
2731
+ if (number != NULL)
2732
+ num = (int) number->floatval;
2733
+ }
2734
+ if (nargs >= 3) {
2735
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NUMBER)) {
2736
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2737
+ goto error;
2738
+ }
2739
+ position = valuePop(ctxt);
2740
+ if (position != NULL)
2741
+ pos = (int) position->floatval;
2742
+ }
2743
+ if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
2744
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2745
+ goto error;
2746
+ }
2747
+ string = valuePop(ctxt);
2748
+ if ((ctxt->value == NULL) ||
2749
+ ((ctxt->value->type != XPATH_LOCATIONSET) &&
2750
+ (ctxt->value->type != XPATH_NODESET))) {
2751
+ xmlXPathErr(ctxt, XPATH_INVALID_TYPE);
2752
+ goto error;
2753
+ }
2754
+ set = valuePop(ctxt);
2755
+ newset = xmlXPtrLocationSetCreate(NULL);
2756
+ if (newset == NULL) {
2757
+ xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
2758
+ goto error;
2759
+ }
2760
+ if (set->nodesetval == NULL) {
2761
+ goto error;
2762
+ }
2763
+ if (set->type == XPATH_NODESET) {
2764
+ xmlXPathObjectPtr tmp;
2765
+
2766
+ /*
2767
+ * First convert to a location set
2768
+ */
2769
+ tmp = xmlXPtrNewLocationSetNodeSet(set->nodesetval);
2770
+ xmlXPathFreeObject(set);
2771
+ if (tmp == NULL) {
2772
+ xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
2773
+ goto error;
2774
+ }
2775
+ set = tmp;
2776
+ }
2777
+ oldset = (xmlLocationSetPtr) set->user;
2778
+
2779
+ /*
2780
+ * The loop is to search for each element in the location set
2781
+ * the list of location set corresponding to that search
2782
+ */
2783
+ for (i = 0;i < oldset->locNr;i++) {
2784
+ #ifdef DEBUG_RANGES
2785
+ xmlXPathDebugDumpObject(stdout, oldset->locTab[i], 0);
2786
+ #endif
2787
+
2788
+ xmlXPtrGetStartPoint(oldset->locTab[i], &start, &startindex);
2789
+ xmlXPtrGetEndPoint(oldset->locTab[i], &end, &endindex);
2790
+ xmlXPtrAdvanceChar(&start, &startindex, 0);
2791
+ xmlXPtrGetLastChar(&end, &endindex);
2792
+
2793
+ #ifdef DEBUG_RANGES
2794
+ xmlGenericError(xmlGenericErrorContext,
2795
+ "from index %d of ->", startindex);
2796
+ xmlDebugDumpString(stdout, start->content);
2797
+ xmlGenericError(xmlGenericErrorContext, "\n");
2798
+ xmlGenericError(xmlGenericErrorContext,
2799
+ "to index %d of ->", endindex);
2800
+ xmlDebugDumpString(stdout, end->content);
2801
+ xmlGenericError(xmlGenericErrorContext, "\n");
2802
+ #endif
2803
+ do {
2804
+ fend = end;
2805
+ fendindex = endindex;
2806
+ found = xmlXPtrSearchString(string->stringval, &start, &startindex,
2807
+ &fend, &fendindex);
2808
+ if (found == 1) {
2809
+ if (position == NULL) {
2810
+ xmlXPtrLocationSetAdd(newset,
2811
+ xmlXPtrNewRange(start, startindex, fend, fendindex));
2812
+ } else if (xmlXPtrAdvanceChar(&start, &startindex,
2813
+ pos - 1) == 0) {
2814
+ if ((number != NULL) && (num > 0)) {
2815
+ int rindx;
2816
+ xmlNodePtr rend;
2817
+ rend = start;
2818
+ rindx = startindex - 1;
2819
+ if (xmlXPtrAdvanceChar(&rend, &rindx,
2820
+ num) == 0) {
2821
+ xmlXPtrLocationSetAdd(newset,
2822
+ xmlXPtrNewRange(start, startindex,
2823
+ rend, rindx));
2824
+ }
2825
+ } else if ((number != NULL) && (num <= 0)) {
2826
+ xmlXPtrLocationSetAdd(newset,
2827
+ xmlXPtrNewRange(start, startindex,
2828
+ start, startindex));
2829
+ } else {
2830
+ xmlXPtrLocationSetAdd(newset,
2831
+ xmlXPtrNewRange(start, startindex,
2832
+ fend, fendindex));
2833
+ }
2834
+ }
2835
+ start = fend;
2836
+ startindex = fendindex;
2837
+ if (string->stringval[0] == 0)
2838
+ startindex++;
2839
+ }
2840
+ } while (found == 1);
2841
+ }
2842
+
2843
+ /*
2844
+ * Save the new value and cleanup
2845
+ */
2846
+ error:
2847
+ if (newset != NULL)
2848
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2849
+ xmlXPathFreeObject(set);
2850
+ xmlXPathFreeObject(string);
2851
+ if (position) xmlXPathFreeObject(position);
2852
+ if (number) xmlXPathFreeObject(number);
2853
+ }
2854
+
2855
+ /**
2856
+ * xmlXPtrEvalRangePredicate:
2857
+ * @ctxt: the XPointer Parser context
2858
+ *
2859
+ * [8] Predicate ::= '[' PredicateExpr ']'
2860
+ * [9] PredicateExpr ::= Expr
2861
+ *
2862
+ * Evaluate a predicate as in xmlXPathEvalPredicate() but for
2863
+ * a Location Set instead of a node set
2864
+ */
2865
+ void
2866
+ xmlXPtrEvalRangePredicate(xmlXPathParserContextPtr ctxt) {
2867
+ const xmlChar *cur;
2868
+ xmlXPathObjectPtr res;
2869
+ xmlXPathObjectPtr obj, tmp;
2870
+ xmlLocationSetPtr newset = NULL;
2871
+ xmlLocationSetPtr oldset;
2872
+ int i;
2873
+
2874
+ if (ctxt == NULL) return;
2875
+
2876
+ SKIP_BLANKS;
2877
+ if (CUR != '[') {
2878
+ XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
2879
+ }
2880
+ NEXT;
2881
+ SKIP_BLANKS;
2882
+
2883
+ /*
2884
+ * Extract the old set, and then evaluate the result of the
2885
+ * expression for all the element in the set. use it to grow
2886
+ * up a new set.
2887
+ */
2888
+ CHECK_TYPE(XPATH_LOCATIONSET);
2889
+ obj = valuePop(ctxt);
2890
+ oldset = obj->user;
2891
+ ctxt->context->node = NULL;
2892
+
2893
+ if ((oldset == NULL) || (oldset->locNr == 0)) {
2894
+ ctxt->context->contextSize = 0;
2895
+ ctxt->context->proximityPosition = 0;
2896
+ xmlXPathEvalExpr(ctxt);
2897
+ res = valuePop(ctxt);
2898
+ if (res != NULL)
2899
+ xmlXPathFreeObject(res);
2900
+ valuePush(ctxt, obj);
2901
+ CHECK_ERROR;
2902
+ } else {
2903
+ /*
2904
+ * Save the expression pointer since we will have to evaluate
2905
+ * it multiple times. Initialize the new set.
2906
+ */
2907
+ cur = ctxt->cur;
2908
+ newset = xmlXPtrLocationSetCreate(NULL);
2909
+
2910
+ for (i = 0; i < oldset->locNr; i++) {
2911
+ ctxt->cur = cur;
2912
+
2913
+ /*
2914
+ * Run the evaluation with a node list made of a single item
2915
+ * in the nodeset.
2916
+ */
2917
+ ctxt->context->node = oldset->locTab[i]->user;
2918
+ tmp = xmlXPathNewNodeSet(ctxt->context->node);
2919
+ valuePush(ctxt, tmp);
2920
+ ctxt->context->contextSize = oldset->locNr;
2921
+ ctxt->context->proximityPosition = i + 1;
2922
+
2923
+ xmlXPathEvalExpr(ctxt);
2924
+ CHECK_ERROR;
2925
+
2926
+ /*
2927
+ * The result of the evaluation need to be tested to
2928
+ * decided whether the filter succeeded or not
2929
+ */
2930
+ res = valuePop(ctxt);
2931
+ if (xmlXPathEvaluatePredicateResult(ctxt, res)) {
2932
+ xmlXPtrLocationSetAdd(newset,
2933
+ xmlXPathObjectCopy(oldset->locTab[i]));
2934
+ }
2935
+
2936
+ /*
2937
+ * Cleanup
2938
+ */
2939
+ if (res != NULL)
2940
+ xmlXPathFreeObject(res);
2941
+ if (ctxt->value == tmp) {
2942
+ res = valuePop(ctxt);
2943
+ xmlXPathFreeObject(res);
2944
+ }
2945
+
2946
+ ctxt->context->node = NULL;
2947
+ }
2948
+
2949
+ /*
2950
+ * The result is used as the new evaluation set.
2951
+ */
2952
+ xmlXPathFreeObject(obj);
2953
+ ctxt->context->node = NULL;
2954
+ ctxt->context->contextSize = -1;
2955
+ ctxt->context->proximityPosition = -1;
2956
+ valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
2957
+ }
2958
+ if (CUR != ']') {
2959
+ XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
2960
+ }
2961
+
2962
+ NEXT;
2963
+ SKIP_BLANKS;
2964
+ }
2965
+
2966
+ #define bottom_xpointer
2967
+ #include "elfgcchack.h"
2968
+ #endif
2969
+