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