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