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