@helm2/poc_jenki_rce 0.0.1

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

Potentially problematic release.


This version of @helm2/poc_jenki_rce 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 +118 -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,2621 @@
1
+ /*
2
+ * pattern.c: Implementation of selectors for nodes
3
+ *
4
+ * Reference:
5
+ * http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/
6
+ * to some extent
7
+ * http://www.w3.org/TR/1999/REC-xml-19991116
8
+ *
9
+ * See Copyright for the status of this software.
10
+ *
11
+ * daniel@veillard.com
12
+ */
13
+
14
+ /*
15
+ * TODO:
16
+ * - compilation flags to check for specific syntaxes
17
+ * using flags of xmlPatterncompile()
18
+ * - making clear how pattern starting with / or . need to be handled,
19
+ * currently push(NULL, NULL) means a reset of the streaming context
20
+ * and indicating we are on / (the document node), probably need
21
+ * something similar for .
22
+ * - get rid of the "compile" starting with lowercase
23
+ * - DONE (2006-05-16): get rid of the Strdup/Strndup in case of dictionary
24
+ */
25
+
26
+ #define IN_LIBXML
27
+ #include "libxml.h"
28
+
29
+ #include <string.h>
30
+ #include <libxml/xmlmemory.h>
31
+ #include <libxml/tree.h>
32
+ #include <libxml/hash.h>
33
+ #include <libxml/dict.h>
34
+ #include <libxml/xmlerror.h>
35
+ #include <libxml/parserInternals.h>
36
+ #include <libxml/pattern.h>
37
+
38
+ #ifdef LIBXML_PATTERN_ENABLED
39
+
40
+ /* #define DEBUG_STREAMING */
41
+
42
+ #ifdef ERROR
43
+ #undef ERROR
44
+ #endif
45
+ #define ERROR(a, b, c, d)
46
+ #define ERROR5(a, b, c, d, e)
47
+
48
+ #define XML_STREAM_STEP_DESC 1
49
+ #define XML_STREAM_STEP_FINAL 2
50
+ #define XML_STREAM_STEP_ROOT 4
51
+ #define XML_STREAM_STEP_ATTR 8
52
+ #define XML_STREAM_STEP_NODE 16
53
+ #define XML_STREAM_STEP_IN_SET 32
54
+
55
+ /*
56
+ * NOTE: Those private flags (XML_STREAM_xxx) are used
57
+ * in _xmlStreamCtxt->flag. They extend the public
58
+ * xmlPatternFlags, so be careful not to interfere with the
59
+ * reserved values for xmlPatternFlags.
60
+ */
61
+ #define XML_STREAM_FINAL_IS_ANY_NODE 1<<14
62
+ #define XML_STREAM_FROM_ROOT 1<<15
63
+ #define XML_STREAM_DESC 1<<16
64
+
65
+ /*
66
+ * XML_STREAM_ANY_NODE is used for comparison against
67
+ * xmlElementType enums, to indicate a node of any type.
68
+ */
69
+ #define XML_STREAM_ANY_NODE 100
70
+
71
+ #define XML_PATTERN_NOTPATTERN (XML_PATTERN_XPATH | \
72
+ XML_PATTERN_XSSEL | \
73
+ XML_PATTERN_XSFIELD)
74
+
75
+ #define XML_STREAM_XS_IDC(c) ((c)->flags & \
76
+ (XML_PATTERN_XSSEL | XML_PATTERN_XSFIELD))
77
+
78
+ #define XML_STREAM_XS_IDC_SEL(c) ((c)->flags & XML_PATTERN_XSSEL)
79
+
80
+ #define XML_STREAM_XS_IDC_FIELD(c) ((c)->flags & XML_PATTERN_XSFIELD)
81
+
82
+ #define XML_PAT_COPY_NSNAME(c, r, nsname) \
83
+ if ((c)->comp->dict) \
84
+ r = (xmlChar *) xmlDictLookup((c)->comp->dict, BAD_CAST nsname, -1); \
85
+ else r = xmlStrdup(BAD_CAST nsname);
86
+
87
+ #define XML_PAT_FREE_STRING(c, r) if ((c)->comp->dict == NULL) xmlFree(r);
88
+
89
+ typedef struct _xmlStreamStep xmlStreamStep;
90
+ typedef xmlStreamStep *xmlStreamStepPtr;
91
+ struct _xmlStreamStep {
92
+ int flags; /* properties of that step */
93
+ const xmlChar *name; /* first string value if NULL accept all */
94
+ const xmlChar *ns; /* second string value */
95
+ int nodeType; /* type of node */
96
+ };
97
+
98
+ typedef struct _xmlStreamComp xmlStreamComp;
99
+ typedef xmlStreamComp *xmlStreamCompPtr;
100
+ struct _xmlStreamComp {
101
+ xmlDict *dict; /* the dictionary if any */
102
+ int nbStep; /* number of steps in the automata */
103
+ int maxStep; /* allocated number of steps */
104
+ xmlStreamStepPtr steps; /* the array of steps */
105
+ int flags;
106
+ };
107
+
108
+ struct _xmlStreamCtxt {
109
+ struct _xmlStreamCtxt *next;/* link to next sub pattern if | */
110
+ xmlStreamCompPtr comp; /* the compiled stream */
111
+ int nbState; /* number of states in the automata */
112
+ int maxState; /* allocated number of states */
113
+ int level; /* how deep are we ? */
114
+ int *states; /* the array of step indexes */
115
+ int flags; /* validation options */
116
+ int blockLevel;
117
+ };
118
+
119
+ static void xmlFreeStreamComp(xmlStreamCompPtr comp);
120
+
121
+ /*
122
+ * Types are private:
123
+ */
124
+
125
+ typedef enum {
126
+ XML_OP_END=0,
127
+ XML_OP_ROOT,
128
+ XML_OP_ELEM,
129
+ XML_OP_CHILD,
130
+ XML_OP_ATTR,
131
+ XML_OP_PARENT,
132
+ XML_OP_ANCESTOR,
133
+ XML_OP_NS,
134
+ XML_OP_ALL
135
+ } xmlPatOp;
136
+
137
+
138
+ typedef struct _xmlStepState xmlStepState;
139
+ typedef xmlStepState *xmlStepStatePtr;
140
+ struct _xmlStepState {
141
+ int step;
142
+ xmlNodePtr node;
143
+ };
144
+
145
+ typedef struct _xmlStepStates xmlStepStates;
146
+ typedef xmlStepStates *xmlStepStatesPtr;
147
+ struct _xmlStepStates {
148
+ int nbstates;
149
+ int maxstates;
150
+ xmlStepStatePtr states;
151
+ };
152
+
153
+ typedef struct _xmlStepOp xmlStepOp;
154
+ typedef xmlStepOp *xmlStepOpPtr;
155
+ struct _xmlStepOp {
156
+ xmlPatOp op;
157
+ const xmlChar *value;
158
+ const xmlChar *value2; /* The namespace name */
159
+ };
160
+
161
+ #define PAT_FROM_ROOT (1<<8)
162
+ #define PAT_FROM_CUR (1<<9)
163
+
164
+ struct _xmlPattern {
165
+ void *data; /* the associated template */
166
+ xmlDictPtr dict; /* the optional dictionary */
167
+ struct _xmlPattern *next; /* next pattern if | is used */
168
+ const xmlChar *pattern; /* the pattern */
169
+ int flags; /* flags */
170
+ int nbStep;
171
+ int maxStep;
172
+ xmlStepOpPtr steps; /* ops for computation */
173
+ xmlStreamCompPtr stream; /* the streaming data if any */
174
+ };
175
+
176
+ typedef struct _xmlPatParserContext xmlPatParserContext;
177
+ typedef xmlPatParserContext *xmlPatParserContextPtr;
178
+ struct _xmlPatParserContext {
179
+ const xmlChar *cur; /* the current char being parsed */
180
+ const xmlChar *base; /* the full expression */
181
+ int error; /* error code */
182
+ xmlDictPtr dict; /* the dictionary if any */
183
+ xmlPatternPtr comp; /* the result */
184
+ xmlNodePtr elem; /* the current node if any */
185
+ const xmlChar **namespaces; /* the namespaces definitions */
186
+ int nb_namespaces; /* the number of namespaces */
187
+ };
188
+
189
+ /************************************************************************
190
+ * *
191
+ * Type functions *
192
+ * *
193
+ ************************************************************************/
194
+
195
+ /**
196
+ * xmlNewPattern:
197
+ *
198
+ * Create a new XSLT Pattern
199
+ *
200
+ * Returns the newly allocated xmlPatternPtr or NULL in case of error
201
+ */
202
+ static xmlPatternPtr
203
+ xmlNewPattern(void) {
204
+ xmlPatternPtr cur;
205
+
206
+ cur = (xmlPatternPtr) xmlMalloc(sizeof(xmlPattern));
207
+ if (cur == NULL) {
208
+ ERROR(NULL, NULL, NULL,
209
+ "xmlNewPattern : malloc failed\n");
210
+ return(NULL);
211
+ }
212
+ memset(cur, 0, sizeof(xmlPattern));
213
+ cur->maxStep = 10;
214
+ cur->steps = (xmlStepOpPtr) xmlMalloc(cur->maxStep * sizeof(xmlStepOp));
215
+ if (cur->steps == NULL) {
216
+ xmlFree(cur);
217
+ ERROR(NULL, NULL, NULL,
218
+ "xmlNewPattern : malloc failed\n");
219
+ return(NULL);
220
+ }
221
+ return(cur);
222
+ }
223
+
224
+ /**
225
+ * xmlFreePattern:
226
+ * @comp: an XSLT comp
227
+ *
228
+ * Free up the memory allocated by @comp
229
+ */
230
+ void
231
+ xmlFreePattern(xmlPatternPtr comp) {
232
+ xmlFreePatternList(comp);
233
+ }
234
+
235
+ static void
236
+ xmlFreePatternInternal(xmlPatternPtr comp) {
237
+ xmlStepOpPtr op;
238
+ int i;
239
+
240
+ if (comp == NULL)
241
+ return;
242
+ if (comp->stream != NULL)
243
+ xmlFreeStreamComp(comp->stream);
244
+ if (comp->pattern != NULL)
245
+ xmlFree((xmlChar *)comp->pattern);
246
+ if (comp->steps != NULL) {
247
+ if (comp->dict == NULL) {
248
+ for (i = 0;i < comp->nbStep;i++) {
249
+ op = &comp->steps[i];
250
+ if (op->value != NULL)
251
+ xmlFree((xmlChar *) op->value);
252
+ if (op->value2 != NULL)
253
+ xmlFree((xmlChar *) op->value2);
254
+ }
255
+ }
256
+ xmlFree(comp->steps);
257
+ }
258
+ if (comp->dict != NULL)
259
+ xmlDictFree(comp->dict);
260
+
261
+ memset(comp, -1, sizeof(xmlPattern));
262
+ xmlFree(comp);
263
+ }
264
+
265
+ /**
266
+ * xmlFreePatternList:
267
+ * @comp: an XSLT comp list
268
+ *
269
+ * Free up the memory allocated by all the elements of @comp
270
+ */
271
+ void
272
+ xmlFreePatternList(xmlPatternPtr comp) {
273
+ xmlPatternPtr cur;
274
+
275
+ while (comp != NULL) {
276
+ cur = comp;
277
+ comp = comp->next;
278
+ cur->next = NULL;
279
+ xmlFreePatternInternal(cur);
280
+ }
281
+ }
282
+
283
+ /**
284
+ * xmlNewPatParserContext:
285
+ * @pattern: the pattern context
286
+ * @dict: the inherited dictionary or NULL
287
+ * @namespaces: the prefix definitions, array of [URI, prefix] terminated
288
+ * with [NULL, NULL] or NULL if no namespace is used
289
+ *
290
+ * Create a new XML pattern parser context
291
+ *
292
+ * Returns the newly allocated xmlPatParserContextPtr or NULL in case of error
293
+ */
294
+ static xmlPatParserContextPtr
295
+ xmlNewPatParserContext(const xmlChar *pattern, xmlDictPtr dict,
296
+ const xmlChar **namespaces) {
297
+ xmlPatParserContextPtr cur;
298
+
299
+ if (pattern == NULL)
300
+ return(NULL);
301
+
302
+ cur = (xmlPatParserContextPtr) xmlMalloc(sizeof(xmlPatParserContext));
303
+ if (cur == NULL) {
304
+ ERROR(NULL, NULL, NULL,
305
+ "xmlNewPatParserContext : malloc failed\n");
306
+ return(NULL);
307
+ }
308
+ memset(cur, 0, sizeof(xmlPatParserContext));
309
+ cur->dict = dict;
310
+ cur->cur = pattern;
311
+ cur->base = pattern;
312
+ if (namespaces != NULL) {
313
+ int i;
314
+ for (i = 0;namespaces[2 * i] != NULL;i++)
315
+ ;
316
+ cur->nb_namespaces = i;
317
+ } else {
318
+ cur->nb_namespaces = 0;
319
+ }
320
+ cur->namespaces = namespaces;
321
+ return(cur);
322
+ }
323
+
324
+ /**
325
+ * xmlFreePatParserContext:
326
+ * @ctxt: an XSLT parser context
327
+ *
328
+ * Free up the memory allocated by @ctxt
329
+ */
330
+ static void
331
+ xmlFreePatParserContext(xmlPatParserContextPtr ctxt) {
332
+ if (ctxt == NULL)
333
+ return;
334
+ memset(ctxt, -1, sizeof(xmlPatParserContext));
335
+ xmlFree(ctxt);
336
+ }
337
+
338
+ /**
339
+ * xmlPatternAdd:
340
+ * @comp: the compiled match expression
341
+ * @op: an op
342
+ * @value: the first value
343
+ * @value2: the second value
344
+ *
345
+ * Add a step to an XSLT Compiled Match
346
+ *
347
+ * Returns -1 in case of failure, 0 otherwise.
348
+ */
349
+ static int
350
+ xmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED,
351
+ xmlPatternPtr comp,
352
+ xmlPatOp op, xmlChar * value, xmlChar * value2)
353
+ {
354
+ if (comp->nbStep >= comp->maxStep) {
355
+ xmlStepOpPtr temp;
356
+ temp = (xmlStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
357
+ sizeof(xmlStepOp));
358
+ if (temp == NULL) {
359
+ ERROR(ctxt, NULL, NULL,
360
+ "xmlPatternAdd: realloc failed\n");
361
+ return (-1);
362
+ }
363
+ comp->steps = temp;
364
+ comp->maxStep *= 2;
365
+ }
366
+ comp->steps[comp->nbStep].op = op;
367
+ comp->steps[comp->nbStep].value = value;
368
+ comp->steps[comp->nbStep].value2 = value2;
369
+ comp->nbStep++;
370
+ return (0);
371
+ }
372
+
373
+ #if 0
374
+ /**
375
+ * xsltSwapTopPattern:
376
+ * @comp: the compiled match expression
377
+ *
378
+ * reverse the two top steps.
379
+ */
380
+ static void
381
+ xsltSwapTopPattern(xmlPatternPtr comp) {
382
+ int i;
383
+ int j = comp->nbStep - 1;
384
+
385
+ if (j > 0) {
386
+ register const xmlChar *tmp;
387
+ register xmlPatOp op;
388
+ i = j - 1;
389
+ tmp = comp->steps[i].value;
390
+ comp->steps[i].value = comp->steps[j].value;
391
+ comp->steps[j].value = tmp;
392
+ tmp = comp->steps[i].value2;
393
+ comp->steps[i].value2 = comp->steps[j].value2;
394
+ comp->steps[j].value2 = tmp;
395
+ op = comp->steps[i].op;
396
+ comp->steps[i].op = comp->steps[j].op;
397
+ comp->steps[j].op = op;
398
+ }
399
+ }
400
+ #endif
401
+
402
+ /**
403
+ * xmlReversePattern:
404
+ * @comp: the compiled match expression
405
+ *
406
+ * reverse all the stack of expressions
407
+ *
408
+ * returns 0 in case of success and -1 in case of error.
409
+ */
410
+ static int
411
+ xmlReversePattern(xmlPatternPtr comp) {
412
+ int i, j;
413
+
414
+ /*
415
+ * remove the leading // for //a or .//a
416
+ */
417
+ if ((comp->nbStep > 0) && (comp->steps[0].op == XML_OP_ANCESTOR)) {
418
+ for (i = 0, j = 1;j < comp->nbStep;i++,j++) {
419
+ comp->steps[i].value = comp->steps[j].value;
420
+ comp->steps[i].value2 = comp->steps[j].value2;
421
+ comp->steps[i].op = comp->steps[j].op;
422
+ }
423
+ comp->nbStep--;
424
+ }
425
+ if (comp->nbStep >= comp->maxStep) {
426
+ xmlStepOpPtr temp;
427
+ temp = (xmlStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
428
+ sizeof(xmlStepOp));
429
+ if (temp == NULL) {
430
+ ERROR(ctxt, NULL, NULL,
431
+ "xmlReversePattern: realloc failed\n");
432
+ return (-1);
433
+ }
434
+ comp->steps = temp;
435
+ comp->maxStep *= 2;
436
+ }
437
+ i = 0;
438
+ j = comp->nbStep - 1;
439
+ while (j > i) {
440
+ register const xmlChar *tmp;
441
+ register xmlPatOp op;
442
+ tmp = comp->steps[i].value;
443
+ comp->steps[i].value = comp->steps[j].value;
444
+ comp->steps[j].value = tmp;
445
+ tmp = comp->steps[i].value2;
446
+ comp->steps[i].value2 = comp->steps[j].value2;
447
+ comp->steps[j].value2 = tmp;
448
+ op = comp->steps[i].op;
449
+ comp->steps[i].op = comp->steps[j].op;
450
+ comp->steps[j].op = op;
451
+ j--;
452
+ i++;
453
+ }
454
+ comp->steps[comp->nbStep].value = NULL;
455
+ comp->steps[comp->nbStep].value2 = NULL;
456
+ comp->steps[comp->nbStep++].op = XML_OP_END;
457
+ return(0);
458
+ }
459
+
460
+ /************************************************************************
461
+ * *
462
+ * The interpreter for the precompiled patterns *
463
+ * *
464
+ ************************************************************************/
465
+
466
+ static int
467
+ xmlPatPushState(xmlStepStates *states, int step, xmlNodePtr node) {
468
+ if ((states->states == NULL) || (states->maxstates <= 0)) {
469
+ states->maxstates = 4;
470
+ states->nbstates = 0;
471
+ states->states = xmlMalloc(4 * sizeof(xmlStepState));
472
+ }
473
+ else if (states->maxstates <= states->nbstates) {
474
+ xmlStepState *tmp;
475
+
476
+ tmp = (xmlStepStatePtr) xmlRealloc(states->states,
477
+ 2 * states->maxstates * sizeof(xmlStepState));
478
+ if (tmp == NULL)
479
+ return(-1);
480
+ states->states = tmp;
481
+ states->maxstates *= 2;
482
+ }
483
+ states->states[states->nbstates].step = step;
484
+ states->states[states->nbstates++].node = node;
485
+ #if 0
486
+ fprintf(stderr, "Push: %d, %s\n", step, node->name);
487
+ #endif
488
+ return(0);
489
+ }
490
+
491
+ /**
492
+ * xmlPatMatch:
493
+ * @comp: the precompiled pattern
494
+ * @node: a node
495
+ *
496
+ * Test whether the node matches the pattern
497
+ *
498
+ * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
499
+ */
500
+ static int
501
+ xmlPatMatch(xmlPatternPtr comp, xmlNodePtr node) {
502
+ int i;
503
+ xmlStepOpPtr step;
504
+ xmlStepStates states = {0, 0, NULL}; /* // may require backtrack */
505
+
506
+ if ((comp == NULL) || (node == NULL)) return(-1);
507
+ i = 0;
508
+ restart:
509
+ for (;i < comp->nbStep;i++) {
510
+ step = &comp->steps[i];
511
+ switch (step->op) {
512
+ case XML_OP_END:
513
+ goto found;
514
+ case XML_OP_ROOT:
515
+ if (node->type == XML_NAMESPACE_DECL)
516
+ goto rollback;
517
+ node = node->parent;
518
+ if ((node->type == XML_DOCUMENT_NODE) ||
519
+ #ifdef LIBXML_DOCB_ENABLED
520
+ (node->type == XML_DOCB_DOCUMENT_NODE) ||
521
+ #endif
522
+ (node->type == XML_HTML_DOCUMENT_NODE))
523
+ continue;
524
+ goto rollback;
525
+ case XML_OP_ELEM:
526
+ if (node->type != XML_ELEMENT_NODE)
527
+ goto rollback;
528
+ if (step->value == NULL)
529
+ continue;
530
+ if (step->value[0] != node->name[0])
531
+ goto rollback;
532
+ if (!xmlStrEqual(step->value, node->name))
533
+ goto rollback;
534
+
535
+ /* Namespace test */
536
+ if (node->ns == NULL) {
537
+ if (step->value2 != NULL)
538
+ goto rollback;
539
+ } else if (node->ns->href != NULL) {
540
+ if (step->value2 == NULL)
541
+ goto rollback;
542
+ if (!xmlStrEqual(step->value2, node->ns->href))
543
+ goto rollback;
544
+ }
545
+ continue;
546
+ case XML_OP_CHILD: {
547
+ xmlNodePtr lst;
548
+
549
+ if ((node->type != XML_ELEMENT_NODE) &&
550
+ (node->type != XML_DOCUMENT_NODE) &&
551
+ #ifdef LIBXML_DOCB_ENABLED
552
+ (node->type != XML_DOCB_DOCUMENT_NODE) &&
553
+ #endif
554
+ (node->type != XML_HTML_DOCUMENT_NODE))
555
+ goto rollback;
556
+
557
+ lst = node->children;
558
+
559
+ if (step->value != NULL) {
560
+ while (lst != NULL) {
561
+ if ((lst->type == XML_ELEMENT_NODE) &&
562
+ (step->value[0] == lst->name[0]) &&
563
+ (xmlStrEqual(step->value, lst->name)))
564
+ break;
565
+ lst = lst->next;
566
+ }
567
+ if (lst != NULL)
568
+ continue;
569
+ }
570
+ goto rollback;
571
+ }
572
+ case XML_OP_ATTR:
573
+ if (node->type != XML_ATTRIBUTE_NODE)
574
+ goto rollback;
575
+ if (step->value != NULL) {
576
+ if (step->value[0] != node->name[0])
577
+ goto rollback;
578
+ if (!xmlStrEqual(step->value, node->name))
579
+ goto rollback;
580
+ }
581
+ /* Namespace test */
582
+ if (node->ns == NULL) {
583
+ if (step->value2 != NULL)
584
+ goto rollback;
585
+ } else if (step->value2 != NULL) {
586
+ if (!xmlStrEqual(step->value2, node->ns->href))
587
+ goto rollback;
588
+ }
589
+ continue;
590
+ case XML_OP_PARENT:
591
+ if ((node->type == XML_DOCUMENT_NODE) ||
592
+ (node->type == XML_HTML_DOCUMENT_NODE) ||
593
+ #ifdef LIBXML_DOCB_ENABLED
594
+ (node->type == XML_DOCB_DOCUMENT_NODE) ||
595
+ #endif
596
+ (node->type == XML_NAMESPACE_DECL))
597
+ goto rollback;
598
+ node = node->parent;
599
+ if (node == NULL)
600
+ goto rollback;
601
+ if (step->value == NULL)
602
+ continue;
603
+ if (step->value[0] != node->name[0])
604
+ goto rollback;
605
+ if (!xmlStrEqual(step->value, node->name))
606
+ goto rollback;
607
+ /* Namespace test */
608
+ if (node->ns == NULL) {
609
+ if (step->value2 != NULL)
610
+ goto rollback;
611
+ } else if (node->ns->href != NULL) {
612
+ if (step->value2 == NULL)
613
+ goto rollback;
614
+ if (!xmlStrEqual(step->value2, node->ns->href))
615
+ goto rollback;
616
+ }
617
+ continue;
618
+ case XML_OP_ANCESTOR:
619
+ /* TODO: implement coalescing of ANCESTOR/NODE ops */
620
+ if (step->value == NULL) {
621
+ i++;
622
+ step = &comp->steps[i];
623
+ if (step->op == XML_OP_ROOT)
624
+ goto found;
625
+ if (step->op != XML_OP_ELEM)
626
+ goto rollback;
627
+ if (step->value == NULL)
628
+ return(-1);
629
+ }
630
+ if (node == NULL)
631
+ goto rollback;
632
+ if ((node->type == XML_DOCUMENT_NODE) ||
633
+ (node->type == XML_HTML_DOCUMENT_NODE) ||
634
+ #ifdef LIBXML_DOCB_ENABLED
635
+ (node->type == XML_DOCB_DOCUMENT_NODE) ||
636
+ #endif
637
+ (node->type == XML_NAMESPACE_DECL))
638
+ goto rollback;
639
+ node = node->parent;
640
+ while (node != NULL) {
641
+ if ((node->type == XML_ELEMENT_NODE) &&
642
+ (step->value[0] == node->name[0]) &&
643
+ (xmlStrEqual(step->value, node->name))) {
644
+ /* Namespace test */
645
+ if (node->ns == NULL) {
646
+ if (step->value2 == NULL)
647
+ break;
648
+ } else if (node->ns->href != NULL) {
649
+ if ((step->value2 != NULL) &&
650
+ (xmlStrEqual(step->value2, node->ns->href)))
651
+ break;
652
+ }
653
+ }
654
+ node = node->parent;
655
+ }
656
+ if (node == NULL)
657
+ goto rollback;
658
+ /*
659
+ * prepare a potential rollback from here
660
+ * for ancestors of that node.
661
+ */
662
+ if (step->op == XML_OP_ANCESTOR)
663
+ xmlPatPushState(&states, i, node);
664
+ else
665
+ xmlPatPushState(&states, i - 1, node);
666
+ continue;
667
+ case XML_OP_NS:
668
+ if (node->type != XML_ELEMENT_NODE)
669
+ goto rollback;
670
+ if (node->ns == NULL) {
671
+ if (step->value != NULL)
672
+ goto rollback;
673
+ } else if (node->ns->href != NULL) {
674
+ if (step->value == NULL)
675
+ goto rollback;
676
+ if (!xmlStrEqual(step->value, node->ns->href))
677
+ goto rollback;
678
+ }
679
+ break;
680
+ case XML_OP_ALL:
681
+ if (node->type != XML_ELEMENT_NODE)
682
+ goto rollback;
683
+ break;
684
+ }
685
+ }
686
+ found:
687
+ if (states.states != NULL) {
688
+ /* Free the rollback states */
689
+ xmlFree(states.states);
690
+ }
691
+ return(1);
692
+ rollback:
693
+ /* got an error try to rollback */
694
+ if (states.states == NULL)
695
+ return(0);
696
+ if (states.nbstates <= 0) {
697
+ xmlFree(states.states);
698
+ return(0);
699
+ }
700
+ states.nbstates--;
701
+ i = states.states[states.nbstates].step;
702
+ node = states.states[states.nbstates].node;
703
+ #if 0
704
+ fprintf(stderr, "Pop: %d, %s\n", i, node->name);
705
+ #endif
706
+ goto restart;
707
+ }
708
+
709
+ /************************************************************************
710
+ * *
711
+ * Dedicated parser for templates *
712
+ * *
713
+ ************************************************************************/
714
+
715
+ #define TODO \
716
+ xmlGenericError(xmlGenericErrorContext, \
717
+ "Unimplemented block at %s:%d\n", \
718
+ __FILE__, __LINE__);
719
+ #define CUR (*ctxt->cur)
720
+ #define SKIP(val) ctxt->cur += (val)
721
+ #define NXT(val) ctxt->cur[(val)]
722
+ #define PEEKPREV(val) ctxt->cur[-(val)]
723
+ #define CUR_PTR ctxt->cur
724
+
725
+ #define SKIP_BLANKS \
726
+ while (IS_BLANK_CH(CUR)) NEXT
727
+
728
+ #define CURRENT (*ctxt->cur)
729
+ #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
730
+
731
+
732
+ #define PUSH(op, val, val2) \
733
+ if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error;
734
+
735
+ #define XSLT_ERROR(X) \
736
+ { xsltError(ctxt, __FILE__, __LINE__, X); \
737
+ ctxt->error = (X); return; }
738
+
739
+ #define XSLT_ERROR0(X) \
740
+ { xsltError(ctxt, __FILE__, __LINE__, X); \
741
+ ctxt->error = (X); return(0); }
742
+
743
+ #if 0
744
+ /**
745
+ * xmlPatScanLiteral:
746
+ * @ctxt: the XPath Parser context
747
+ *
748
+ * Parse an XPath Literal:
749
+ *
750
+ * [29] Literal ::= '"' [^"]* '"'
751
+ * | "'" [^']* "'"
752
+ *
753
+ * Returns the Literal parsed or NULL
754
+ */
755
+
756
+ static xmlChar *
757
+ xmlPatScanLiteral(xmlPatParserContextPtr ctxt) {
758
+ const xmlChar *q, *cur;
759
+ xmlChar *ret = NULL;
760
+ int val, len;
761
+
762
+ SKIP_BLANKS;
763
+ if (CUR == '"') {
764
+ NEXT;
765
+ cur = q = CUR_PTR;
766
+ val = xmlStringCurrentChar(NULL, cur, &len);
767
+ while ((IS_CHAR(val)) && (val != '"')) {
768
+ cur += len;
769
+ val = xmlStringCurrentChar(NULL, cur, &len);
770
+ }
771
+ if (!IS_CHAR(val)) {
772
+ ctxt->error = 1;
773
+ return(NULL);
774
+ } else {
775
+ if (ctxt->dict)
776
+ ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
777
+ else
778
+ ret = xmlStrndup(q, cur - q);
779
+ }
780
+ cur += len;
781
+ CUR_PTR = cur;
782
+ } else if (CUR == '\'') {
783
+ NEXT;
784
+ cur = q = CUR_PTR;
785
+ val = xmlStringCurrentChar(NULL, cur, &len);
786
+ while ((IS_CHAR(val)) && (val != '\'')) {
787
+ cur += len;
788
+ val = xmlStringCurrentChar(NULL, cur, &len);
789
+ }
790
+ if (!IS_CHAR(val)) {
791
+ ctxt->error = 1;
792
+ return(NULL);
793
+ } else {
794
+ if (ctxt->dict)
795
+ ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
796
+ else
797
+ ret = xmlStrndup(q, cur - q);
798
+ }
799
+ cur += len;
800
+ CUR_PTR = cur;
801
+ } else {
802
+ /* XP_ERROR(XPATH_START_LITERAL_ERROR); */
803
+ ctxt->error = 1;
804
+ return(NULL);
805
+ }
806
+ return(ret);
807
+ }
808
+ #endif
809
+
810
+ /**
811
+ * xmlPatScanName:
812
+ * @ctxt: the XPath Parser context
813
+ *
814
+ * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' |
815
+ * CombiningChar | Extender
816
+ *
817
+ * [5] Name ::= (Letter | '_' | ':') (NameChar)*
818
+ *
819
+ * [6] Names ::= Name (S Name)*
820
+ *
821
+ * Returns the Name parsed or NULL
822
+ */
823
+
824
+ static xmlChar *
825
+ xmlPatScanName(xmlPatParserContextPtr ctxt) {
826
+ const xmlChar *q, *cur;
827
+ xmlChar *ret = NULL;
828
+ int val, len;
829
+
830
+ SKIP_BLANKS;
831
+
832
+ cur = q = CUR_PTR;
833
+ val = xmlStringCurrentChar(NULL, cur, &len);
834
+ if (!IS_LETTER(val) && (val != '_') && (val != ':'))
835
+ return(NULL);
836
+
837
+ while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
838
+ (val == '.') || (val == '-') ||
839
+ (val == '_') ||
840
+ (IS_COMBINING(val)) ||
841
+ (IS_EXTENDER(val))) {
842
+ cur += len;
843
+ val = xmlStringCurrentChar(NULL, cur, &len);
844
+ }
845
+ if (ctxt->dict)
846
+ ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
847
+ else
848
+ ret = xmlStrndup(q, cur - q);
849
+ CUR_PTR = cur;
850
+ return(ret);
851
+ }
852
+
853
+ /**
854
+ * xmlPatScanNCName:
855
+ * @ctxt: the XPath Parser context
856
+ *
857
+ * Parses a non qualified name
858
+ *
859
+ * Returns the Name parsed or NULL
860
+ */
861
+
862
+ static xmlChar *
863
+ xmlPatScanNCName(xmlPatParserContextPtr ctxt) {
864
+ const xmlChar *q, *cur;
865
+ xmlChar *ret = NULL;
866
+ int val, len;
867
+
868
+ SKIP_BLANKS;
869
+
870
+ cur = q = CUR_PTR;
871
+ val = xmlStringCurrentChar(NULL, cur, &len);
872
+ if (!IS_LETTER(val) && (val != '_'))
873
+ return(NULL);
874
+
875
+ while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
876
+ (val == '.') || (val == '-') ||
877
+ (val == '_') ||
878
+ (IS_COMBINING(val)) ||
879
+ (IS_EXTENDER(val))) {
880
+ cur += len;
881
+ val = xmlStringCurrentChar(NULL, cur, &len);
882
+ }
883
+ if (ctxt->dict)
884
+ ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
885
+ else
886
+ ret = xmlStrndup(q, cur - q);
887
+ CUR_PTR = cur;
888
+ return(ret);
889
+ }
890
+
891
+ #if 0
892
+ /**
893
+ * xmlPatScanQName:
894
+ * @ctxt: the XPath Parser context
895
+ * @prefix: the place to store the prefix
896
+ *
897
+ * Parse a qualified name
898
+ *
899
+ * Returns the Name parsed or NULL
900
+ */
901
+
902
+ static xmlChar *
903
+ xmlPatScanQName(xmlPatParserContextPtr ctxt, xmlChar **prefix) {
904
+ xmlChar *ret = NULL;
905
+
906
+ *prefix = NULL;
907
+ ret = xmlPatScanNCName(ctxt);
908
+ if (CUR == ':') {
909
+ *prefix = ret;
910
+ NEXT;
911
+ ret = xmlPatScanNCName(ctxt);
912
+ }
913
+ return(ret);
914
+ }
915
+ #endif
916
+
917
+ /**
918
+ * xmlCompileAttributeTest:
919
+ * @ctxt: the compilation context
920
+ *
921
+ * Compile an attribute test.
922
+ */
923
+ static void
924
+ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
925
+ xmlChar *token = NULL;
926
+ xmlChar *name = NULL;
927
+ xmlChar *URL = NULL;
928
+
929
+ SKIP_BLANKS;
930
+ name = xmlPatScanNCName(ctxt);
931
+ if (name == NULL) {
932
+ if (CUR == '*') {
933
+ PUSH(XML_OP_ATTR, NULL, NULL);
934
+ NEXT;
935
+ } else {
936
+ ERROR(NULL, NULL, NULL,
937
+ "xmlCompileAttributeTest : Name expected\n");
938
+ ctxt->error = 1;
939
+ }
940
+ return;
941
+ }
942
+ if (CUR == ':') {
943
+ int i;
944
+ xmlChar *prefix = name;
945
+
946
+ NEXT;
947
+
948
+ if (IS_BLANK_CH(CUR)) {
949
+ ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
950
+ XML_PAT_FREE_STRING(ctxt, prefix);
951
+ ctxt->error = 1;
952
+ goto error;
953
+ }
954
+ /*
955
+ * This is a namespace match
956
+ */
957
+ token = xmlPatScanName(ctxt);
958
+ if ((prefix[0] == 'x') &&
959
+ (prefix[1] == 'm') &&
960
+ (prefix[2] == 'l') &&
961
+ (prefix[3] == 0))
962
+ {
963
+ XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE);
964
+ } else {
965
+ for (i = 0;i < ctxt->nb_namespaces;i++) {
966
+ if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
967
+ XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
968
+ break;
969
+ }
970
+ }
971
+ if (i >= ctxt->nb_namespaces) {
972
+ ERROR5(NULL, NULL, NULL,
973
+ "xmlCompileAttributeTest : no namespace bound to prefix %s\n",
974
+ prefix);
975
+ XML_PAT_FREE_STRING(ctxt, prefix);
976
+ ctxt->error = 1;
977
+ goto error;
978
+ }
979
+ }
980
+ XML_PAT_FREE_STRING(ctxt, prefix);
981
+ if (token == NULL) {
982
+ if (CUR == '*') {
983
+ NEXT;
984
+ PUSH(XML_OP_ATTR, NULL, URL);
985
+ } else {
986
+ ERROR(NULL, NULL, NULL,
987
+ "xmlCompileAttributeTest : Name expected\n");
988
+ ctxt->error = 1;
989
+ goto error;
990
+ }
991
+ } else {
992
+ PUSH(XML_OP_ATTR, token, URL);
993
+ }
994
+ } else {
995
+ PUSH(XML_OP_ATTR, name, NULL);
996
+ }
997
+ return;
998
+ error:
999
+ if (URL != NULL)
1000
+ XML_PAT_FREE_STRING(ctxt, URL)
1001
+ if (token != NULL)
1002
+ XML_PAT_FREE_STRING(ctxt, token);
1003
+ }
1004
+
1005
+ /**
1006
+ * xmlCompileStepPattern:
1007
+ * @ctxt: the compilation context
1008
+ *
1009
+ * Compile the Step Pattern and generates a precompiled
1010
+ * form suitable for fast matching.
1011
+ *
1012
+ * [3] Step ::= '.' | NameTest
1013
+ * [4] NameTest ::= QName | '*' | NCName ':' '*'
1014
+ */
1015
+
1016
+ static void
1017
+ xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
1018
+ xmlChar *token = NULL;
1019
+ xmlChar *name = NULL;
1020
+ xmlChar *URL = NULL;
1021
+ int hasBlanks = 0;
1022
+
1023
+ SKIP_BLANKS;
1024
+ if (CUR == '.') {
1025
+ /*
1026
+ * Context node.
1027
+ */
1028
+ NEXT;
1029
+ PUSH(XML_OP_ELEM, NULL, NULL);
1030
+ return;
1031
+ }
1032
+ if (CUR == '@') {
1033
+ /*
1034
+ * Attribute test.
1035
+ */
1036
+ if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
1037
+ ERROR5(NULL, NULL, NULL,
1038
+ "Unexpected attribute axis in '%s'.\n", ctxt->base);
1039
+ ctxt->error = 1;
1040
+ return;
1041
+ }
1042
+ NEXT;
1043
+ xmlCompileAttributeTest(ctxt);
1044
+ if (ctxt->error != 0)
1045
+ goto error;
1046
+ return;
1047
+ }
1048
+ name = xmlPatScanNCName(ctxt);
1049
+ if (name == NULL) {
1050
+ if (CUR == '*') {
1051
+ NEXT;
1052
+ PUSH(XML_OP_ALL, NULL, NULL);
1053
+ return;
1054
+ } else {
1055
+ ERROR(NULL, NULL, NULL,
1056
+ "xmlCompileStepPattern : Name expected\n");
1057
+ ctxt->error = 1;
1058
+ return;
1059
+ }
1060
+ }
1061
+ if (IS_BLANK_CH(CUR)) {
1062
+ hasBlanks = 1;
1063
+ SKIP_BLANKS;
1064
+ }
1065
+ if (CUR == ':') {
1066
+ NEXT;
1067
+ if (CUR != ':') {
1068
+ xmlChar *prefix = name;
1069
+ int i;
1070
+
1071
+ if (hasBlanks || IS_BLANK_CH(CUR)) {
1072
+ ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
1073
+ ctxt->error = 1;
1074
+ goto error;
1075
+ }
1076
+ /*
1077
+ * This is a namespace match
1078
+ */
1079
+ token = xmlPatScanName(ctxt);
1080
+ if ((prefix[0] == 'x') &&
1081
+ (prefix[1] == 'm') &&
1082
+ (prefix[2] == 'l') &&
1083
+ (prefix[3] == 0))
1084
+ {
1085
+ XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
1086
+ } else {
1087
+ for (i = 0;i < ctxt->nb_namespaces;i++) {
1088
+ if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
1089
+ XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
1090
+ break;
1091
+ }
1092
+ }
1093
+ if (i >= ctxt->nb_namespaces) {
1094
+ ERROR5(NULL, NULL, NULL,
1095
+ "xmlCompileStepPattern : no namespace bound to prefix %s\n",
1096
+ prefix);
1097
+ ctxt->error = 1;
1098
+ goto error;
1099
+ }
1100
+ }
1101
+ XML_PAT_FREE_STRING(ctxt, prefix);
1102
+ name = NULL;
1103
+ if (token == NULL) {
1104
+ if (CUR == '*') {
1105
+ NEXT;
1106
+ PUSH(XML_OP_NS, URL, NULL);
1107
+ } else {
1108
+ ERROR(NULL, NULL, NULL,
1109
+ "xmlCompileStepPattern : Name expected\n");
1110
+ ctxt->error = 1;
1111
+ goto error;
1112
+ }
1113
+ } else {
1114
+ PUSH(XML_OP_ELEM, token, URL);
1115
+ }
1116
+ } else {
1117
+ NEXT;
1118
+ if (xmlStrEqual(name, (const xmlChar *) "child")) {
1119
+ XML_PAT_FREE_STRING(ctxt, name);
1120
+ name = xmlPatScanName(ctxt);
1121
+ if (name == NULL) {
1122
+ if (CUR == '*') {
1123
+ NEXT;
1124
+ PUSH(XML_OP_ALL, NULL, NULL);
1125
+ return;
1126
+ } else {
1127
+ ERROR(NULL, NULL, NULL,
1128
+ "xmlCompileStepPattern : QName expected\n");
1129
+ ctxt->error = 1;
1130
+ goto error;
1131
+ }
1132
+ }
1133
+ if (CUR == ':') {
1134
+ xmlChar *prefix = name;
1135
+ int i;
1136
+
1137
+ NEXT;
1138
+ if (IS_BLANK_CH(CUR)) {
1139
+ ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
1140
+ ctxt->error = 1;
1141
+ goto error;
1142
+ }
1143
+ /*
1144
+ * This is a namespace match
1145
+ */
1146
+ token = xmlPatScanName(ctxt);
1147
+ if ((prefix[0] == 'x') &&
1148
+ (prefix[1] == 'm') &&
1149
+ (prefix[2] == 'l') &&
1150
+ (prefix[3] == 0))
1151
+ {
1152
+ XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
1153
+ } else {
1154
+ for (i = 0;i < ctxt->nb_namespaces;i++) {
1155
+ if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
1156
+ XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
1157
+ break;
1158
+ }
1159
+ }
1160
+ if (i >= ctxt->nb_namespaces) {
1161
+ ERROR5(NULL, NULL, NULL,
1162
+ "xmlCompileStepPattern : no namespace bound "
1163
+ "to prefix %s\n", prefix);
1164
+ ctxt->error = 1;
1165
+ goto error;
1166
+ }
1167
+ }
1168
+ XML_PAT_FREE_STRING(ctxt, prefix);
1169
+ name = NULL;
1170
+ if (token == NULL) {
1171
+ if (CUR == '*') {
1172
+ NEXT;
1173
+ PUSH(XML_OP_NS, URL, NULL);
1174
+ } else {
1175
+ ERROR(NULL, NULL, NULL,
1176
+ "xmlCompileStepPattern : Name expected\n");
1177
+ ctxt->error = 1;
1178
+ goto error;
1179
+ }
1180
+ } else {
1181
+ PUSH(XML_OP_CHILD, token, URL);
1182
+ }
1183
+ } else
1184
+ PUSH(XML_OP_CHILD, name, NULL);
1185
+ return;
1186
+ } else if (xmlStrEqual(name, (const xmlChar *) "attribute")) {
1187
+ XML_PAT_FREE_STRING(ctxt, name)
1188
+ name = NULL;
1189
+ if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
1190
+ ERROR5(NULL, NULL, NULL,
1191
+ "Unexpected attribute axis in '%s'.\n", ctxt->base);
1192
+ ctxt->error = 1;
1193
+ goto error;
1194
+ }
1195
+ xmlCompileAttributeTest(ctxt);
1196
+ if (ctxt->error != 0)
1197
+ goto error;
1198
+ return;
1199
+ } else {
1200
+ ERROR5(NULL, NULL, NULL,
1201
+ "The 'element' or 'attribute' axis is expected.\n", NULL);
1202
+ ctxt->error = 1;
1203
+ goto error;
1204
+ }
1205
+ }
1206
+ } else if (CUR == '*') {
1207
+ if (name != NULL) {
1208
+ ctxt->error = 1;
1209
+ goto error;
1210
+ }
1211
+ NEXT;
1212
+ PUSH(XML_OP_ALL, token, NULL);
1213
+ } else {
1214
+ PUSH(XML_OP_ELEM, name, NULL);
1215
+ }
1216
+ return;
1217
+ error:
1218
+ if (URL != NULL)
1219
+ XML_PAT_FREE_STRING(ctxt, URL)
1220
+ if (token != NULL)
1221
+ XML_PAT_FREE_STRING(ctxt, token)
1222
+ if (name != NULL)
1223
+ XML_PAT_FREE_STRING(ctxt, name)
1224
+ }
1225
+
1226
+ /**
1227
+ * xmlCompilePathPattern:
1228
+ * @ctxt: the compilation context
1229
+ *
1230
+ * Compile the Path Pattern and generates a precompiled
1231
+ * form suitable for fast matching.
1232
+ *
1233
+ * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
1234
+ */
1235
+ static void
1236
+ xmlCompilePathPattern(xmlPatParserContextPtr ctxt) {
1237
+ SKIP_BLANKS;
1238
+ if (CUR == '/') {
1239
+ ctxt->comp->flags |= PAT_FROM_ROOT;
1240
+ } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) {
1241
+ ctxt->comp->flags |= PAT_FROM_CUR;
1242
+ }
1243
+
1244
+ if ((CUR == '/') && (NXT(1) == '/')) {
1245
+ PUSH(XML_OP_ANCESTOR, NULL, NULL);
1246
+ NEXT;
1247
+ NEXT;
1248
+ } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) {
1249
+ PUSH(XML_OP_ANCESTOR, NULL, NULL);
1250
+ NEXT;
1251
+ NEXT;
1252
+ NEXT;
1253
+ /* Check for incompleteness. */
1254
+ SKIP_BLANKS;
1255
+ if (CUR == 0) {
1256
+ ERROR5(NULL, NULL, NULL,
1257
+ "Incomplete expression '%s'.\n", ctxt->base);
1258
+ ctxt->error = 1;
1259
+ goto error;
1260
+ }
1261
+ }
1262
+ if (CUR == '@') {
1263
+ NEXT;
1264
+ xmlCompileAttributeTest(ctxt);
1265
+ SKIP_BLANKS;
1266
+ /* TODO: check for incompleteness */
1267
+ if (CUR != 0) {
1268
+ xmlCompileStepPattern(ctxt);
1269
+ if (ctxt->error != 0)
1270
+ goto error;
1271
+ }
1272
+ } else {
1273
+ if (CUR == '/') {
1274
+ PUSH(XML_OP_ROOT, NULL, NULL);
1275
+ NEXT;
1276
+ /* Check for incompleteness. */
1277
+ SKIP_BLANKS;
1278
+ if (CUR == 0) {
1279
+ ERROR5(NULL, NULL, NULL,
1280
+ "Incomplete expression '%s'.\n", ctxt->base);
1281
+ ctxt->error = 1;
1282
+ goto error;
1283
+ }
1284
+ }
1285
+ xmlCompileStepPattern(ctxt);
1286
+ if (ctxt->error != 0)
1287
+ goto error;
1288
+ SKIP_BLANKS;
1289
+ while (CUR == '/') {
1290
+ if (NXT(1) == '/') {
1291
+ PUSH(XML_OP_ANCESTOR, NULL, NULL);
1292
+ NEXT;
1293
+ NEXT;
1294
+ SKIP_BLANKS;
1295
+ xmlCompileStepPattern(ctxt);
1296
+ if (ctxt->error != 0)
1297
+ goto error;
1298
+ } else {
1299
+ PUSH(XML_OP_PARENT, NULL, NULL);
1300
+ NEXT;
1301
+ SKIP_BLANKS;
1302
+ if (CUR == 0) {
1303
+ ERROR5(NULL, NULL, NULL,
1304
+ "Incomplete expression '%s'.\n", ctxt->base);
1305
+ ctxt->error = 1;
1306
+ goto error;
1307
+ }
1308
+ xmlCompileStepPattern(ctxt);
1309
+ if (ctxt->error != 0)
1310
+ goto error;
1311
+ }
1312
+ }
1313
+ }
1314
+ if (CUR != 0) {
1315
+ ERROR5(NULL, NULL, NULL,
1316
+ "Failed to compile pattern %s\n", ctxt->base);
1317
+ ctxt->error = 1;
1318
+ }
1319
+ error:
1320
+ return;
1321
+ }
1322
+
1323
+ /**
1324
+ * xmlCompileIDCXPathPath:
1325
+ * @ctxt: the compilation context
1326
+ *
1327
+ * Compile the Path Pattern and generates a precompiled
1328
+ * form suitable for fast matching.
1329
+ *
1330
+ * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
1331
+ */
1332
+ static void
1333
+ xmlCompileIDCXPathPath(xmlPatParserContextPtr ctxt) {
1334
+ SKIP_BLANKS;
1335
+ if (CUR == '/') {
1336
+ ERROR5(NULL, NULL, NULL,
1337
+ "Unexpected selection of the document root in '%s'.\n",
1338
+ ctxt->base);
1339
+ goto error;
1340
+ }
1341
+ ctxt->comp->flags |= PAT_FROM_CUR;
1342
+
1343
+ if (CUR == '.') {
1344
+ /* "." - "self::node()" */
1345
+ NEXT;
1346
+ SKIP_BLANKS;
1347
+ if (CUR == 0) {
1348
+ /*
1349
+ * Selection of the context node.
1350
+ */
1351
+ PUSH(XML_OP_ELEM, NULL, NULL);
1352
+ return;
1353
+ }
1354
+ if (CUR != '/') {
1355
+ /* TODO: A more meaningful error message. */
1356
+ ERROR5(NULL, NULL, NULL,
1357
+ "Unexpected token after '.' in '%s'.\n", ctxt->base);
1358
+ goto error;
1359
+ }
1360
+ /* "./" - "self::node()/" */
1361
+ NEXT;
1362
+ SKIP_BLANKS;
1363
+ if (CUR == '/') {
1364
+ if (IS_BLANK_CH(PEEKPREV(1))) {
1365
+ /*
1366
+ * Disallow "./ /"
1367
+ */
1368
+ ERROR5(NULL, NULL, NULL,
1369
+ "Unexpected '/' token in '%s'.\n", ctxt->base);
1370
+ goto error;
1371
+ }
1372
+ /* ".//" - "self:node()/descendant-or-self::node()/" */
1373
+ PUSH(XML_OP_ANCESTOR, NULL, NULL);
1374
+ NEXT;
1375
+ SKIP_BLANKS;
1376
+ }
1377
+ if (CUR == 0)
1378
+ goto error_unfinished;
1379
+ }
1380
+ /*
1381
+ * Process steps.
1382
+ */
1383
+ do {
1384
+ xmlCompileStepPattern(ctxt);
1385
+ if (ctxt->error != 0)
1386
+ goto error;
1387
+ SKIP_BLANKS;
1388
+ if (CUR != '/')
1389
+ break;
1390
+ PUSH(XML_OP_PARENT, NULL, NULL);
1391
+ NEXT;
1392
+ SKIP_BLANKS;
1393
+ if (CUR == '/') {
1394
+ /*
1395
+ * Disallow subsequent '//'.
1396
+ */
1397
+ ERROR5(NULL, NULL, NULL,
1398
+ "Unexpected subsequent '//' in '%s'.\n",
1399
+ ctxt->base);
1400
+ goto error;
1401
+ }
1402
+ if (CUR == 0)
1403
+ goto error_unfinished;
1404
+
1405
+ } while (CUR != 0);
1406
+
1407
+ if (CUR != 0) {
1408
+ ERROR5(NULL, NULL, NULL,
1409
+ "Failed to compile expression '%s'.\n", ctxt->base);
1410
+ ctxt->error = 1;
1411
+ }
1412
+ return;
1413
+ error:
1414
+ ctxt->error = 1;
1415
+ return;
1416
+
1417
+ error_unfinished:
1418
+ ctxt->error = 1;
1419
+ ERROR5(NULL, NULL, NULL,
1420
+ "Unfinished expression '%s'.\n", ctxt->base);
1421
+ return;
1422
+ }
1423
+
1424
+ /************************************************************************
1425
+ * *
1426
+ * The streaming code *
1427
+ * *
1428
+ ************************************************************************/
1429
+
1430
+ #ifdef DEBUG_STREAMING
1431
+ static void
1432
+ xmlDebugStreamComp(xmlStreamCompPtr stream) {
1433
+ int i;
1434
+
1435
+ if (stream == NULL) {
1436
+ printf("Stream: NULL\n");
1437
+ return;
1438
+ }
1439
+ printf("Stream: %d steps\n", stream->nbStep);
1440
+ for (i = 0;i < stream->nbStep;i++) {
1441
+ if (stream->steps[i].ns != NULL) {
1442
+ printf("{%s}", stream->steps[i].ns);
1443
+ }
1444
+ if (stream->steps[i].name == NULL) {
1445
+ printf("* ");
1446
+ } else {
1447
+ printf("%s ", stream->steps[i].name);
1448
+ }
1449
+ if (stream->steps[i].flags & XML_STREAM_STEP_ROOT)
1450
+ printf("root ");
1451
+ if (stream->steps[i].flags & XML_STREAM_STEP_DESC)
1452
+ printf("// ");
1453
+ if (stream->steps[i].flags & XML_STREAM_STEP_FINAL)
1454
+ printf("final ");
1455
+ printf("\n");
1456
+ }
1457
+ }
1458
+ static void
1459
+ xmlDebugStreamCtxt(xmlStreamCtxtPtr ctxt, int match) {
1460
+ int i;
1461
+
1462
+ if (ctxt == NULL) {
1463
+ printf("Stream: NULL\n");
1464
+ return;
1465
+ }
1466
+ printf("Stream: level %d, %d states: ", ctxt->level, ctxt->nbState);
1467
+ if (match)
1468
+ printf("matches\n");
1469
+ else
1470
+ printf("\n");
1471
+ for (i = 0;i < ctxt->nbState;i++) {
1472
+ if (ctxt->states[2 * i] < 0)
1473
+ printf(" %d: free\n", i);
1474
+ else {
1475
+ printf(" %d: step %d, level %d", i, ctxt->states[2 * i],
1476
+ ctxt->states[(2 * i) + 1]);
1477
+ if (ctxt->comp->steps[ctxt->states[2 * i]].flags &
1478
+ XML_STREAM_STEP_DESC)
1479
+ printf(" //\n");
1480
+ else
1481
+ printf("\n");
1482
+ }
1483
+ }
1484
+ }
1485
+ #endif
1486
+ /**
1487
+ * xmlNewStreamComp:
1488
+ * @size: the number of expected steps
1489
+ *
1490
+ * build a new compiled pattern for streaming
1491
+ *
1492
+ * Returns the new structure or NULL in case of error.
1493
+ */
1494
+ static xmlStreamCompPtr
1495
+ xmlNewStreamComp(int size) {
1496
+ xmlStreamCompPtr cur;
1497
+
1498
+ if (size < 4)
1499
+ size = 4;
1500
+
1501
+ cur = (xmlStreamCompPtr) xmlMalloc(sizeof(xmlStreamComp));
1502
+ if (cur == NULL) {
1503
+ ERROR(NULL, NULL, NULL,
1504
+ "xmlNewStreamComp: malloc failed\n");
1505
+ return(NULL);
1506
+ }
1507
+ memset(cur, 0, sizeof(xmlStreamComp));
1508
+ cur->steps = (xmlStreamStepPtr) xmlMalloc(size * sizeof(xmlStreamStep));
1509
+ if (cur->steps == NULL) {
1510
+ xmlFree(cur);
1511
+ ERROR(NULL, NULL, NULL,
1512
+ "xmlNewStreamComp: malloc failed\n");
1513
+ return(NULL);
1514
+ }
1515
+ cur->nbStep = 0;
1516
+ cur->maxStep = size;
1517
+ return(cur);
1518
+ }
1519
+
1520
+ /**
1521
+ * xmlFreeStreamComp:
1522
+ * @comp: the compiled pattern for streaming
1523
+ *
1524
+ * Free the compiled pattern for streaming
1525
+ */
1526
+ static void
1527
+ xmlFreeStreamComp(xmlStreamCompPtr comp) {
1528
+ if (comp != NULL) {
1529
+ if (comp->steps != NULL)
1530
+ xmlFree(comp->steps);
1531
+ if (comp->dict != NULL)
1532
+ xmlDictFree(comp->dict);
1533
+ xmlFree(comp);
1534
+ }
1535
+ }
1536
+
1537
+ /**
1538
+ * xmlStreamCompAddStep:
1539
+ * @comp: the compiled pattern for streaming
1540
+ * @name: the first string, the name, or NULL for *
1541
+ * @ns: the second step, the namespace name
1542
+ * @flags: the flags for that step
1543
+ *
1544
+ * Add a new step to the compiled pattern
1545
+ *
1546
+ * Returns -1 in case of error or the step index if successful
1547
+ */
1548
+ static int
1549
+ xmlStreamCompAddStep(xmlStreamCompPtr comp, const xmlChar *name,
1550
+ const xmlChar *ns, int nodeType, int flags) {
1551
+ xmlStreamStepPtr cur;
1552
+
1553
+ if (comp->nbStep >= comp->maxStep) {
1554
+ cur = (xmlStreamStepPtr) xmlRealloc(comp->steps,
1555
+ comp->maxStep * 2 * sizeof(xmlStreamStep));
1556
+ if (cur == NULL) {
1557
+ ERROR(NULL, NULL, NULL,
1558
+ "xmlNewStreamComp: malloc failed\n");
1559
+ return(-1);
1560
+ }
1561
+ comp->steps = cur;
1562
+ comp->maxStep *= 2;
1563
+ }
1564
+ cur = &comp->steps[comp->nbStep++];
1565
+ cur->flags = flags;
1566
+ cur->name = name;
1567
+ cur->ns = ns;
1568
+ cur->nodeType = nodeType;
1569
+ return(comp->nbStep - 1);
1570
+ }
1571
+
1572
+ /**
1573
+ * xmlStreamCompile:
1574
+ * @comp: the precompiled pattern
1575
+ *
1576
+ * Tries to stream compile a pattern
1577
+ *
1578
+ * Returns -1 in case of failure and 0 in case of success.
1579
+ */
1580
+ static int
1581
+ xmlStreamCompile(xmlPatternPtr comp) {
1582
+ xmlStreamCompPtr stream;
1583
+ int i, s = 0, root = 0, flags = 0, prevs = -1;
1584
+ xmlStepOp step;
1585
+
1586
+ if ((comp == NULL) || (comp->steps == NULL))
1587
+ return(-1);
1588
+ /*
1589
+ * special case for .
1590
+ */
1591
+ if ((comp->nbStep == 1) &&
1592
+ (comp->steps[0].op == XML_OP_ELEM) &&
1593
+ (comp->steps[0].value == NULL) &&
1594
+ (comp->steps[0].value2 == NULL)) {
1595
+ stream = xmlNewStreamComp(0);
1596
+ if (stream == NULL)
1597
+ return(-1);
1598
+ /* Note that the stream will have no steps in this case. */
1599
+ stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;
1600
+ comp->stream = stream;
1601
+ return(0);
1602
+ }
1603
+
1604
+ stream = xmlNewStreamComp((comp->nbStep / 2) + 1);
1605
+ if (stream == NULL)
1606
+ return(-1);
1607
+ if (comp->dict != NULL) {
1608
+ stream->dict = comp->dict;
1609
+ xmlDictReference(stream->dict);
1610
+ }
1611
+
1612
+ i = 0;
1613
+ if (comp->flags & PAT_FROM_ROOT)
1614
+ stream->flags |= XML_STREAM_FROM_ROOT;
1615
+
1616
+ for (;i < comp->nbStep;i++) {
1617
+ step = comp->steps[i];
1618
+ switch (step.op) {
1619
+ case XML_OP_END:
1620
+ break;
1621
+ case XML_OP_ROOT:
1622
+ if (i != 0)
1623
+ goto error;
1624
+ root = 1;
1625
+ break;
1626
+ case XML_OP_NS:
1627
+ s = xmlStreamCompAddStep(stream, NULL, step.value,
1628
+ XML_ELEMENT_NODE, flags);
1629
+ if (s < 0)
1630
+ goto error;
1631
+ prevs = s;
1632
+ flags = 0;
1633
+ break;
1634
+ case XML_OP_ATTR:
1635
+ flags |= XML_STREAM_STEP_ATTR;
1636
+ prevs = -1;
1637
+ s = xmlStreamCompAddStep(stream,
1638
+ step.value, step.value2, XML_ATTRIBUTE_NODE, flags);
1639
+ flags = 0;
1640
+ if (s < 0)
1641
+ goto error;
1642
+ break;
1643
+ case XML_OP_ELEM:
1644
+ if ((step.value == NULL) && (step.value2 == NULL)) {
1645
+ /*
1646
+ * We have a "." or "self::node()" here.
1647
+ * Eliminate redundant self::node() tests like in "/./."
1648
+ * or "//./"
1649
+ * The only case we won't eliminate is "//.", i.e. if
1650
+ * self::node() is the last node test and we had
1651
+ * continuation somewhere beforehand.
1652
+ */
1653
+ if ((comp->nbStep == i + 1) &&
1654
+ (flags & XML_STREAM_STEP_DESC)) {
1655
+ /*
1656
+ * Mark the special case where the expression resolves
1657
+ * to any type of node.
1658
+ */
1659
+ if (comp->nbStep == i + 1) {
1660
+ stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;
1661
+ }
1662
+ flags |= XML_STREAM_STEP_NODE;
1663
+ s = xmlStreamCompAddStep(stream, NULL, NULL,
1664
+ XML_STREAM_ANY_NODE, flags);
1665
+ if (s < 0)
1666
+ goto error;
1667
+ flags = 0;
1668
+ /*
1669
+ * If there was a previous step, mark it to be added to
1670
+ * the result node-set; this is needed since only
1671
+ * the last step will be marked as "final" and only
1672
+ * "final" nodes are added to the resulting set.
1673
+ */
1674
+ if (prevs != -1) {
1675
+ stream->steps[prevs].flags |= XML_STREAM_STEP_IN_SET;
1676
+ prevs = -1;
1677
+ }
1678
+ break;
1679
+
1680
+ } else {
1681
+ /* Just skip this one. */
1682
+ continue;
1683
+ }
1684
+ }
1685
+ /* An element node. */
1686
+ s = xmlStreamCompAddStep(stream, step.value, step.value2,
1687
+ XML_ELEMENT_NODE, flags);
1688
+ if (s < 0)
1689
+ goto error;
1690
+ prevs = s;
1691
+ flags = 0;
1692
+ break;
1693
+ case XML_OP_CHILD:
1694
+ /* An element node child. */
1695
+ s = xmlStreamCompAddStep(stream, step.value, step.value2,
1696
+ XML_ELEMENT_NODE, flags);
1697
+ if (s < 0)
1698
+ goto error;
1699
+ prevs = s;
1700
+ flags = 0;
1701
+ break;
1702
+ case XML_OP_ALL:
1703
+ s = xmlStreamCompAddStep(stream, NULL, NULL,
1704
+ XML_ELEMENT_NODE, flags);
1705
+ if (s < 0)
1706
+ goto error;
1707
+ prevs = s;
1708
+ flags = 0;
1709
+ break;
1710
+ case XML_OP_PARENT:
1711
+ break;
1712
+ case XML_OP_ANCESTOR:
1713
+ /* Skip redundant continuations. */
1714
+ if (flags & XML_STREAM_STEP_DESC)
1715
+ break;
1716
+ flags |= XML_STREAM_STEP_DESC;
1717
+ /*
1718
+ * Mark the expression as having "//".
1719
+ */
1720
+ if ((stream->flags & XML_STREAM_DESC) == 0)
1721
+ stream->flags |= XML_STREAM_DESC;
1722
+ break;
1723
+ }
1724
+ }
1725
+ if ((! root) && (comp->flags & XML_PATTERN_NOTPATTERN) == 0) {
1726
+ /*
1727
+ * If this should behave like a real pattern, we will mark
1728
+ * the first step as having "//", to be reentrant on every
1729
+ * tree level.
1730
+ */
1731
+ if ((stream->flags & XML_STREAM_DESC) == 0)
1732
+ stream->flags |= XML_STREAM_DESC;
1733
+
1734
+ if (stream->nbStep > 0) {
1735
+ if ((stream->steps[0].flags & XML_STREAM_STEP_DESC) == 0)
1736
+ stream->steps[0].flags |= XML_STREAM_STEP_DESC;
1737
+ }
1738
+ }
1739
+ if (stream->nbStep <= s)
1740
+ goto error;
1741
+ stream->steps[s].flags |= XML_STREAM_STEP_FINAL;
1742
+ if (root)
1743
+ stream->steps[0].flags |= XML_STREAM_STEP_ROOT;
1744
+ #ifdef DEBUG_STREAMING
1745
+ xmlDebugStreamComp(stream);
1746
+ #endif
1747
+ comp->stream = stream;
1748
+ return(0);
1749
+ error:
1750
+ xmlFreeStreamComp(stream);
1751
+ return(0);
1752
+ }
1753
+
1754
+ /**
1755
+ * xmlNewStreamCtxt:
1756
+ * @size: the number of expected states
1757
+ *
1758
+ * build a new stream context
1759
+ *
1760
+ * Returns the new structure or NULL in case of error.
1761
+ */
1762
+ static xmlStreamCtxtPtr
1763
+ xmlNewStreamCtxt(xmlStreamCompPtr stream) {
1764
+ xmlStreamCtxtPtr cur;
1765
+
1766
+ cur = (xmlStreamCtxtPtr) xmlMalloc(sizeof(xmlStreamCtxt));
1767
+ if (cur == NULL) {
1768
+ ERROR(NULL, NULL, NULL,
1769
+ "xmlNewStreamCtxt: malloc failed\n");
1770
+ return(NULL);
1771
+ }
1772
+ memset(cur, 0, sizeof(xmlStreamCtxt));
1773
+ cur->states = (int *) xmlMalloc(4 * 2 * sizeof(int));
1774
+ if (cur->states == NULL) {
1775
+ xmlFree(cur);
1776
+ ERROR(NULL, NULL, NULL,
1777
+ "xmlNewStreamCtxt: malloc failed\n");
1778
+ return(NULL);
1779
+ }
1780
+ cur->nbState = 0;
1781
+ cur->maxState = 4;
1782
+ cur->level = 0;
1783
+ cur->comp = stream;
1784
+ cur->blockLevel = -1;
1785
+ return(cur);
1786
+ }
1787
+
1788
+ /**
1789
+ * xmlFreeStreamCtxt:
1790
+ * @stream: the stream context
1791
+ *
1792
+ * Free the stream context
1793
+ */
1794
+ void
1795
+ xmlFreeStreamCtxt(xmlStreamCtxtPtr stream) {
1796
+ xmlStreamCtxtPtr next;
1797
+
1798
+ while (stream != NULL) {
1799
+ next = stream->next;
1800
+ if (stream->states != NULL)
1801
+ xmlFree(stream->states);
1802
+ xmlFree(stream);
1803
+ stream = next;
1804
+ }
1805
+ }
1806
+
1807
+ /**
1808
+ * xmlStreamCtxtAddState:
1809
+ * @comp: the stream context
1810
+ * @idx: the step index for that streaming state
1811
+ *
1812
+ * Add a new state to the stream context
1813
+ *
1814
+ * Returns -1 in case of error or the state index if successful
1815
+ */
1816
+ static int
1817
+ xmlStreamCtxtAddState(xmlStreamCtxtPtr comp, int idx, int level) {
1818
+ int i;
1819
+ for (i = 0;i < comp->nbState;i++) {
1820
+ if (comp->states[2 * i] < 0) {
1821
+ comp->states[2 * i] = idx;
1822
+ comp->states[2 * i + 1] = level;
1823
+ return(i);
1824
+ }
1825
+ }
1826
+ if (comp->nbState >= comp->maxState) {
1827
+ int *cur;
1828
+
1829
+ cur = (int *) xmlRealloc(comp->states,
1830
+ comp->maxState * 4 * sizeof(int));
1831
+ if (cur == NULL) {
1832
+ ERROR(NULL, NULL, NULL,
1833
+ "xmlNewStreamCtxt: malloc failed\n");
1834
+ return(-1);
1835
+ }
1836
+ comp->states = cur;
1837
+ comp->maxState *= 2;
1838
+ }
1839
+ comp->states[2 * comp->nbState] = idx;
1840
+ comp->states[2 * comp->nbState++ + 1] = level;
1841
+ return(comp->nbState - 1);
1842
+ }
1843
+
1844
+ /**
1845
+ * xmlStreamPushInternal:
1846
+ * @stream: the stream context
1847
+ * @name: the current name
1848
+ * @ns: the namespace name
1849
+ * @nodeType: the type of the node
1850
+ *
1851
+ * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
1852
+ * indicated a dictionary, then strings for name and ns will be expected
1853
+ * to come from the dictionary.
1854
+ * Both @name and @ns being NULL means the / i.e. the root of the document.
1855
+ * This can also act as a reset.
1856
+ *
1857
+ * Returns: -1 in case of error, 1 if the current state in the stream is a
1858
+ * match and 0 otherwise.
1859
+ */
1860
+ static int
1861
+ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
1862
+ const xmlChar *name, const xmlChar *ns,
1863
+ int nodeType) {
1864
+ int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc;
1865
+ xmlStreamCompPtr comp;
1866
+ xmlStreamStep step;
1867
+ #ifdef DEBUG_STREAMING
1868
+ xmlStreamCtxtPtr orig = stream;
1869
+ #endif
1870
+
1871
+ if ((stream == NULL) || (stream->nbState < 0))
1872
+ return(-1);
1873
+
1874
+ while (stream != NULL) {
1875
+ comp = stream->comp;
1876
+
1877
+ if ((nodeType == XML_ELEMENT_NODE) &&
1878
+ (name == NULL) && (ns == NULL)) {
1879
+ /* We have a document node here (or a reset). */
1880
+ stream->nbState = 0;
1881
+ stream->level = 0;
1882
+ stream->blockLevel = -1;
1883
+ if (comp->flags & XML_STREAM_FROM_ROOT) {
1884
+ if (comp->nbStep == 0) {
1885
+ /* TODO: We have a "/." here? */
1886
+ ret = 1;
1887
+ } else {
1888
+ if ((comp->nbStep == 1) &&
1889
+ (comp->steps[0].nodeType == XML_STREAM_ANY_NODE) &&
1890
+ (comp->steps[0].flags & XML_STREAM_STEP_DESC))
1891
+ {
1892
+ /*
1893
+ * In the case of "//." the document node will match
1894
+ * as well.
1895
+ */
1896
+ ret = 1;
1897
+ } else if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {
1898
+ /* TODO: Do we need this ? */
1899
+ tmp = xmlStreamCtxtAddState(stream, 0, 0);
1900
+ if (tmp < 0)
1901
+ err++;
1902
+ }
1903
+ }
1904
+ }
1905
+ stream = stream->next;
1906
+ continue; /* while */
1907
+ }
1908
+
1909
+ /*
1910
+ * Fast check for ".".
1911
+ */
1912
+ if (comp->nbStep == 0) {
1913
+ /*
1914
+ * / and . are handled at the XPath node set creation
1915
+ * level by checking min depth
1916
+ */
1917
+ if (stream->flags & XML_PATTERN_XPATH) {
1918
+ stream = stream->next;
1919
+ continue; /* while */
1920
+ }
1921
+ /*
1922
+ * For non-pattern like evaluation like XML Schema IDCs
1923
+ * or traditional XPath expressions, this will match if
1924
+ * we are at the first level only, otherwise on every level.
1925
+ */
1926
+ if ((nodeType != XML_ATTRIBUTE_NODE) &&
1927
+ (((stream->flags & XML_PATTERN_NOTPATTERN) == 0) ||
1928
+ (stream->level == 0))) {
1929
+ ret = 1;
1930
+ }
1931
+ stream->level++;
1932
+ goto stream_next;
1933
+ }
1934
+ if (stream->blockLevel != -1) {
1935
+ /*
1936
+ * Skip blocked expressions.
1937
+ */
1938
+ stream->level++;
1939
+ goto stream_next;
1940
+ }
1941
+
1942
+ if ((nodeType != XML_ELEMENT_NODE) &&
1943
+ (nodeType != XML_ATTRIBUTE_NODE) &&
1944
+ ((comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) == 0)) {
1945
+ /*
1946
+ * No need to process nodes of other types if we don't
1947
+ * resolve to those types.
1948
+ * TODO: Do we need to block the context here?
1949
+ */
1950
+ stream->level++;
1951
+ goto stream_next;
1952
+ }
1953
+
1954
+ /*
1955
+ * Check evolution of existing states
1956
+ */
1957
+ i = 0;
1958
+ m = stream->nbState;
1959
+ while (i < m) {
1960
+ if ((comp->flags & XML_STREAM_DESC) == 0) {
1961
+ /*
1962
+ * If there is no "//", then only the last
1963
+ * added state is of interest.
1964
+ */
1965
+ stepNr = stream->states[2 * (stream->nbState -1)];
1966
+ /*
1967
+ * TODO: Security check, should not happen, remove it.
1968
+ */
1969
+ if (stream->states[(2 * (stream->nbState -1)) + 1] <
1970
+ stream->level) {
1971
+ return (-1);
1972
+ }
1973
+ desc = 0;
1974
+ /* loop-stopper */
1975
+ i = m;
1976
+ } else {
1977
+ /*
1978
+ * If there are "//", then we need to process every "//"
1979
+ * occurring in the states, plus any other state for this
1980
+ * level.
1981
+ */
1982
+ stepNr = stream->states[2 * i];
1983
+
1984
+ /* TODO: should not happen anymore: dead states */
1985
+ if (stepNr < 0)
1986
+ goto next_state;
1987
+
1988
+ tmp = stream->states[(2 * i) + 1];
1989
+
1990
+ /* skip new states just added */
1991
+ if (tmp > stream->level)
1992
+ goto next_state;
1993
+
1994
+ /* skip states at ancestor levels, except if "//" */
1995
+ desc = comp->steps[stepNr].flags & XML_STREAM_STEP_DESC;
1996
+ if ((tmp < stream->level) && (!desc))
1997
+ goto next_state;
1998
+ }
1999
+ /*
2000
+ * Check for correct node-type.
2001
+ */
2002
+ step = comp->steps[stepNr];
2003
+ if (step.nodeType != nodeType) {
2004
+ if (step.nodeType == XML_ATTRIBUTE_NODE) {
2005
+ /*
2006
+ * Block this expression for deeper evaluation.
2007
+ */
2008
+ if ((comp->flags & XML_STREAM_DESC) == 0)
2009
+ stream->blockLevel = stream->level +1;
2010
+ goto next_state;
2011
+ } else if (step.nodeType != XML_STREAM_ANY_NODE)
2012
+ goto next_state;
2013
+ }
2014
+ /*
2015
+ * Compare local/namespace-name.
2016
+ */
2017
+ match = 0;
2018
+ if (step.nodeType == XML_STREAM_ANY_NODE) {
2019
+ match = 1;
2020
+ } else if (step.name == NULL) {
2021
+ if (step.ns == NULL) {
2022
+ /*
2023
+ * This lets through all elements/attributes.
2024
+ */
2025
+ match = 1;
2026
+ } else if (ns != NULL)
2027
+ match = xmlStrEqual(step.ns, ns);
2028
+ } else if (((step.ns != NULL) == (ns != NULL)) &&
2029
+ (name != NULL) &&
2030
+ (step.name[0] == name[0]) &&
2031
+ xmlStrEqual(step.name, name) &&
2032
+ ((step.ns == ns) || xmlStrEqual(step.ns, ns)))
2033
+ {
2034
+ match = 1;
2035
+ }
2036
+ #if 0
2037
+ /*
2038
+ * TODO: Pointer comparison won't work, since not guaranteed that the given
2039
+ * values are in the same dict; especially if it's the namespace name,
2040
+ * normally coming from ns->href. We need a namespace dict mechanism !
2041
+ */
2042
+ } else if (comp->dict) {
2043
+ if (step.name == NULL) {
2044
+ if (step.ns == NULL)
2045
+ match = 1;
2046
+ else
2047
+ match = (step.ns == ns);
2048
+ } else {
2049
+ match = ((step.name == name) && (step.ns == ns));
2050
+ }
2051
+ #endif /* if 0 ------------------------------------------------------- */
2052
+ if (match) {
2053
+ final = step.flags & XML_STREAM_STEP_FINAL;
2054
+ if (desc) {
2055
+ if (final) {
2056
+ ret = 1;
2057
+ } else {
2058
+ /* descending match create a new state */
2059
+ xmlStreamCtxtAddState(stream, stepNr + 1,
2060
+ stream->level + 1);
2061
+ }
2062
+ } else {
2063
+ if (final) {
2064
+ ret = 1;
2065
+ } else {
2066
+ xmlStreamCtxtAddState(stream, stepNr + 1,
2067
+ stream->level + 1);
2068
+ }
2069
+ }
2070
+ if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
2071
+ /*
2072
+ * Check if we have a special case like "foo/bar//.", where
2073
+ * "foo" is selected as well.
2074
+ */
2075
+ ret = 1;
2076
+ }
2077
+ }
2078
+ if (((comp->flags & XML_STREAM_DESC) == 0) &&
2079
+ ((! match) || final)) {
2080
+ /*
2081
+ * Mark this expression as blocked for any evaluation at
2082
+ * deeper levels. Note that this includes "/foo"
2083
+ * expressions if the *pattern* behaviour is used.
2084
+ */
2085
+ stream->blockLevel = stream->level +1;
2086
+ }
2087
+ next_state:
2088
+ i++;
2089
+ }
2090
+
2091
+ stream->level++;
2092
+
2093
+ /*
2094
+ * Re/enter the expression.
2095
+ * Don't reenter if it's an absolute expression like "/foo",
2096
+ * except "//foo".
2097
+ */
2098
+ step = comp->steps[0];
2099
+ if (step.flags & XML_STREAM_STEP_ROOT)
2100
+ goto stream_next;
2101
+
2102
+ desc = step.flags & XML_STREAM_STEP_DESC;
2103
+ if (stream->flags & XML_PATTERN_NOTPATTERN) {
2104
+ /*
2105
+ * Re/enter the expression if it is a "descendant" one,
2106
+ * or if we are at the 1st level of evaluation.
2107
+ */
2108
+
2109
+ if (stream->level == 1) {
2110
+ if (XML_STREAM_XS_IDC(stream)) {
2111
+ /*
2112
+ * XS-IDC: The missing "self::node()" will always
2113
+ * match the first given node.
2114
+ */
2115
+ goto stream_next;
2116
+ } else
2117
+ goto compare;
2118
+ }
2119
+ /*
2120
+ * A "//" is always reentrant.
2121
+ */
2122
+ if (desc)
2123
+ goto compare;
2124
+
2125
+ /*
2126
+ * XS-IDC: Process the 2nd level, since the missing
2127
+ * "self::node()" is responsible for the 2nd level being
2128
+ * the real start level.
2129
+ */
2130
+ if ((stream->level == 2) && XML_STREAM_XS_IDC(stream))
2131
+ goto compare;
2132
+
2133
+ goto stream_next;
2134
+ }
2135
+
2136
+ compare:
2137
+ /*
2138
+ * Check expected node-type.
2139
+ */
2140
+ if (step.nodeType != nodeType) {
2141
+ if (nodeType == XML_ATTRIBUTE_NODE)
2142
+ goto stream_next;
2143
+ else if (step.nodeType != XML_STREAM_ANY_NODE)
2144
+ goto stream_next;
2145
+ }
2146
+ /*
2147
+ * Compare local/namespace-name.
2148
+ */
2149
+ match = 0;
2150
+ if (step.nodeType == XML_STREAM_ANY_NODE) {
2151
+ match = 1;
2152
+ } else if (step.name == NULL) {
2153
+ if (step.ns == NULL) {
2154
+ /*
2155
+ * This lets through all elements/attributes.
2156
+ */
2157
+ match = 1;
2158
+ } else if (ns != NULL)
2159
+ match = xmlStrEqual(step.ns, ns);
2160
+ } else if (((step.ns != NULL) == (ns != NULL)) &&
2161
+ (name != NULL) &&
2162
+ (step.name[0] == name[0]) &&
2163
+ xmlStrEqual(step.name, name) &&
2164
+ ((step.ns == ns) || xmlStrEqual(step.ns, ns)))
2165
+ {
2166
+ match = 1;
2167
+ }
2168
+ final = step.flags & XML_STREAM_STEP_FINAL;
2169
+ if (match) {
2170
+ if (final)
2171
+ ret = 1;
2172
+ else
2173
+ xmlStreamCtxtAddState(stream, 1, stream->level);
2174
+ if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
2175
+ /*
2176
+ * Check if we have a special case like "foo//.", where
2177
+ * "foo" is selected as well.
2178
+ */
2179
+ ret = 1;
2180
+ }
2181
+ }
2182
+ if (((comp->flags & XML_STREAM_DESC) == 0) &&
2183
+ ((! match) || final)) {
2184
+ /*
2185
+ * Mark this expression as blocked for any evaluation at
2186
+ * deeper levels.
2187
+ */
2188
+ stream->blockLevel = stream->level;
2189
+ }
2190
+
2191
+ stream_next:
2192
+ stream = stream->next;
2193
+ } /* while stream != NULL */
2194
+
2195
+ if (err > 0)
2196
+ ret = -1;
2197
+ #ifdef DEBUG_STREAMING
2198
+ xmlDebugStreamCtxt(orig, ret);
2199
+ #endif
2200
+ return(ret);
2201
+ }
2202
+
2203
+ /**
2204
+ * xmlStreamPush:
2205
+ * @stream: the stream context
2206
+ * @name: the current name
2207
+ * @ns: the namespace name
2208
+ *
2209
+ * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
2210
+ * indicated a dictionary, then strings for name and ns will be expected
2211
+ * to come from the dictionary.
2212
+ * Both @name and @ns being NULL means the / i.e. the root of the document.
2213
+ * This can also act as a reset.
2214
+ * Otherwise the function will act as if it has been given an element-node.
2215
+ *
2216
+ * Returns: -1 in case of error, 1 if the current state in the stream is a
2217
+ * match and 0 otherwise.
2218
+ */
2219
+ int
2220
+ xmlStreamPush(xmlStreamCtxtPtr stream,
2221
+ const xmlChar *name, const xmlChar *ns) {
2222
+ return (xmlStreamPushInternal(stream, name, ns, (int) XML_ELEMENT_NODE));
2223
+ }
2224
+
2225
+ /**
2226
+ * xmlStreamPushNode:
2227
+ * @stream: the stream context
2228
+ * @name: the current name
2229
+ * @ns: the namespace name
2230
+ * @nodeType: the type of the node being pushed
2231
+ *
2232
+ * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
2233
+ * indicated a dictionary, then strings for name and ns will be expected
2234
+ * to come from the dictionary.
2235
+ * Both @name and @ns being NULL means the / i.e. the root of the document.
2236
+ * This can also act as a reset.
2237
+ * Different from xmlStreamPush() this function can be fed with nodes of type:
2238
+ * element-, attribute-, text-, cdata-section-, comment- and
2239
+ * processing-instruction-node.
2240
+ *
2241
+ * Returns: -1 in case of error, 1 if the current state in the stream is a
2242
+ * match and 0 otherwise.
2243
+ */
2244
+ int
2245
+ xmlStreamPushNode(xmlStreamCtxtPtr stream,
2246
+ const xmlChar *name, const xmlChar *ns,
2247
+ int nodeType)
2248
+ {
2249
+ return (xmlStreamPushInternal(stream, name, ns,
2250
+ nodeType));
2251
+ }
2252
+
2253
+ /**
2254
+ * xmlStreamPushAttr:
2255
+ * @stream: the stream context
2256
+ * @name: the current name
2257
+ * @ns: the namespace name
2258
+ *
2259
+ * Push new attribute data onto the stream. NOTE: if the call xmlPatterncompile()
2260
+ * indicated a dictionary, then strings for name and ns will be expected
2261
+ * to come from the dictionary.
2262
+ * Both @name and @ns being NULL means the / i.e. the root of the document.
2263
+ * This can also act as a reset.
2264
+ * Otherwise the function will act as if it has been given an attribute-node.
2265
+ *
2266
+ * Returns: -1 in case of error, 1 if the current state in the stream is a
2267
+ * match and 0 otherwise.
2268
+ */
2269
+ int
2270
+ xmlStreamPushAttr(xmlStreamCtxtPtr stream,
2271
+ const xmlChar *name, const xmlChar *ns) {
2272
+ return (xmlStreamPushInternal(stream, name, ns, (int) XML_ATTRIBUTE_NODE));
2273
+ }
2274
+
2275
+ /**
2276
+ * xmlStreamPop:
2277
+ * @stream: the stream context
2278
+ *
2279
+ * push one level from the stream.
2280
+ *
2281
+ * Returns: -1 in case of error, 0 otherwise.
2282
+ */
2283
+ int
2284
+ xmlStreamPop(xmlStreamCtxtPtr stream) {
2285
+ int i, lev;
2286
+
2287
+ if (stream == NULL)
2288
+ return(-1);
2289
+ while (stream != NULL) {
2290
+ /*
2291
+ * Reset block-level.
2292
+ */
2293
+ if (stream->blockLevel == stream->level)
2294
+ stream->blockLevel = -1;
2295
+
2296
+ /*
2297
+ * stream->level can be zero when XML_FINAL_IS_ANY_NODE is set
2298
+ * (see the thread at
2299
+ * http://mail.gnome.org/archives/xslt/2008-July/msg00027.html)
2300
+ */
2301
+ if (stream->level)
2302
+ stream->level--;
2303
+ /*
2304
+ * Check evolution of existing states
2305
+ */
2306
+ for (i = stream->nbState -1; i >= 0; i--) {
2307
+ /* discard obsoleted states */
2308
+ lev = stream->states[(2 * i) + 1];
2309
+ if (lev > stream->level)
2310
+ stream->nbState--;
2311
+ if (lev <= stream->level)
2312
+ break;
2313
+ }
2314
+ stream = stream->next;
2315
+ }
2316
+ return(0);
2317
+ }
2318
+
2319
+ /**
2320
+ * xmlStreamWantsAnyNode:
2321
+ * @streamCtxt: the stream context
2322
+ *
2323
+ * Query if the streaming pattern additionally needs to be fed with
2324
+ * text-, cdata-section-, comment- and processing-instruction-nodes.
2325
+ * If the result is 0 then only element-nodes and attribute-nodes
2326
+ * need to be pushed.
2327
+ *
2328
+ * Returns: 1 in case of need of nodes of the above described types,
2329
+ * 0 otherwise. -1 on API errors.
2330
+ */
2331
+ int
2332
+ xmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt)
2333
+ {
2334
+ if (streamCtxt == NULL)
2335
+ return(-1);
2336
+ while (streamCtxt != NULL) {
2337
+ if (streamCtxt->comp->flags & XML_STREAM_FINAL_IS_ANY_NODE)
2338
+ return(1);
2339
+ streamCtxt = streamCtxt->next;
2340
+ }
2341
+ return(0);
2342
+ }
2343
+
2344
+ /************************************************************************
2345
+ * *
2346
+ * The public interfaces *
2347
+ * *
2348
+ ************************************************************************/
2349
+
2350
+ /**
2351
+ * xmlPatterncompile:
2352
+ * @pattern: the pattern to compile
2353
+ * @dict: an optional dictionary for interned strings
2354
+ * @flags: compilation flags, see xmlPatternFlags
2355
+ * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
2356
+ *
2357
+ * Compile a pattern.
2358
+ *
2359
+ * Returns the compiled form of the pattern or NULL in case of error
2360
+ */
2361
+ xmlPatternPtr
2362
+ xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
2363
+ const xmlChar **namespaces) {
2364
+ xmlPatternPtr ret = NULL, cur;
2365
+ xmlPatParserContextPtr ctxt = NULL;
2366
+ const xmlChar *or, *start;
2367
+ xmlChar *tmp = NULL;
2368
+ int type = 0;
2369
+ int streamable = 1;
2370
+
2371
+ if (pattern == NULL)
2372
+ return(NULL);
2373
+
2374
+ start = pattern;
2375
+ or = start;
2376
+ while (*or != 0) {
2377
+ tmp = NULL;
2378
+ while ((*or != 0) && (*or != '|')) or++;
2379
+ if (*or == 0)
2380
+ ctxt = xmlNewPatParserContext(start, dict, namespaces);
2381
+ else {
2382
+ tmp = xmlStrndup(start, or - start);
2383
+ if (tmp != NULL) {
2384
+ ctxt = xmlNewPatParserContext(tmp, dict, namespaces);
2385
+ }
2386
+ or++;
2387
+ }
2388
+ if (ctxt == NULL) goto error;
2389
+ cur = xmlNewPattern();
2390
+ if (cur == NULL) goto error;
2391
+ /*
2392
+ * Assign string dict.
2393
+ */
2394
+ if (dict) {
2395
+ cur->dict = dict;
2396
+ xmlDictReference(dict);
2397
+ }
2398
+ if (ret == NULL)
2399
+ ret = cur;
2400
+ else {
2401
+ cur->next = ret->next;
2402
+ ret->next = cur;
2403
+ }
2404
+ cur->flags = flags;
2405
+ ctxt->comp = cur;
2406
+
2407
+ if (XML_STREAM_XS_IDC(cur))
2408
+ xmlCompileIDCXPathPath(ctxt);
2409
+ else
2410
+ xmlCompilePathPattern(ctxt);
2411
+ if (ctxt->error != 0)
2412
+ goto error;
2413
+ xmlFreePatParserContext(ctxt);
2414
+ ctxt = NULL;
2415
+
2416
+
2417
+ if (streamable) {
2418
+ if (type == 0) {
2419
+ type = cur->flags & (PAT_FROM_ROOT | PAT_FROM_CUR);
2420
+ } else if (type == PAT_FROM_ROOT) {
2421
+ if (cur->flags & PAT_FROM_CUR)
2422
+ streamable = 0;
2423
+ } else if (type == PAT_FROM_CUR) {
2424
+ if (cur->flags & PAT_FROM_ROOT)
2425
+ streamable = 0;
2426
+ }
2427
+ }
2428
+ if (streamable)
2429
+ xmlStreamCompile(cur);
2430
+ if (xmlReversePattern(cur) < 0)
2431
+ goto error;
2432
+ if (tmp != NULL) {
2433
+ xmlFree(tmp);
2434
+ tmp = NULL;
2435
+ }
2436
+ start = or;
2437
+ }
2438
+ if (streamable == 0) {
2439
+ cur = ret;
2440
+ while (cur != NULL) {
2441
+ if (cur->stream != NULL) {
2442
+ xmlFreeStreamComp(cur->stream);
2443
+ cur->stream = NULL;
2444
+ }
2445
+ cur = cur->next;
2446
+ }
2447
+ }
2448
+
2449
+ return(ret);
2450
+ error:
2451
+ if (ctxt != NULL) xmlFreePatParserContext(ctxt);
2452
+ if (ret != NULL) xmlFreePattern(ret);
2453
+ if (tmp != NULL) xmlFree(tmp);
2454
+ return(NULL);
2455
+ }
2456
+
2457
+ /**
2458
+ * xmlPatternMatch:
2459
+ * @comp: the precompiled pattern
2460
+ * @node: a node
2461
+ *
2462
+ * Test whether the node matches the pattern
2463
+ *
2464
+ * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
2465
+ */
2466
+ int
2467
+ xmlPatternMatch(xmlPatternPtr comp, xmlNodePtr node)
2468
+ {
2469
+ int ret = 0;
2470
+
2471
+ if ((comp == NULL) || (node == NULL))
2472
+ return(-1);
2473
+
2474
+ while (comp != NULL) {
2475
+ ret = xmlPatMatch(comp, node);
2476
+ if (ret != 0)
2477
+ return(ret);
2478
+ comp = comp->next;
2479
+ }
2480
+ return(ret);
2481
+ }
2482
+
2483
+ /**
2484
+ * xmlPatternGetStreamCtxt:
2485
+ * @comp: the precompiled pattern
2486
+ *
2487
+ * Get a streaming context for that pattern
2488
+ * Use xmlFreeStreamCtxt to free the context.
2489
+ *
2490
+ * Returns a pointer to the context or NULL in case of failure
2491
+ */
2492
+ xmlStreamCtxtPtr
2493
+ xmlPatternGetStreamCtxt(xmlPatternPtr comp)
2494
+ {
2495
+ xmlStreamCtxtPtr ret = NULL, cur;
2496
+
2497
+ if ((comp == NULL) || (comp->stream == NULL))
2498
+ return(NULL);
2499
+
2500
+ while (comp != NULL) {
2501
+ if (comp->stream == NULL)
2502
+ goto failed;
2503
+ cur = xmlNewStreamCtxt(comp->stream);
2504
+ if (cur == NULL)
2505
+ goto failed;
2506
+ if (ret == NULL)
2507
+ ret = cur;
2508
+ else {
2509
+ cur->next = ret->next;
2510
+ ret->next = cur;
2511
+ }
2512
+ cur->flags = comp->flags;
2513
+ comp = comp->next;
2514
+ }
2515
+ return(ret);
2516
+ failed:
2517
+ xmlFreeStreamCtxt(ret);
2518
+ return(NULL);
2519
+ }
2520
+
2521
+ /**
2522
+ * xmlPatternStreamable:
2523
+ * @comp: the precompiled pattern
2524
+ *
2525
+ * Check if the pattern is streamable i.e. xmlPatternGetStreamCtxt()
2526
+ * should work.
2527
+ *
2528
+ * Returns 1 if streamable, 0 if not and -1 in case of error.
2529
+ */
2530
+ int
2531
+ xmlPatternStreamable(xmlPatternPtr comp) {
2532
+ if (comp == NULL)
2533
+ return(-1);
2534
+ while (comp != NULL) {
2535
+ if (comp->stream == NULL)
2536
+ return(0);
2537
+ comp = comp->next;
2538
+ }
2539
+ return(1);
2540
+ }
2541
+
2542
+ /**
2543
+ * xmlPatternMaxDepth:
2544
+ * @comp: the precompiled pattern
2545
+ *
2546
+ * Check the maximum depth reachable by a pattern
2547
+ *
2548
+ * Returns -2 if no limit (using //), otherwise the depth,
2549
+ * and -1 in case of error
2550
+ */
2551
+ int
2552
+ xmlPatternMaxDepth(xmlPatternPtr comp) {
2553
+ int ret = 0, i;
2554
+ if (comp == NULL)
2555
+ return(-1);
2556
+ while (comp != NULL) {
2557
+ if (comp->stream == NULL)
2558
+ return(-1);
2559
+ for (i = 0;i < comp->stream->nbStep;i++)
2560
+ if (comp->stream->steps[i].flags & XML_STREAM_STEP_DESC)
2561
+ return(-2);
2562
+ if (comp->stream->nbStep > ret)
2563
+ ret = comp->stream->nbStep;
2564
+ comp = comp->next;
2565
+ }
2566
+ return(ret);
2567
+ }
2568
+
2569
+ /**
2570
+ * xmlPatternMinDepth:
2571
+ * @comp: the precompiled pattern
2572
+ *
2573
+ * Check the minimum depth reachable by a pattern, 0 mean the / or . are
2574
+ * part of the set.
2575
+ *
2576
+ * Returns -1 in case of error otherwise the depth,
2577
+ *
2578
+ */
2579
+ int
2580
+ xmlPatternMinDepth(xmlPatternPtr comp) {
2581
+ int ret = 12345678;
2582
+ if (comp == NULL)
2583
+ return(-1);
2584
+ while (comp != NULL) {
2585
+ if (comp->stream == NULL)
2586
+ return(-1);
2587
+ if (comp->stream->nbStep < ret)
2588
+ ret = comp->stream->nbStep;
2589
+ if (ret == 0)
2590
+ return(0);
2591
+ comp = comp->next;
2592
+ }
2593
+ return(ret);
2594
+ }
2595
+
2596
+ /**
2597
+ * xmlPatternFromRoot:
2598
+ * @comp: the precompiled pattern
2599
+ *
2600
+ * Check if the pattern must be looked at from the root.
2601
+ *
2602
+ * Returns 1 if true, 0 if false and -1 in case of error
2603
+ */
2604
+ int
2605
+ xmlPatternFromRoot(xmlPatternPtr comp) {
2606
+ if (comp == NULL)
2607
+ return(-1);
2608
+ while (comp != NULL) {
2609
+ if (comp->stream == NULL)
2610
+ return(-1);
2611
+ if (comp->flags & PAT_FROM_ROOT)
2612
+ return(1);
2613
+ comp = comp->next;
2614
+ }
2615
+ return(0);
2616
+
2617
+ }
2618
+
2619
+ #define bottom_pattern
2620
+ #include "elfgcchack.h"
2621
+ #endif /* LIBXML_PATTERN_ENABLED */