1b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/*
2b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * pattern.c: Implemetation of selectors for nodes
3b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
4b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Reference:
5b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *   http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/
6f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *   to some extent
7b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *   http://www.w3.org/TR/1999/REC-xml-19991116
8b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
9b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * See Copyright for the status of this software.
10b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
11b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * daniel@veillard.com
12b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
13b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
14f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard/*
15f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard * TODO:
16f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard * - compilation flags to check for specific syntaxes
17f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard *   using flags of xmlPatterncompile()
18f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard * - making clear how pattern starting with / or . need to be handled,
19f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard *   currently push(NULL, NULL) means a reset of the streaming context
20f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard *   and indicating we are on / (the document node), probably need
21f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard *   something similar for .
22d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard * - get rid of the "compile" starting with lowercase
236ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik * - DONE (2006-05-16): get rid of the Strdup/Strndup in case of dictionary
24f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard */
25f9d169142dd652f5e077e1c2391facaa6bf40f4dDaniel Veillard
26b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define IN_LIBXML
27b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include "libxml.h"
28b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
29b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include <string.h>
30b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include <libxml/xmlmemory.h>
31b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include <libxml/tree.h>
32b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include <libxml/hash.h>
33b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include <libxml/dict.h>
34b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include <libxml/xmlerror.h>
35b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include <libxml/parserInternals.h>
36b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#include <libxml/pattern.h>
37b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
38d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard#ifdef LIBXML_PATTERN_ENABLED
39b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
40d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard/* #define DEBUG_STREAMING */
412fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
42204f1f144ce1eded7dd25162c1c67e66a93fe450Patrick R. Gansterer#ifdef ERROR
43204f1f144ce1eded7dd25162c1c67e66a93fe450Patrick R. Gansterer#undef ERROR
44204f1f144ce1eded7dd25162c1c67e66a93fe450Patrick R. Gansterer#endif
45b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define ERROR(a, b, c, d)
46b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define ERROR5(a, b, c, d, e)
47b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
482fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard#define XML_STREAM_STEP_DESC	1
492fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard#define XML_STREAM_STEP_FINAL	2
502fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard#define XML_STREAM_STEP_ROOT	4
512a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik#define XML_STREAM_STEP_ATTR	8
5297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#define XML_STREAM_STEP_NODE	16
53bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik#define XML_STREAM_STEP_IN_SET	32
542fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
559ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik/*
5697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik* NOTE: Those private flags (XML_STREAM_xxx) are used
5797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   in _xmlStreamCtxt->flag. They extend the public
5897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*   xmlPatternFlags, so be carefull not to interfere with the
59f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard*   reserved values for xmlPatternFlags.
609ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik*/
6197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#define XML_STREAM_FINAL_IS_ANY_NODE 1<<14
6297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#define XML_STREAM_FROM_ROOT 1<<15
639ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik#define XML_STREAM_DESC 1<<16
649ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
6597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik/*
6697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik* XML_STREAM_ANY_NODE is used for comparison against
6797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik* xmlElementType enums, to indicate a node of any type.
6897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik*/
6997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik#define XML_STREAM_ANY_NODE 100
7097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
71ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack#define XML_PATTERN_NOTPATTERN  (XML_PATTERN_XPATH | \
72ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack				 XML_PATTERN_XSSEL | \
73ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack				 XML_PATTERN_XSFIELD)
749ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
75940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik#define XML_STREAM_XS_IDC(c) ((c)->flags & \
769ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik    (XML_PATTERN_XSSEL | XML_PATTERN_XSFIELD))
77285ebabb07c93921a60e4ab2dbefcbc0c49fb334Kasimier T. Buchcik
78940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik#define XML_STREAM_XS_IDC_SEL(c) ((c)->flags & XML_PATTERN_XSSEL)
79940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik
80940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik#define XML_STREAM_XS_IDC_FIELD(c) ((c)->flags & XML_PATTERN_XSFIELD)
81940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik
826ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik#define XML_PAT_COPY_NSNAME(c, r, nsname) \
836ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    if ((c)->comp->dict) \
846ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	r = (xmlChar *) xmlDictLookup((c)->comp->dict, BAD_CAST nsname, -1); \
856ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    else r = xmlStrdup(BAD_CAST nsname);
866ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik
876ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik#define XML_PAT_FREE_STRING(c, r) if ((c)->comp->dict == NULL) xmlFree(r);
886ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik
892fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardtypedef struct _xmlStreamStep xmlStreamStep;
902fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardtypedef xmlStreamStep *xmlStreamStepPtr;
912fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstruct _xmlStreamStep {
922fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    int flags;			/* properties of that step */
932fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    const xmlChar *name;	/* first string value if NULL accept all */
942fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    const xmlChar *ns;		/* second string value */
9597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    int nodeType;		/* type of node */
962fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard};
972fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
982fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardtypedef struct _xmlStreamComp xmlStreamComp;
992fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardtypedef xmlStreamComp *xmlStreamCompPtr;
1002fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstruct _xmlStreamComp {
101fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack    xmlDict *dict;		/* the dictionary if any */
1022fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    int nbStep;			/* number of steps in the automata */
1032fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    int maxStep;		/* allocated number of steps */
1042fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlStreamStepPtr steps;	/* the array of steps */
1059ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik    int flags;
1062fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard};
1072fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
1082fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstruct _xmlStreamCtxt {
109f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    struct _xmlStreamCtxt *next;/* link to next sub pattern if | */
1102fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlStreamCompPtr comp;	/* the compiled stream */
111fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack    int nbState;		/* number of states in the automata */
112fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack    int maxState;		/* allocated number of states */
1132fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    int level;			/* how deep are we ? */
1142fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    int *states;		/* the array of step indexes */
115285ebabb07c93921a60e4ab2dbefcbc0c49fb334Kasimier T. Buchcik    int flags;			/* validation options */
1169ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik    int blockLevel;
1172fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard};
1182fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
1192fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic void xmlFreeStreamComp(xmlStreamCompPtr comp);
1202fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
121b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/*
122b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Types are private:
123b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
124b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
125b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardtypedef enum {
126b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_END=0,
127b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_ROOT,
128b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_ELEM,
129b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_CHILD,
130b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_ATTR,
131b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_PARENT,
132b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_ANCESTOR,
133b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_NS,
134b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    XML_OP_ALL
135b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard} xmlPatOp;
136b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
137b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
138d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardtypedef struct _xmlStepState xmlStepState;
139d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardtypedef xmlStepState *xmlStepStatePtr;
140d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardstruct _xmlStepState {
141d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    int step;
142d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    xmlNodePtr node;
143d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard};
144d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard
145d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardtypedef struct _xmlStepStates xmlStepStates;
146d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardtypedef xmlStepStates *xmlStepStatesPtr;
147d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardstruct _xmlStepStates {
148d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    int nbstates;
149d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    int maxstates;
150d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    xmlStepStatePtr states;
151d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard};
152d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard
153b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardtypedef struct _xmlStepOp xmlStepOp;
154b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardtypedef xmlStepOp *xmlStepOpPtr;
155b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstruct _xmlStepOp {
156b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlPatOp op;
157b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    const xmlChar *value;
1586ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    const xmlChar *value2; /* The namespace name */
159b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard};
160b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
161ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack#define PAT_FROM_ROOT	(1<<8)
162ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack#define PAT_FROM_CUR	(1<<9)
16356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
164b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstruct _xmlPattern {
165f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard    void *data;		/* the associated template */
166fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack    xmlDictPtr dict;		/* the optional dictionary */
167f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    struct _xmlPattern *next;	/* next pattern if | is used */
168b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    const xmlChar *pattern;	/* the pattern */
169f5812c3179f94dc050e9783e77a182f4e8d3c9eaDaniel Veillard    int flags;			/* flags */
170b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int nbStep;
171b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int maxStep;
172c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    xmlStepOpPtr steps;        /* ops for computation */
1732fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlStreamCompPtr stream;	/* the streaming data if any */
174b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard};
175b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
176b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardtypedef struct _xmlPatParserContext xmlPatParserContext;
177b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardtypedef xmlPatParserContext *xmlPatParserContextPtr;
178b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstruct _xmlPatParserContext {
179b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    const xmlChar *cur;			/* the current char being parsed */
180b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    const xmlChar *base;		/* the full expression */
181b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int	           error;		/* error code */
182fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack    xmlDictPtr     dict;		/* the dictionary if any */
183b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlPatternPtr  comp;		/* the result */
184f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard    xmlNodePtr     elem;		/* the current node if any */
185ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard    const xmlChar **namespaces;		/* the namespaces definitions */
186ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard    int   nb_namespaces;		/* the number of namespaces */
187b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard};
188b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
189b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/************************************************************************
190f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *									*
191f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *			Type functions					*
192f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *									*
193b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard ************************************************************************/
194b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
195b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
196b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlNewPattern:
197b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
198b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Create a new XSLT Pattern
199b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
200b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns the newly allocated xmlPatternPtr or NULL in case of error
201b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
202b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic xmlPatternPtr
203b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlNewPattern(void) {
204b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlPatternPtr cur;
205b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
206b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    cur = (xmlPatternPtr) xmlMalloc(sizeof(xmlPattern));
207b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (cur == NULL) {
208b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	ERROR(NULL, NULL, NULL,
209b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		"xmlNewPattern : malloc failed\n");
210b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	return(NULL);
211b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
212b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    memset(cur, 0, sizeof(xmlPattern));
213b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    cur->maxStep = 10;
214c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    cur->steps = (xmlStepOpPtr) xmlMalloc(cur->maxStep * sizeof(xmlStepOp));
215c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    if (cur->steps == NULL) {
216c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard        xmlFree(cur);
217c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	ERROR(NULL, NULL, NULL,
218c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard		"xmlNewPattern : malloc failed\n");
219c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	return(NULL);
220c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    }
221b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(cur);
222b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
223b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
224b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
225b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlFreePattern:
226b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @comp:  an XSLT comp
227b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
228b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Free up the memory allocated by @comp
229b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
230b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardvoid
231b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlFreePattern(xmlPatternPtr comp) {
232b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlStepOpPtr op;
233b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int i;
234b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
235b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (comp == NULL)
236b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	return;
237f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    if (comp->next != NULL)
238f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard        xmlFreePattern(comp->next);
2392fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (comp->stream != NULL)
2402fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        xmlFreeStreamComp(comp->stream);
241b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (comp->pattern != NULL)
242b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	xmlFree((xmlChar *)comp->pattern);
243c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    if (comp->steps != NULL) {
2442fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        if (comp->dict == NULL) {
2452fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    for (i = 0;i < comp->nbStep;i++) {
2462fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		op = &comp->steps[i];
2472fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		if (op->value != NULL)
2482fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		    xmlFree((xmlChar *) op->value);
2492fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		if (op->value2 != NULL)
2502fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		    xmlFree((xmlChar *) op->value2);
2512fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    }
252c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	}
253c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	xmlFree(comp->steps);
254b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
2552fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (comp->dict != NULL)
2562fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        xmlDictFree(comp->dict);
2572fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
258b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    memset(comp, -1, sizeof(xmlPattern));
259b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlFree(comp);
260b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
261b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
262b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
263b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlFreePatternList:
264b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @comp:  an XSLT comp list
265b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
266b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Free up the memory allocated by all the elements of @comp
267b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
268b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardvoid
269b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlFreePatternList(xmlPatternPtr comp) {
270b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlPatternPtr cur;
271b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
272b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    while (comp != NULL) {
273b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	cur = comp;
274b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp = comp->next;
275fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	cur->next = NULL;
276b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	xmlFreePattern(cur);
277b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
278b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
279b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
280b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
281b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlNewPatParserContext:
282b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @pattern:  the pattern context
283fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * @dict:  the inherited dictionary or NULL
2842fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @namespaces: the prefix definitions, array of [URI, prefix] terminated
2852fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *              with [NULL, NULL] or NULL if no namespace is used
286b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
287b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Create a new XML pattern parser context
288b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
289b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns the newly allocated xmlPatParserContextPtr or NULL in case of error
290b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
291b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic xmlPatParserContextPtr
292ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel VeillardxmlNewPatParserContext(const xmlChar *pattern, xmlDictPtr dict,
293ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard                       const xmlChar **namespaces) {
294b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlPatParserContextPtr cur;
295b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
296b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (pattern == NULL)
297b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard        return(NULL);
298b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
299b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    cur = (xmlPatParserContextPtr) xmlMalloc(sizeof(xmlPatParserContext));
300b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (cur == NULL) {
301b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	ERROR(NULL, NULL, NULL,
302b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		"xmlNewPatParserContext : malloc failed\n");
303b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	return(NULL);
304b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
305b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    memset(cur, 0, sizeof(xmlPatParserContext));
306b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    cur->dict = dict;
307b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    cur->cur = pattern;
308b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    cur->base = pattern;
309ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard    if (namespaces != NULL) {
310ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard        int i;
311cedf84d35ab127dd24f9bcbf8b8339518d0e8928Nico Weber        for (i = 0;namespaces[2 * i] != NULL;i++)
312cedf84d35ab127dd24f9bcbf8b8339518d0e8928Nico Weber            ;
313ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard        cur->nb_namespaces = i;
314ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard    } else {
315ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard        cur->nb_namespaces = 0;
316ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard    }
317ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard    cur->namespaces = namespaces;
318b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(cur);
319b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
320b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
321b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
322b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlFreePatParserContext:
323b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @ctxt:  an XSLT parser context
324b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
325b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Free up the memory allocated by @ctxt
326b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
327b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic void
328b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlFreePatParserContext(xmlPatParserContextPtr ctxt) {
329b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (ctxt == NULL)
330f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	return;
331b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    memset(ctxt, -1, sizeof(xmlPatParserContext));
332b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlFree(ctxt);
333b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
334b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
335b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
336b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlPatternAdd:
337b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @comp:  the compiled match expression
338b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @op:  an op
339b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @value:  the first value
340b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @value2:  the second value
341b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
342fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * Add a step to an XSLT Compiled Match
343b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
344b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns -1 in case of failure, 0 otherwise.
345b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
346b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic int
347b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED,
348b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard                xmlPatternPtr comp,
349b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard                xmlPatOp op, xmlChar * value, xmlChar * value2)
350b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard{
351c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    if (comp->nbStep >= comp->maxStep) {
352c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard        xmlStepOpPtr temp;
353c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	temp = (xmlStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
354c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	                                 sizeof(xmlStepOp));
355c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard        if (temp == NULL) {
356c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	    ERROR(ctxt, NULL, NULL,
357c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard			     "xmlPatternAdd: realloc failed\n");
358c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	    return (-1);
359c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	}
360c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	comp->steps = temp;
361c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	comp->maxStep *= 2;
362b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
363b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    comp->steps[comp->nbStep].op = op;
364b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    comp->steps[comp->nbStep].value = value;
365b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    comp->steps[comp->nbStep].value2 = value2;
366b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    comp->nbStep++;
367b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return (0);
368b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
369b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
370b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#if 0
371b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
372b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xsltSwapTopPattern:
373b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @comp:  the compiled match expression
374b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
375b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * reverse the two top steps.
376b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
377b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic void
378b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxsltSwapTopPattern(xmlPatternPtr comp) {
379b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int i;
380b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int j = comp->nbStep - 1;
381b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
382b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (j > 0) {
383b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	register const xmlChar *tmp;
384b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	register xmlPatOp op;
385b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	i = j - 1;
386b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	tmp = comp->steps[i].value;
387b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[i].value = comp->steps[j].value;
388b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[j].value = tmp;
389b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	tmp = comp->steps[i].value2;
390b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[i].value2 = comp->steps[j].value2;
391b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[j].value2 = tmp;
392b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	op = comp->steps[i].op;
393b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[i].op = comp->steps[j].op;
394b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[j].op = op;
395b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
396b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
397b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#endif
398b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
399b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
400b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlReversePattern:
401b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @comp:  the compiled match expression
402b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
403b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * reverse all the stack of expressions
404c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard *
405c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard * returns 0 in case of success and -1 in case of error.
406b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
407c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillardstatic int
408b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlReversePattern(xmlPatternPtr comp) {
40956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int i, j;
41056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
41156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    /*
41256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     * remove the leading // for //a or .//a
41356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     */
41456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if ((comp->nbStep > 0) && (comp->steps[0].op == XML_OP_ANCESTOR)) {
41556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        for (i = 0, j = 1;j < comp->nbStep;i++,j++) {
41656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp->steps[i].value = comp->steps[j].value;
41756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp->steps[i].value2 = comp->steps[j].value2;
41856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    comp->steps[i].op = comp->steps[j].op;
41956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	}
42056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	comp->nbStep--;
42156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
422c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    if (comp->nbStep >= comp->maxStep) {
423c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard        xmlStepOpPtr temp;
424c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	temp = (xmlStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
425c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	                                 sizeof(xmlStepOp));
426c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard        if (temp == NULL) {
427c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	    ERROR(ctxt, NULL, NULL,
428c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard			     "xmlReversePattern: realloc failed\n");
429c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	    return (-1);
430c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	}
431c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	comp->steps = temp;
432c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard	comp->maxStep *= 2;
433c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    }
43456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    i = 0;
43556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    j = comp->nbStep - 1;
436b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    while (j > i) {
437b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	register const xmlChar *tmp;
438b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	register xmlPatOp op;
439b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	tmp = comp->steps[i].value;
440b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[i].value = comp->steps[j].value;
441b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[j].value = tmp;
442b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	tmp = comp->steps[i].value2;
443b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[i].value2 = comp->steps[j].value2;
444b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[j].value2 = tmp;
445b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	op = comp->steps[i].op;
446b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[i].op = comp->steps[j].op;
447b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	comp->steps[j].op = op;
448b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	j--;
449b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	i++;
450b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
451c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    comp->steps[comp->nbStep].value = NULL;
452c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    comp->steps[comp->nbStep].value2 = NULL;
453b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    comp->steps[comp->nbStep++].op = XML_OP_END;
454c7c9fb19a43347ef6134016e842405bd4d957902Daniel Veillard    return(0);
455b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
456b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
457b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/************************************************************************
458f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *									*
459f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *		The interpreter for the precompiled patterns		*
460f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *									*
461b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard ************************************************************************/
462b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
463d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardstatic int
464d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel VeillardxmlPatPushState(xmlStepStates *states, int step, xmlNodePtr node) {
465d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    if ((states->states == NULL) || (states->maxstates <= 0)) {
466d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard        states->maxstates = 4;
467d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	states->nbstates = 0;
468d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	states->states = xmlMalloc(4 * sizeof(xmlStepState));
469d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    }
470d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    else if (states->maxstates <= states->nbstates) {
471d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard        xmlStepState *tmp;
472d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard
473d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	tmp = (xmlStepStatePtr) xmlRealloc(states->states,
474d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			       2 * states->maxstates * sizeof(xmlStepState));
475d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	if (tmp == NULL)
476d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	    return(-1);
477d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	states->states = tmp;
478d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	states->maxstates *= 2;
479d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    }
480d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    states->states[states->nbstates].step = step;
481d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    states->states[states->nbstates++].node = node;
482d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard#if 0
483d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    fprintf(stderr, "Push: %d, %s\n", step, node->name);
484d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard#endif
485d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    return(0);
486d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard}
487d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard
488b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
489b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlPatMatch:
490b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @comp: the precompiled pattern
491b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @node: a node
492b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
493fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * Test whether the node matches the pattern
494b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
495b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
496b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
497b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic int
498b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlPatMatch(xmlPatternPtr comp, xmlNodePtr node) {
499b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int i;
500b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlStepOpPtr step;
501d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    xmlStepStates states = {0, 0, NULL}; /* // may require backtrack */
502b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
503b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if ((comp == NULL) || (node == NULL)) return(-1);
504d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    i = 0;
505d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardrestart:
506d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    for (;i < comp->nbStep;i++) {
507b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	step = &comp->steps[i];
508b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	switch (step->op) {
509b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_END:
510d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		goto found;
511b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_ROOT:
5122fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		if (node->type == XML_NAMESPACE_DECL)
513d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
5142fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		node = node->parent;
515b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if ((node->type == XML_DOCUMENT_NODE) ||
516b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#ifdef LIBXML_DOCB_ENABLED
517b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type == XML_DOCB_DOCUMENT_NODE) ||
518b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#endif
519b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type == XML_HTML_DOCUMENT_NODE))
520b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    continue;
521d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		goto rollback;
522b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_ELEM:
523b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node->type != XML_ELEMENT_NODE)
524d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
525b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (step->value == NULL)
526b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    continue;
527b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (step->value[0] != node->name[0])
528d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
529b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (!xmlStrEqual(step->value, node->name))
530d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
531b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
532b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		/* Namespace test */
533b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node->ns == NULL) {
534b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value2 != NULL)
535d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
536b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		} else if (node->ns->href != NULL) {
537b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value2 == NULL)
538d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
539b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (!xmlStrEqual(step->value2, node->ns->href))
540d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
541b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
542b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		continue;
543b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_CHILD: {
544b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		xmlNodePtr lst;
545b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
546b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if ((node->type != XML_ELEMENT_NODE) &&
547b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type != XML_DOCUMENT_NODE) &&
548b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#ifdef LIBXML_DOCB_ENABLED
549b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type != XML_DOCB_DOCUMENT_NODE) &&
550b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#endif
551b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type != XML_HTML_DOCUMENT_NODE))
552d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
553b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
554b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		lst = node->children;
555b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
556b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (step->value != NULL) {
557b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    while (lst != NULL) {
558b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			if ((lst->type == XML_ELEMENT_NODE) &&
559b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			    (step->value[0] == lst->name[0]) &&
560b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			    (xmlStrEqual(step->value, lst->name)))
561b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			    break;
562b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			lst = lst->next;
563b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    }
564b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (lst != NULL)
565b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			continue;
566b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
567d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		goto rollback;
568b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    }
569b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_ATTR:
570b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node->type != XML_ATTRIBUTE_NODE)
571d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
572b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (step->value != NULL) {
573b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value[0] != node->name[0])
574d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
575b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (!xmlStrEqual(step->value, node->name))
576d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
577b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
578b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		/* Namespace test */
579b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node->ns == NULL) {
580b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value2 != NULL)
581d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
582b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		} else if (step->value2 != NULL) {
583b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (!xmlStrEqual(step->value2, node->ns->href))
584d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
585b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
586b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		continue;
587b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_PARENT:
588b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if ((node->type == XML_DOCUMENT_NODE) ||
589b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type == XML_HTML_DOCUMENT_NODE) ||
590b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#ifdef LIBXML_DOCB_ENABLED
591b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type == XML_DOCB_DOCUMENT_NODE) ||
592b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#endif
593b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type == XML_NAMESPACE_DECL))
594d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
595b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		node = node->parent;
596b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node == NULL)
597d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
598b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (step->value == NULL)
599b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    continue;
600b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (step->value[0] != node->name[0])
601d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
602b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (!xmlStrEqual(step->value, node->name))
603d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
604b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		/* Namespace test */
605b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node->ns == NULL) {
606b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value2 != NULL)
607d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
608b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		} else if (node->ns->href != NULL) {
609b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value2 == NULL)
610d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
611b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (!xmlStrEqual(step->value2, node->ns->href))
612d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
613b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
614b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		continue;
615b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_ANCESTOR:
616b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		/* TODO: implement coalescing of ANCESTOR/NODE ops */
617b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (step->value == NULL) {
618b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    i++;
619b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    step = &comp->steps[i];
620b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->op == XML_OP_ROOT)
621d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto found;
622b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->op != XML_OP_ELEM)
623d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
624b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value == NULL)
625b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			return(-1);
626b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
627b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node == NULL)
628d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
629b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if ((node->type == XML_DOCUMENT_NODE) ||
630b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type == XML_HTML_DOCUMENT_NODE) ||
631b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#ifdef LIBXML_DOCB_ENABLED
632b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type == XML_DOCB_DOCUMENT_NODE) ||
633b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#endif
634b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    (node->type == XML_NAMESPACE_DECL))
635d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
636b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		node = node->parent;
637b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		while (node != NULL) {
638b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if ((node->type == XML_ELEMENT_NODE) &&
639b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			(step->value[0] == node->name[0]) &&
640b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			(xmlStrEqual(step->value, node->name))) {
641b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			/* Namespace test */
642b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			if (node->ns == NULL) {
643b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			    if (step->value2 == NULL)
644b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard				break;
645b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			} else if (node->ns->href != NULL) {
646b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			    if ((step->value2 != NULL) &&
647b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			        (xmlStrEqual(step->value2, node->ns->href)))
648b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard				break;
649b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			}
650b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    }
651b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    node = node->parent;
652b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
653b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node == NULL)
654d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
655d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		/*
656d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		 * prepare a potential rollback from here
657d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		 * for ancestors of that node.
658d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		 */
659d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		if (step->op == XML_OP_ANCESTOR)
660d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    xmlPatPushState(&states, i, node);
661d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		else
662d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    xmlPatPushState(&states, i - 1, node);
663b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		continue;
664b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_NS:
665b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node->type != XML_ELEMENT_NODE)
666d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
667b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node->ns == NULL) {
668b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value != NULL)
669d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
670b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		} else if (node->ns->href != NULL) {
671b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (step->value == NULL)
672d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
673b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    if (!xmlStrEqual(step->value, node->ns->href))
674d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard			goto rollback;
675b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
676b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		break;
677b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            case XML_OP_ALL:
678b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (node->type != XML_ELEMENT_NODE)
679d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		    goto rollback;
680b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		break;
681b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	}
682b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
683d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardfound:
684d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    if (states.states != NULL) {
685d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard        /* Free the rollback states */
686d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	xmlFree(states.states);
687d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    }
688b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(1);
689d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillardrollback:
690d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    /* got an error try to rollback */
691d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    if (states.states == NULL)
692d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	return(0);
693d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    if (states.nbstates <= 0) {
694d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	xmlFree(states.states);
695d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard	return(0);
696d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    }
697d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    states.nbstates--;
698d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    i = states.states[states.nbstates].step;
699d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    node = states.states[states.nbstates].node;
700d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard#if 0
701d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    fprintf(stderr, "Pop: %d, %s\n", i, node->name);
702d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard#endif
703d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard    goto restart;
704b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
705b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
706b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/************************************************************************
707b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *									*
708b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *			Dedicated parser for templates			*
709b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *									*
710b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard ************************************************************************/
711b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
712f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard#define TODO								\
713b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlGenericError(xmlGenericErrorContext,				\
714b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    "Unimplemented block at %s:%d\n",				\
715b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard            __FILE__, __LINE__);
716b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define CUR (*ctxt->cur)
717b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define SKIP(val) ctxt->cur += (val)
718b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define NXT(val) ctxt->cur[(val)]
719940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik#define PEEKPREV(val) ctxt->cur[-(val)]
720b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define CUR_PTR ctxt->cur
721b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
722f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard#define SKIP_BLANKS							\
723427174fbf2544b44071c1039720e6634fb154f84Daniel Veillard    while (IS_BLANK_CH(CUR)) NEXT
724b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
725b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define CURRENT (*ctxt->cur)
726b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)
727b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
728b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
729f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard#define PUSH(op, val, val2)						\
730b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error;
731b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
732b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define XSLT_ERROR(X)							\
733ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack    { xsltError(ctxt, __FILE__, __LINE__, X);				\
734b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard      ctxt->error = (X); return; }
735b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
736b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#define XSLT_ERROR0(X)							\
737ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack    { xsltError(ctxt, __FILE__, __LINE__, X);				\
738b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard      ctxt->error = (X); return(0); }
739b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
740b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#if 0
741b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
742b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlPatScanLiteral:
743b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @ctxt:  the XPath Parser context
744b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
745b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Parse an XPath Litteral:
746b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
747b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * [29] Literal ::= '"' [^"]* '"'
748b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *                | "'" [^']* "'"
749b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
750b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns the Literal parsed or NULL
751b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
752b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
753b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic xmlChar *
754b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlPatScanLiteral(xmlPatParserContextPtr ctxt) {
755b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    const xmlChar *q, *cur;
756b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlChar *ret = NULL;
757b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int val, len;
758b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
759b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    SKIP_BLANKS;
760b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (CUR == '"') {
761b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard        NEXT;
762b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	cur = q = CUR_PTR;
763b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	val = xmlStringCurrentChar(NULL, cur, &len);
764b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	while ((IS_CHAR(val)) && (val != '"')) {
765b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    cur += len;
766b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    val = xmlStringCurrentChar(NULL, cur, &len);
767b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	}
768b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	if (!IS_CHAR(val)) {
769b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    ctxt->error = 1;
770b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    return(NULL);
771b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	} else {
7726ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    if (ctxt->dict)
7736ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
7746ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    else
775f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		ret = xmlStrndup(q, cur - q);
776b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard        }
777b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	cur += len;
778b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	CUR_PTR = cur;
779b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    } else if (CUR == '\'') {
780b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard        NEXT;
781b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	cur = q = CUR_PTR;
782b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	val = xmlStringCurrentChar(NULL, cur, &len);
783b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	while ((IS_CHAR(val)) && (val != '\'')) {
784b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    cur += len;
785b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    val = xmlStringCurrentChar(NULL, cur, &len);
786b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	}
787b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	if (!IS_CHAR(val)) {
788b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    ctxt->error = 1;
789b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    return(NULL);
790b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	} else {
7916ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    if (ctxt->dict)
7926ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
7936ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    else
794f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		ret = xmlStrndup(q, cur - q);
795b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard        }
796b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	cur += len;
797b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	CUR_PTR = cur;
798b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    } else {
799b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	/* XP_ERROR(XPATH_START_LITERAL_ERROR); */
800b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	ctxt->error = 1;
801b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	return(NULL);
802b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
803b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(ret);
804b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
805b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#endif
806b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
807b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
808b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlPatScanName:
809b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @ctxt:  the XPath Parser context
810b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
811f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' |
812b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *                  CombiningChar | Extender
813b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
814b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * [5] Name ::= (Letter | '_' | ':') (NameChar)*
815b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
816b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * [6] Names ::= Name (S Name)*
817b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
818b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns the Name parsed or NULL
819b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
820b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
821b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic xmlChar *
822b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlPatScanName(xmlPatParserContextPtr ctxt) {
823b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    const xmlChar *q, *cur;
824b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlChar *ret = NULL;
825b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int val, len;
826b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
827b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    SKIP_BLANKS;
828b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
829b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    cur = q = CUR_PTR;
830b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    val = xmlStringCurrentChar(NULL, cur, &len);
831b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (!IS_LETTER(val) && (val != '_') && (val != ':'))
832b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	return(NULL);
833b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
834b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
835b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard           (val == '.') || (val == '-') ||
836f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	   (val == '_') ||
837b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	   (IS_COMBINING(val)) ||
838b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	   (IS_EXTENDER(val))) {
839b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	cur += len;
840b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	val = xmlStringCurrentChar(NULL, cur, &len);
841b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
8426ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    if (ctxt->dict)
8436ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
8446ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    else
845f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	ret = xmlStrndup(q, cur - q);
846b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    CUR_PTR = cur;
847b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(ret);
848b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
849b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
850b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
851b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlPatScanNCName:
852b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @ctxt:  the XPath Parser context
853b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
854b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Parses a non qualified name
855b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
856b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns the Name parsed or NULL
857b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
858b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
859b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic xmlChar *
860b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlPatScanNCName(xmlPatParserContextPtr ctxt) {
861b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    const xmlChar *q, *cur;
862b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlChar *ret = NULL;
863b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    int val, len;
864b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
865b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    SKIP_BLANKS;
866b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
867b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    cur = q = CUR_PTR;
868b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    val = xmlStringCurrentChar(NULL, cur, &len);
869b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (!IS_LETTER(val) && (val != '_'))
870b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	return(NULL);
871b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
872b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
873b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard           (val == '.') || (val == '-') ||
874b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	   (val == '_') ||
875b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	   (IS_COMBINING(val)) ||
876b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	   (IS_EXTENDER(val))) {
877b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	cur += len;
878b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	val = xmlStringCurrentChar(NULL, cur, &len);
879b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
8806ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    if (ctxt->dict)
8816ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
8826ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    else
8836ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	ret = xmlStrndup(q, cur - q);
884b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    CUR_PTR = cur;
885b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(ret);
886b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
887b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
888b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#if 0
889b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
890b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlPatScanQName:
891b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @ctxt:  the XPath Parser context
892b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @prefix:  the place to store the prefix
893b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
894b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Parse a qualified name
895b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
896b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns the Name parsed or NULL
897b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
898b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
899b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic xmlChar *
900b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlPatScanQName(xmlPatParserContextPtr ctxt, xmlChar **prefix) {
901b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlChar *ret = NULL;
902b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
903b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    *prefix = NULL;
904b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    ret = xmlPatScanNCName(ctxt);
905b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (CUR == ':') {
906b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard        *prefix = ret;
907b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
908b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	ret = xmlPatScanNCName(ctxt);
909b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
910b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(ret);
911b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
912b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#endif
913b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
914b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
9152a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * xmlCompileAttributeTest:
9162a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * @ctxt:  the compilation context
9172a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik *
9182a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * Compile an attribute test.
9192a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik */
9202a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcikstatic void
9212a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. BuchcikxmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
9222a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    xmlChar *token = NULL;
9232a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    xmlChar *name = NULL;
9242a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    xmlChar *URL = NULL;
925f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
926940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    SKIP_BLANKS;
9272a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    name = xmlPatScanNCName(ctxt);
9282a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    if (name == NULL) {
9292a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	if (CUR == '*') {
9302a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    PUSH(XML_OP_ATTR, NULL, NULL);
9319ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    NEXT;
9322a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	} else {
9332a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    ERROR(NULL, NULL, NULL,
9342a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		"xmlCompileAttributeTest : Name expected\n");
9352a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    ctxt->error = 1;
9362a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	}
9372a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	return;
9382a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    }
9392a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    if (CUR == ':') {
9402a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	int i;
9412a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	xmlChar *prefix = name;
942f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
9432a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	NEXT;
944940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik
945f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	if (IS_BLANK_CH(CUR)) {
946940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
9476ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    XML_PAT_FREE_STRING(ctxt, prefix);
948940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    ctxt->error = 1;
949940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    goto error;
950940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	}
9512a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	/*
9522a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	* This is a namespace match
9532a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	*/
9542a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	token = xmlPatScanName(ctxt);
955627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	if ((prefix[0] == 'x') &&
956627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	    (prefix[1] == 'm') &&
957627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	    (prefix[2] == 'l') &&
9586ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    (prefix[3] == 0))
9596ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	{
960f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE);
961627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	} else {
962627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	    for (i = 0;i < ctxt->nb_namespaces;i++) {
963627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
964f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
965627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    break;
966627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		}
967627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	    }
968627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	    if (i >= ctxt->nb_namespaces) {
969627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		ERROR5(NULL, NULL, NULL,
970627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    "xmlCompileAttributeTest : no namespace bound to prefix %s\n",
971627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    prefix);
9721f131f1133e1441ea159204d606fb4bbc394e14bNick Wellnhofer	        XML_PAT_FREE_STRING(ctxt, prefix);
973f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		ctxt->error = 1;
974627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		goto error;
9752a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    }
9762a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	}
9776ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	XML_PAT_FREE_STRING(ctxt, prefix);
9782a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	if (token == NULL) {
9792a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    if (CUR == '*') {
9802a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		NEXT;
9812a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		PUSH(XML_OP_ATTR, NULL, URL);
9822a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    } else {
9832a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		ERROR(NULL, NULL, NULL,
9842a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    "xmlCompileAttributeTest : Name expected\n");
9852a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		ctxt->error = 1;
9862a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		goto error;
987f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    }
9882a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	} else {
9892a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    PUSH(XML_OP_ATTR, token, URL);
9902a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	}
9912a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    } else {
9922a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	PUSH(XML_OP_ATTR, name, NULL);
9932a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    }
9942a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    return;
9952a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcikerror:
9962a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    if (URL != NULL)
997f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	XML_PAT_FREE_STRING(ctxt, URL)
9982a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    if (token != NULL)
9996ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	XML_PAT_FREE_STRING(ctxt, token);
10002a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik}
10012a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik
10022a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik/**
1003b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlCompileStepPattern:
1004b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @ctxt:  the compilation context
1005b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
1006b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Compile the Step Pattern and generates a precompiled
1007b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * form suitable for fast matching.
1008b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
1009b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * [3]    Step    ::=    '.' | NameTest
1010f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard * [4]    NameTest    ::=    QName | '*' | NCName ':' '*'
1011b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
1012b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
1013b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic void
1014b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
1015b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlChar *token = NULL;
1016b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlChar *name = NULL;
1017b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlChar *URL = NULL;
1018940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    int hasBlanks = 0;
1019b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
1020b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    SKIP_BLANKS;
1021b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (CUR == '.') {
1022940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	/*
1023940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	* Context node.
1024940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	*/
1025b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
1026b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	PUSH(XML_OP_ELEM, NULL, NULL);
1027b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	return;
1028b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
1029940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    if (CUR == '@') {
1030940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	/*
1031940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	* Attribute test.
1032940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	*/
1033940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
1034940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    ERROR5(NULL, NULL, NULL,
1035940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		"Unexpected attribute axis in '%s'.\n", ctxt->base);
1036940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    ctxt->error = 1;
1037940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    return;
1038940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	}
1039940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	NEXT;
1040940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	xmlCompileAttributeTest(ctxt);
1041f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	if (ctxt->error != 0)
1042940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    goto error;
1043940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	return;
1044940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    }
1045b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    name = xmlPatScanNCName(ctxt);
1046b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (name == NULL) {
1047b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	if (CUR == '*') {
1048b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    NEXT;
1049b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    PUSH(XML_OP_ALL, NULL, NULL);
1050b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    return;
1051b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	} else {
1052b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    ERROR(NULL, NULL, NULL,
1053b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    "xmlCompileStepPattern : Name expected\n");
1054b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    ctxt->error = 1;
1055b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    return;
1056b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	}
1057b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
1058940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    if (IS_BLANK_CH(CUR)) {
1059940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	hasBlanks = 1;
1060940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	SKIP_BLANKS;
1061940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    }
1062b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (CUR == ':') {
1063b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
1064b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	if (CUR != ':') {
1065b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    xmlChar *prefix = name;
1066f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    int i;
1067b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
1068940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    if (hasBlanks || IS_BLANK_CH(CUR)) {
1069940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
1070940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		ctxt->error = 1;
1071940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		goto error;
1072940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    }
1073b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    /*
1074b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	     * This is a namespace match
1075b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	     */
1076b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    token = xmlPatScanName(ctxt);
1077627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	    if ((prefix[0] == 'x') &&
1078627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		(prefix[1] == 'm') &&
1079627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		(prefix[2] == 'l') &&
10806ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		(prefix[3] == 0))
10816ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    {
10826ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
1083627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik	    } else {
1084627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		for (i = 0;i < ctxt->nb_namespaces;i++) {
1085627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
10866ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik			XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
1087627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			break;
1088627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    }
1089627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		}
1090627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		if (i >= ctxt->nb_namespaces) {
1091627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    ERROR5(NULL, NULL, NULL,
1092627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			"xmlCompileStepPattern : no namespace bound to prefix %s\n",
1093627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			prefix);
1094627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    ctxt->error = 1;
1095627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    goto error;
1096d4301aba26ab6d415be85a80b084bd91b3cfcc05Daniel Veillard		}
1097b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    }
10986ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    XML_PAT_FREE_STRING(ctxt, prefix);
10993108ba92b7a7a03bb4f913a59e2bbece6322275aRob Richards	    name = NULL;
1100b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    if (token == NULL) {
1101b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		if (CUR == '*') {
1102b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    NEXT;
1103b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    PUSH(XML_OP_NS, URL, NULL);
1104b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		} else {
1105b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    ERROR(NULL, NULL, NULL,
1106b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			    "xmlCompileStepPattern : Name expected\n");
1107b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    ctxt->error = 1;
1108b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    goto error;
1109b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
1110b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    } else {
1111b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		PUSH(XML_OP_ELEM, token, URL);
1112b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    }
1113b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	} else {
1114b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    NEXT;
1115f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    if (xmlStrEqual(name, (const xmlChar *) "child")) {
11166ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		XML_PAT_FREE_STRING(ctxt, name);
11172a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		name = xmlPatScanName(ctxt);
11182a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		if (name == NULL) {
11192a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    if (CUR == '*') {
11202a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			NEXT;
11212a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			PUSH(XML_OP_ALL, NULL, NULL);
11222a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			return;
11232a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    } else {
11242a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			ERROR(NULL, NULL, NULL,
1125b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard			    "xmlCompileStepPattern : QName expected\n");
11262a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			ctxt->error = 1;
11272a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			goto error;
1128b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    }
1129b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
11302a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		if (CUR == ':') {
11312a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    xmlChar *prefix = name;
11322a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    int i;
1133f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
11342a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    NEXT;
1135940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    if (IS_BLANK_CH(CUR)) {
1136940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik			ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
1137940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik			ctxt->error = 1;
1138940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik			goto error;
1139940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    }
11402a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    /*
11412a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    * This is a namespace match
11422a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    */
11432a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    token = xmlPatScanName(ctxt);
1144627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    if ((prefix[0] == 'x') &&
1145627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			(prefix[1] == 'm') &&
1146627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			(prefix[2] == 'l') &&
11476ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik			(prefix[3] == 0))
11486ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    {
1149f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard			XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
1150627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik		    } else {
1151627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			for (i = 0;i < ctxt->nb_namespaces;i++) {
1152627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			    if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
1153f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard				XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
1154627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik				break;
1155627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			    }
1156627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			}
1157627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			if (i >= ctxt->nb_namespaces) {
1158627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			    ERROR5(NULL, NULL, NULL,
1159627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik				"xmlCompileStepPattern : no namespace bound "
1160627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik				"to prefix %s\n", prefix);
1161627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			    ctxt->error = 1;
1162627e9a934b692768f1d2715a9429315e0b04b94eKasimier T. Buchcik			    goto error;
11632a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			}
11642a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    }
11656ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    XML_PAT_FREE_STRING(ctxt, prefix);
11663108ba92b7a7a03bb4f913a59e2bbece6322275aRob Richards		    name = NULL;
11672a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    if (token == NULL) {
11682a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			if (CUR == '*') {
11692a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			    NEXT;
11702a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			    PUSH(XML_OP_NS, URL, NULL);
11712a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			} else {
11722a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			    ERROR(NULL, NULL, NULL,
11732a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik				"xmlCompileStepPattern : Name expected\n");
11742a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			    ctxt->error = 1;
11752a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			    goto error;
11762a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			}
11772a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    } else {
11782a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik			PUSH(XML_OP_CHILD, token, URL);
11792a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    }
11802a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		} else
11812a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    PUSH(XML_OP_CHILD, name, NULL);
11822a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		return;
11832a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    } else if (xmlStrEqual(name, (const xmlChar *) "attribute")) {
11846ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		XML_PAT_FREE_STRING(ctxt, name)
11852a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		name = NULL;
1186940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
1187940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    ERROR5(NULL, NULL, NULL,
1188940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik			"Unexpected attribute axis in '%s'.\n", ctxt->base);
1189940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    ctxt->error = 1;
1190940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    goto error;
1191940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		}
11922a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		xmlCompileAttributeTest(ctxt);
11932a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		if (ctxt->error != 0)
1194b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		    goto error;
11952a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		return;
1196b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    } else {
1197940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		ERROR5(NULL, NULL, NULL,
1198940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    "The 'element' or 'attribute' axis is expected.\n", NULL);
1199b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		ctxt->error = 1;
1200b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		goto error;
1201f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    }
1202b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	}
1203b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    } else if (CUR == '*') {
1204fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard        if (name != NULL) {
1205fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    ctxt->error = 1;
1206fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    goto error;
1207fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	}
1208b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
1209b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	PUSH(XML_OP_ALL, token, NULL);
1210b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    } else {
1211b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	PUSH(XML_OP_ELEM, name, NULL);
1212b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
1213b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return;
1214b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillarderror:
12152a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik    if (URL != NULL)
1216f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	XML_PAT_FREE_STRING(ctxt, URL)
1217b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (token != NULL)
12186ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	XML_PAT_FREE_STRING(ctxt, token)
1219b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (name != NULL)
12206ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	XML_PAT_FREE_STRING(ctxt, name)
1221b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
1222b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
1223b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
1224b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlCompilePathPattern:
1225b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @ctxt:  the compilation context
1226b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
1227b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Compile the Path Pattern and generates a precompiled
1228b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * form suitable for fast matching.
1229b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
1230f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard * [5]    Path    ::=    ('.//')? ( Step '/' )* ( Step | '@' NameTest )
1231b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
1232b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardstatic void
1233b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlCompilePathPattern(xmlPatParserContextPtr ctxt) {
1234b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    SKIP_BLANKS;
1235537f1173c39eb21f9c5e8ad3cbc9bed2a08f25e4William M. Brack    if (CUR == '/') {
123656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        ctxt->comp->flags |= PAT_FROM_ROOT;
1237ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack    } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) {
123856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        ctxt->comp->flags |= PAT_FROM_CUR;
123956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1240f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
1241b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if ((CUR == '/') && (NXT(1) == '/')) {
124256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	PUSH(XML_OP_ANCESTOR, NULL, NULL);
1243b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
1244b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
1245b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) {
124656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	PUSH(XML_OP_ANCESTOR, NULL, NULL);
1247b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
1248b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
1249b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	NEXT;
125097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	/* Check for incompleteness. */
125197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	SKIP_BLANKS;
125297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	if (CUR == 0) {
125397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    ERROR5(NULL, NULL, NULL,
125497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	       "Incomplete expression '%s'.\n", ctxt->base);
125597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    ctxt->error = 1;
125697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    goto error;
125797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	}
1258b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
1259b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (CUR == '@') {
12602a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	NEXT;
12612a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	xmlCompileAttributeTest(ctxt);
12622a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	SKIP_BLANKS;
126397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	/* TODO: check for incompleteness */
1264fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack	if (CUR != 0) {
12652a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    xmlCompileStepPattern(ctxt);
126697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    if (ctxt->error != 0)
126797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		goto error;
12682a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	}
1269b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    } else {
12702fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        if (CUR == '/') {
12712fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    PUSH(XML_OP_ROOT, NULL, NULL);
12722fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    NEXT;
127397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    /* Check for incompleteness. */
127497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    SKIP_BLANKS;
127597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    if (CUR == 0) {
127697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		ERROR5(NULL, NULL, NULL,
127797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    "Incomplete expression '%s'.\n", ctxt->base);
127897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		ctxt->error = 1;
127997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		goto error;
128097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    }
12812fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
1282b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	xmlCompileStepPattern(ctxt);
128397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	if (ctxt->error != 0)
128497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    goto error;
1285b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	SKIP_BLANKS;
1286b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	while (CUR == '/') {
1287fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack	    if (NXT(1) == '/') {
1288b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	        PUSH(XML_OP_ANCESTOR, NULL, NULL);
1289b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		NEXT;
1290b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		NEXT;
1291b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		SKIP_BLANKS;
1292b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		xmlCompileStepPattern(ctxt);
129397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if (ctxt->error != 0)
129497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    goto error;
1295b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    } else {
1296b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	        PUSH(XML_OP_PARENT, NULL, NULL);
1297b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		NEXT;
1298b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		SKIP_BLANKS;
129997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if (CUR == 0) {
130097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    ERROR5(NULL, NULL, NULL,
130197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    "Incomplete expression '%s'.\n", ctxt->base);
130297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    ctxt->error = 1;
1303f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    goto error;
1304b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard		}
130597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		xmlCompileStepPattern(ctxt);
130697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if (ctxt->error != 0)
130797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    goto error;
1308b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	    }
1309b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard	}
1310b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    }
131156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (CUR != 0) {
131256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	ERROR5(NULL, NULL, NULL,
131356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	       "Failed to compile pattern %s\n", ctxt->base);
131456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	ctxt->error = 1;
131556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
1316b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillarderror:
1317b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return;
1318b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
13192fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
1320940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik/**
1321940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik * xmlCompileIDCXPathPath:
1322940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik * @ctxt:  the compilation context
1323940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik *
1324940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik * Compile the Path Pattern and generates a precompiled
1325940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik * form suitable for fast matching.
1326940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik *
1327f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard * [5]    Path    ::=    ('.//')? ( Step '/' )* ( Step | '@' NameTest )
1328940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik */
1329940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcikstatic void
1330940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. BuchcikxmlCompileIDCXPathPath(xmlPatParserContextPtr ctxt) {
1331940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    SKIP_BLANKS;
1332940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    if (CUR == '/') {
1333940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	ERROR5(NULL, NULL, NULL,
1334940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    "Unexpected selection of the document root in '%s'.\n",
1335940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    ctxt->base);
1336940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	goto error;
1337940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    }
1338940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    ctxt->comp->flags |= PAT_FROM_CUR;
1339940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik
1340940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    if (CUR == '.') {
1341940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	/* "." - "self::node()" */
1342940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	NEXT;
1343940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	SKIP_BLANKS;
1344940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (CUR == 0) {
1345940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    /*
1346940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    * Selection of the context node.
1347940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    */
1348940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    PUSH(XML_OP_ELEM, NULL, NULL);
1349940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    return;
1350940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	}
1351940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (CUR != '/') {
1352940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    /* TODO: A more meaningful error message. */
1353940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    ERROR5(NULL, NULL, NULL,
1354940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    "Unexpected token after '.' in '%s'.\n", ctxt->base);
1355940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    goto error;
1356940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	}
1357940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	/* "./" - "self::node()/" */
1358940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	NEXT;
1359940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	SKIP_BLANKS;
1360940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (CUR == '/') {
1361940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    if (IS_BLANK_CH(PEEKPREV(1))) {
1362940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		/*
1363940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		* Disallow "./ /"
1364940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		*/
1365940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		ERROR5(NULL, NULL, NULL,
1366940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    "Unexpected '/' token in '%s'.\n", ctxt->base);
1367940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		goto error;
1368940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    }
1369940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    /* ".//" - "self:node()/descendant-or-self::node()/" */
1370940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    PUSH(XML_OP_ANCESTOR, NULL, NULL);
1371940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    NEXT;
1372940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    SKIP_BLANKS;
1373940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	}
1374940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (CUR == 0)
1375940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    goto error_unfinished;
1376940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    }
1377940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    /*
1378940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    * Process steps.
1379940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    */
1380940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    do {
1381940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	xmlCompileStepPattern(ctxt);
1382f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	if (ctxt->error != 0)
1383940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    goto error;
1384940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	SKIP_BLANKS;
1385940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (CUR != '/')
1386940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    break;
1387940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	PUSH(XML_OP_PARENT, NULL, NULL);
1388940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	NEXT;
1389940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	SKIP_BLANKS;
1390940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (CUR == '/') {
1391940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    /*
1392940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    * Disallow subsequent '//'.
1393940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    */
1394940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    ERROR5(NULL, NULL, NULL,
1395940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		"Unexpected subsequent '//' in '%s'.\n",
1396940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		ctxt->base);
1397940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    goto error;
1398940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	}
1399940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (CUR == 0)
1400940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    goto error_unfinished;
1401f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
1402940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    } while (CUR != 0);
1403940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik
1404940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    if (CUR != 0) {
1405940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	ERROR5(NULL, NULL, NULL,
1406940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    "Failed to compile expression '%s'.\n", ctxt->base);
1407940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	ctxt->error = 1;
1408940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    }
1409940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    return;
1410940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcikerror:
1411940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    ctxt->error = 1;
1412940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    return;
1413940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik
1414940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcikerror_unfinished:
1415940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    ctxt->error = 1;
1416940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    ERROR5(NULL, NULL, NULL,
1417f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	"Unfinished expression '%s'.\n", ctxt->base);
1418940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik    return;
1419940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik}
1420940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik
14212fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/************************************************************************
14222fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *									*
14232fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *			The streaming code				*
14242fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *									*
14252fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard ************************************************************************/
14262fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
14272fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard#ifdef DEBUG_STREAMING
14282fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic void
14292fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlDebugStreamComp(xmlStreamCompPtr stream) {
14302fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    int i;
14312fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
14322fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (stream == NULL) {
14332fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        printf("Stream: NULL\n");
14342fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	return;
14352fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
14362fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    printf("Stream: %d steps\n", stream->nbStep);
14372fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    for (i = 0;i < stream->nbStep;i++) {
14382fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	if (stream->steps[i].ns != NULL) {
14392fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    printf("{%s}", stream->steps[i].ns);
14402fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
14412fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        if (stream->steps[i].name == NULL) {
14422fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    printf("* ");
14432fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	} else {
14442fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    printf("%s ", stream->steps[i].name);
14452fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
14462fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	if (stream->steps[i].flags & XML_STREAM_STEP_ROOT)
14472fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    printf("root ");
14482fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	if (stream->steps[i].flags & XML_STREAM_STEP_DESC)
14492fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    printf("// ");
14502fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	if (stream->steps[i].flags & XML_STREAM_STEP_FINAL)
14512fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    printf("final ");
14522fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	printf("\n");
14532fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
14542fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
14552fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic void
14562fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlDebugStreamCtxt(xmlStreamCtxtPtr ctxt, int match) {
14572fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    int i;
14582fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
14592fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (ctxt == NULL) {
14602fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        printf("Stream: NULL\n");
14612fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	return;
14622fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
14632fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    printf("Stream: level %d, %d states: ", ctxt->level, ctxt->nbState);
14642fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (match)
14652fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        printf("matches\n");
14662fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    else
14672fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        printf("\n");
14682fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    for (i = 0;i < ctxt->nbState;i++) {
14692fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        if (ctxt->states[2 * i] < 0)
14702fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    printf(" %d: free\n", i);
14712fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	else {
14722fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    printf(" %d: step %d, level %d", i, ctxt->states[2 * i],
14732fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	           ctxt->states[(2 * i) + 1]);
14742fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard            if (ctxt->comp->steps[ctxt->states[2 * i]].flags &
14752fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	        XML_STREAM_STEP_DESC)
14762fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	        printf(" //\n");
14772fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    else
14782fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	        printf("\n");
14792fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
14802fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
14812fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
14822fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard#endif
14832fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
14842fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlNewStreamComp:
14852fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @size: the number of expected steps
14862fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
14872fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * build a new compiled pattern for streaming
14882fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
14892fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Returns the new structure or NULL in case of error.
14902fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
14912fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic xmlStreamCompPtr
14922fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlNewStreamComp(int size) {
14932fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlStreamCompPtr cur;
14942fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
14952fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (size < 4)
14962fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        size  = 4;
14972fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
14982fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur = (xmlStreamCompPtr) xmlMalloc(sizeof(xmlStreamComp));
14992fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (cur == NULL) {
15002fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	ERROR(NULL, NULL, NULL,
15012fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		"xmlNewStreamComp: malloc failed\n");
15022fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	return(NULL);
15032fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
15042fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    memset(cur, 0, sizeof(xmlStreamComp));
15052fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->steps = (xmlStreamStepPtr) xmlMalloc(size * sizeof(xmlStreamStep));
15062fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (cur->steps == NULL) {
15072fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	xmlFree(cur);
15082fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	ERROR(NULL, NULL, NULL,
15092fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	      "xmlNewStreamComp: malloc failed\n");
15102fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	return(NULL);
15112fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
15122fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->nbStep = 0;
15132fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->maxStep = size;
15142fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    return(cur);
15152fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
15162fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
15172fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
15182fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlFreeStreamComp:
15192fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @comp: the compiled pattern for streaming
15202fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
15212fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Free the compiled pattern for streaming
15222fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
15232fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic void
15242fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlFreeStreamComp(xmlStreamCompPtr comp) {
15252fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (comp != NULL) {
15262fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        if (comp->steps != NULL)
15272fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    xmlFree(comp->steps);
15282fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	if (comp->dict != NULL)
15292fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    xmlDictFree(comp->dict);
15302fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        xmlFree(comp);
15312fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
15322fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
15332fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
15342fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
15352fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlStreamCompAddStep:
15362fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @comp: the compiled pattern for streaming
15372fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @name: the first string, the name, or NULL for *
15382fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @ns: the second step, the namespace name
15392fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @flags: the flags for that step
15402fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
15412fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Add a new step to the compiled pattern
15422fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
15432fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Returns -1 in case of error or the step index if successful
15442fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
15452fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic int
15462fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlStreamCompAddStep(xmlStreamCompPtr comp, const xmlChar *name,
154797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik                     const xmlChar *ns, int nodeType, int flags) {
15482fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlStreamStepPtr cur;
15492fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
15502fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (comp->nbStep >= comp->maxStep) {
15512fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	cur = (xmlStreamStepPtr) xmlRealloc(comp->steps,
15522fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard				 comp->maxStep * 2 * sizeof(xmlStreamStep));
15532fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	if (cur == NULL) {
15542fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    ERROR(NULL, NULL, NULL,
15552fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		  "xmlNewStreamComp: malloc failed\n");
15562fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    return(-1);
15572fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
15582fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	comp->steps = cur;
15592fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        comp->maxStep *= 2;
15602fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
15612fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur = &comp->steps[comp->nbStep++];
15622fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->flags = flags;
15632fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->name = name;
15642fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->ns = ns;
156597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    cur->nodeType = nodeType;
15662fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    return(comp->nbStep - 1);
15672fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
15682fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
15692fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
15702fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlStreamCompile:
15712fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @comp: the precompiled pattern
1572f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *
15732fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Tries to stream compile a pattern
15742fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
15752fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Returns -1 in case of failure and 0 in case of success.
15762fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
15772fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic int
15782fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlStreamCompile(xmlPatternPtr comp) {
15792fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlStreamCompPtr stream;
1580bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik    int i, s = 0, root = 0, flags = 0, prevs = -1;
158197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    xmlStepOp step;
15822fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
15832fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if ((comp == NULL) || (comp->steps == NULL))
15842fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        return(-1);
158556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    /*
158656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     * special case for .
158756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard     */
158856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if ((comp->nbStep == 1) &&
158956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        (comp->steps[0].op == XML_OP_ELEM) &&
159056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	(comp->steps[0].value == NULL) &&
159156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	(comp->steps[0].value2 == NULL)) {
159256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	stream = xmlNewStreamComp(0);
159356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (stream == NULL)
159456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return(-1);
159597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	/* Note that the stream will have no steps in this case. */
159697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;
159756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	comp->stream = stream;
159856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	return(0);
159956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
160056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
16012fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    stream = xmlNewStreamComp((comp->nbStep / 2) + 1);
16022fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (stream == NULL)
16032fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        return(-1);
16042fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (comp->dict != NULL) {
16052fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        stream->dict = comp->dict;
16062fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	xmlDictReference(stream->dict);
16072fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
1608fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard
1609f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard    i = 0;
161097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    if (comp->flags & PAT_FROM_ROOT)
161197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	stream->flags |= XML_STREAM_FROM_ROOT;
161297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
1613fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    for (;i < comp->nbStep;i++) {
161497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	step = comp->steps[i];
161597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik        switch (step.op) {
16162fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    case XML_OP_END:
16172fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	        break;
16182fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    case XML_OP_ROOT:
16192fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	        if (i != 0)
16202fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		    goto error;
16212fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		root = 1;
16222fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		break;
16232fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    case XML_OP_NS:
162497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		s = xmlStreamCompAddStep(stream, NULL, step.value,
1625f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    XML_ELEMENT_NODE, flags);
16262a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		if (s < 0)
16272a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    goto error;
1628bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		prevs = s;
1629f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		flags = 0;
1630f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		break;
16312a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    case XML_OP_ATTR:
16322a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		flags |= XML_STREAM_STEP_ATTR;
1633bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		prevs = -1;
163497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		s = xmlStreamCompAddStep(stream,
163597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    step.value, step.value2, XML_ATTRIBUTE_NODE, flags);
16362a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		flags = 0;
16372a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		if (s < 0)
16382a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		    goto error;
16392a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		break;
1640f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    case XML_OP_ELEM:
164197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	        if ((step.value == NULL) && (step.value2 == NULL)) {
164297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    /*
164397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    * We have a "." or "self::node()" here.
164497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    * Eliminate redundant self::node() tests like in "/./."
164597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    * or "//./"
164697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    * The only case we won't eliminate is "//.", i.e. if
164797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    * self::node() is the last node test and we had
164897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    * continuation somewhere beforehand.
164997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    */
165097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    if ((comp->nbStep == i + 1) &&
165197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			(flags & XML_STREAM_STEP_DESC)) {
165297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			/*
165397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			* Mark the special case where the expression resolves
165497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			* to any type of node.
165597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			*/
165697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			if (comp->nbStep == i + 1) {
165797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			    stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;
165897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			}
1659f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard			flags |= XML_STREAM_STEP_NODE;
166097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			s = xmlStreamCompAddStep(stream, NULL, NULL,
166197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			    XML_STREAM_ANY_NODE, flags);
166297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			if (s < 0)
166397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			    goto error;
1664bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			flags = 0;
1665bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			/*
1666bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			* If there was a previous step, mark it to be added to
1667bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			* the result node-set; this is needed since only
1668bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			* the last step will be marked as "final" and only
1669bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			* "final" nodes are added to the resulting set.
1670bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			*/
1671bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			if (prevs != -1) {
1672bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			    stream->steps[prevs].flags |= XML_STREAM_STEP_IN_SET;
1673bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			    prevs = -1;
1674bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik			}
1675f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard			break;
167697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
167797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    } else {
167897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			/* Just skip this one. */
167997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			continue;
168097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    }
168197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		}
1682f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		/* An element node. */
168397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	        s = xmlStreamCompAddStep(stream, step.value, step.value2,
1684f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    XML_ELEMENT_NODE, flags);
168597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if (s < 0)
168697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    goto error;
1687bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		prevs = s;
1688f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		flags = 0;
1689f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		break;
1690fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    case XML_OP_CHILD:
169197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		/* An element node child. */
169297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	        s = xmlStreamCompAddStep(stream, step.value, step.value2,
1693f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    XML_ELEMENT_NODE, flags);
16942fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		if (s < 0)
16952fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		    goto error;
1696bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		prevs = s;
1697bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		flags = 0;
1698f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		break;
16992fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    case XML_OP_ALL:
170097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	        s = xmlStreamCompAddStep(stream, NULL, NULL,
1701f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    XML_ELEMENT_NODE, flags);
17022fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		if (s < 0)
17032fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		    goto error;
1704bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		prevs = s;
1705bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		flags = 0;
17062fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		break;
1707f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    case XML_OP_PARENT:
17082fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	        break;
17092fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    case XML_OP_ANCESTOR:
171097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		/* Skip redundant continuations. */
171197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if (flags & XML_STREAM_STEP_DESC)
171297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    break;
17132a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	        flags |= XML_STREAM_STEP_DESC;
17149ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/*
17159ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* Mark the expression as having "//".
17169ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		*/
17179ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		if ((stream->flags & XML_STREAM_DESC) == 0)
17189ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    stream->flags |= XML_STREAM_DESC;
17192fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		break;
17202fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
1721f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard    }
17229ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik    if ((! root) && (comp->flags & XML_PATTERN_NOTPATTERN) == 0) {
17239ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	/*
17249ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	* If this should behave like a real pattern, we will mark
17259ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	* the first step as having "//", to be reentrant on every
17269ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	* tree level.
17279ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	*/
17289ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	if ((stream->flags & XML_STREAM_DESC) == 0)
17299ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    stream->flags |= XML_STREAM_DESC;
17309ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
17319ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	if (stream->nbStep > 0) {
17329ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if ((stream->steps[0].flags & XML_STREAM_STEP_DESC) == 0)
1733f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		stream->steps[0].flags |= XML_STREAM_STEP_DESC;
17349ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	}
17352fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
173697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    if (stream->nbStep <= s)
173797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	goto error;
17382fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    stream->steps[s].flags |= XML_STREAM_STEP_FINAL;
17392fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (root)
17402fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	stream->steps[0].flags |= XML_STREAM_STEP_ROOT;
17412fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard#ifdef DEBUG_STREAMING
17422fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlDebugStreamComp(stream);
17432fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard#endif
17442fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    comp->stream = stream;
17452fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    return(0);
17462fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillarderror:
17472fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlFreeStreamComp(stream);
17482fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    return(0);
17492fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
17502fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
17512fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
17522fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlNewStreamCtxt:
17532fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @size: the number of expected states
17542fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
17552fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * build a new stream context
17562fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
17572fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Returns the new structure or NULL in case of error.
17582fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
17592fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic xmlStreamCtxtPtr
17602fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlNewStreamCtxt(xmlStreamCompPtr stream) {
17612fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlStreamCtxtPtr cur;
17622fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
17632fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur = (xmlStreamCtxtPtr) xmlMalloc(sizeof(xmlStreamCtxt));
17642fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (cur == NULL) {
17652fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	ERROR(NULL, NULL, NULL,
17662fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		"xmlNewStreamCtxt: malloc failed\n");
17672fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	return(NULL);
17682fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
17692fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    memset(cur, 0, sizeof(xmlStreamCtxt));
17702fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->states = (int *) xmlMalloc(4 * 2 * sizeof(int));
17712fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (cur->states == NULL) {
17722fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	xmlFree(cur);
17732fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	ERROR(NULL, NULL, NULL,
17742fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	      "xmlNewStreamCtxt: malloc failed\n");
17752fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	return(NULL);
17762fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
17772fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->nbState = 0;
17782fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->maxState = 4;
17792fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->level = 0;
17802fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    cur->comp = stream;
17819ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik    cur->blockLevel = -1;
17822fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    return(cur);
17832fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
17842fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
17852fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
17862fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlFreeStreamCtxt:
17872fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @stream: the stream context
17882fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
17892fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Free the stream context
17902fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
17912fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardvoid
17922fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlFreeStreamCtxt(xmlStreamCtxtPtr stream) {
17932b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard    xmlStreamCtxtPtr next;
17942b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard
17952b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard    while (stream != NULL) {
17962b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard        next = stream->next;
17972fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        if (stream->states != NULL)
17982fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    xmlFree(stream->states);
17992fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        xmlFree(stream);
18002b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard	stream = next;
18012fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
18022fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
18032fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
18042fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
18052fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlStreamCtxtAddState:
18062fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @comp: the stream context
18072fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @idx: the step index for that streaming state
18082fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
18092fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Add a new state to the stream context
18102fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
18112fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Returns -1 in case of error or the state index if successful
18122fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
18132fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardstatic int
18142fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlStreamCtxtAddState(xmlStreamCtxtPtr comp, int idx, int level) {
18152fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    int i;
18162fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    for (i = 0;i < comp->nbState;i++) {
18172fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        if (comp->states[2 * i] < 0) {
18182fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    comp->states[2 * i] = idx;
18192fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    comp->states[2 * i + 1] = level;
18202fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    return(i);
18212fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
18222fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
18232fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (comp->nbState >= comp->maxState) {
18242fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        int *cur;
18252fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
18262fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	cur = (int *) xmlRealloc(comp->states,
18272fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard				 comp->maxState * 4 * sizeof(int));
18282fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	if (cur == NULL) {
18292fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    ERROR(NULL, NULL, NULL,
18302fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		  "xmlNewStreamCtxt: malloc failed\n");
18312fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    return(-1);
18322fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
18332fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	comp->states = cur;
18342fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        comp->maxState *= 2;
18352fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    }
18362fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    comp->states[2 * comp->nbState] = idx;
18372fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    comp->states[2 * comp->nbState++ + 1] = level;
18382fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    return(comp->nbState - 1);
18392fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
18402fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
18412fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
18422a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * xmlStreamPushInternal:
18432fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @stream: the stream context
18442fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @name: the current name
18452fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @ns: the namespace name
18462a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * @nodeType: the type of the node
18472fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
1848fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
1849fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * indicated a dictionary, then strings for name and ns will be expected
18502fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * to come from the dictionary.
18512fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Both @name and @ns being NULL means the / i.e. the root of the document.
18522fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * This can also act as a reset.
18532fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
18542fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Returns: -1 in case of error, 1 if the current state in the stream is a
18552fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *    match and 0 otherwise.
18562fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
18572a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcikstatic int
18582a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. BuchcikxmlStreamPushInternal(xmlStreamCtxtPtr stream,
18592a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		      const xmlChar *name, const xmlChar *ns,
186097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		      int nodeType) {
18616ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc;
18622fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    xmlStreamCompPtr comp;
18636ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik    xmlStreamStep step;
18642b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard#ifdef DEBUG_STREAMING
18652b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard    xmlStreamCtxtPtr orig = stream;
18662b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard#endif
18672fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
18682fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if ((stream == NULL) || (stream->nbState < 0))
18692fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        return(-1);
1870f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard
1871f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    while (stream != NULL) {
1872f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	comp = stream->comp;
187397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
187497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	if ((nodeType == XML_ELEMENT_NODE) &&
187597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    (name == NULL) && (ns == NULL)) {
187697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    /* We have a document node here (or a reset). */
1877f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    stream->nbState = 0;
1878f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    stream->level = 0;
18799ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    stream->blockLevel = -1;
188097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    if (comp->flags & XML_STREAM_FROM_ROOT) {
188197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		if (comp->nbStep == 0) {
188297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    /* TODO: We have a "/." here? */
1883f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		    ret = 1;
188497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		} else {
188597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    if ((comp->nbStep == 1) &&
188697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			(comp->steps[0].nodeType == XML_STREAM_ANY_NODE) &&
188797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			(comp->steps[0].flags & XML_STREAM_STEP_DESC))
188897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    {
188997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			/*
189097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			* In the case of "//." the document node will match
189197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			* as well.
189297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			*/
189397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			ret = 1;
189497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    } else if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {
189597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			/* TODO: Do we need this ? */
189697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			tmp = xmlStreamCtxtAddState(stream, 0, 0);
189797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			if (tmp < 0)
189897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik			    err++;
189997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		    }
190097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		}
19012fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	    }
19022b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard	    stream = stream->next;
1903f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    continue; /* while */
19042fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
19052a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik
19062a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	/*
19072a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	* Fast check for ".".
19082a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	*/
19092a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	if (comp->nbStep == 0) {
191022678566b81e8b026470e4caf37ecb28c9b6f5ceKasimier T. Buchcik	    /*
1911f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	     * / and . are handled at the XPath node set creation
1912f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	     * level by checking min depth
1913f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	     */
1914f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	    if (stream->flags & XML_PATTERN_XPATH) {
1915f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard		stream = stream->next;
1916f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard		continue; /* while */
1917f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	    }
1918f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	    /*
1919ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	    * For non-pattern like evaluation like XML Schema IDCs
1920ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	    * or traditional XPath expressions, this will match if
1921ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	    * we are at the first level only, otherwise on every level.
192222678566b81e8b026470e4caf37ecb28c9b6f5ceKasimier T. Buchcik	    */
192397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    if ((nodeType != XML_ATTRIBUTE_NODE) &&
192422678566b81e8b026470e4caf37ecb28c9b6f5ceKasimier T. Buchcik		(((stream->flags & XML_PATTERN_NOTPATTERN) == 0) ||
192522678566b81e8b026470e4caf37ecb28c9b6f5ceKasimier T. Buchcik		(stream->level == 0))) {
1926f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    ret = 1;
192722678566b81e8b026470e4caf37ecb28c9b6f5ceKasimier T. Buchcik	    }
192822678566b81e8b026470e4caf37ecb28c9b6f5ceKasimier T. Buchcik	    stream->level++;
19292a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    goto stream_next;
19302a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	}
19319ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	if (stream->blockLevel != -1) {
19329ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    /*
19339ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * Skip blocked expressions.
19349ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    */
1935f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    stream->level++;
19369ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    goto stream_next;
1937ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	}
193897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
193997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	if ((nodeType != XML_ELEMENT_NODE) &&
194097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    (nodeType != XML_ATTRIBUTE_NODE) &&
194197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    ((comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) == 0)) {
194297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    /*
194397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    * No need to process nodes of other types if we don't
194497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    * resolve to those types.
194597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    * TODO: Do we need to block the context here?
194697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    */
194797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    stream->level++;
194897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    goto stream_next;
194997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	}
195097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
1951f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	/*
1952f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	 * Check evolution of existing states
1953f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	 */
19549ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	i = 0;
1955f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	m = stream->nbState;
19569ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	while (i < m) {
19579ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if ((comp->flags & XML_STREAM_DESC) == 0) {
19589ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/*
19599ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* If there is no "//", then only the last
19609ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* added state is of interest.
19619ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		*/
19626ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		stepNr = stream->states[2 * (stream->nbState -1)];
19639ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/*
19649ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* TODO: Security check, should not happen, remove it.
19659ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		*/
19669ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		if (stream->states[(2 * (stream->nbState -1)) + 1] <
19679ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    stream->level) {
19689ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    return (-1);
19699ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		}
19709ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		desc = 0;
19719ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/* loop-stopper */
19729ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		i = m;
19739ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    } else {
19749ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/*
19759ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* If there are "//", then we need to process every "//"
19769ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* occuring in the states, plus any other state for this
19779ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* level.
1978f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		*/
19796ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		stepNr = stream->states[2 * i];
19809ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
19819ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/* TODO: should not happen anymore: dead states */
19826ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		if (stepNr < 0)
19839ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    goto next_state;
19849ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
19859ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		tmp = stream->states[(2 * i) + 1];
19869ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
19879ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/* skip new states just added */
19889ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		if (tmp > stream->level)
19899ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    goto next_state;
19909ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
19919ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/* skip states at ancestor levels, except if "//" */
19926ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		desc = comp->steps[stepNr].flags & XML_STREAM_STEP_DESC;
19939ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		if ((tmp < stream->level) && (!desc))
19949ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    goto next_state;
19959ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    }
1996f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    /*
19972a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    * Check for correct node-type.
19982a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	    */
19996ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    step = comp->steps[stepNr];
20006ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    if (step.nodeType != nodeType) {
20016ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		if (step.nodeType == XML_ATTRIBUTE_NODE) {
2002940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    /*
2003940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    * Block this expression for deeper evaluation.
2004940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    */
2005940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik		    if ((comp->flags & XML_STREAM_DESC) == 0)
2006940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik			stream->blockLevel = stream->level +1;
200727820270838916fb8ee9192fb80af3adb9ca120bKasimier T. Buchcik		    goto next_state;
20086ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		} else if (step.nodeType != XML_STREAM_ANY_NODE)
200927820270838916fb8ee9192fb80af3adb9ca120bKasimier T. Buchcik		    goto next_state;
2010f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    }
20119ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    /*
20129ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * Compare local/namespace-name.
20139ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    */
20149ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    match = 0;
20156ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    if (step.nodeType == XML_STREAM_ANY_NODE) {
201697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		match = 1;
20176ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    } else if (step.name == NULL) {
20186ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		if (step.ns == NULL) {
20196ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    /*
20206ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    * This lets through all elements/attributes.
20216ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    */
20226ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    match = 1;
20236ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		} else if (ns != NULL)
20246ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    match = xmlStrEqual(step.ns, ns);
20256ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    } else if (((step.ns != NULL) == (ns != NULL)) &&
20266ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		(name != NULL) &&
20276ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		(step.name[0] == name[0]) &&
20286ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		xmlStrEqual(step.name, name) &&
20296ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		((step.ns == ns) || xmlStrEqual(step.ns, ns)))
20306ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    {
2031f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		match = 1;
2032f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    }
2033f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard#if 0
20346ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik/*
20356ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik* TODO: Pointer comparison won't work, since not guaranteed that the given
20366ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik*  values are in the same dict; especially if it's the namespace name,
20376ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik*  normally coming from ns->href. We need a namespace dict mechanism !
20386ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik*/
203997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    } else if (comp->dict) {
20406ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		if (step.name == NULL) {
20416ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    if (step.ns == NULL)
2042f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard			match = 1;
2043f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		    else
20446ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik			match = (step.ns == ns);
20452fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		} else {
20466ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		    match = ((step.name == name) && (step.ns == ns));
20472fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		}
2048f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard#endif /* if 0 ------------------------------------------------------- */
2049f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    if (match) {
20506ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		final = step.flags & XML_STREAM_STEP_FINAL;
2051f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		if (desc) {
2052f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		    if (final) {
2053f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard			ret = 1;
2054f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		    } else {
2055f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard			/* descending match create a new state */
20566ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik			xmlStreamCtxtAddState(stream, stepNr + 1,
2057f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard			                      stream->level + 1);
2058f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		    }
2059f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		} else {
2060f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		    if (final) {
2061f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard			ret = 1;
2062f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		    } else {
20636ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik			xmlStreamCtxtAddState(stream, stepNr + 1,
2064f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard			                      stream->level + 1);
2065f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		    }
20662fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard		}
20676ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
2068bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		    /*
2069bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		    * Check if we have a special case like "foo/bar//.", where
2070bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		    * "foo" is selected as well.
2071bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		    */
2072bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		    ret = 1;
2073bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		}
2074f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    }
20759ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if (((comp->flags & XML_STREAM_DESC) == 0) &&
20769ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		((! match) || final))  {
20779ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		/*
20789ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* Mark this expression as blocked for any evaluation at
20799ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* deeper levels. Note that this includes "/foo"
20809ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		* expressions if the *pattern* behaviour is used.
20819ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		*/
20829ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		stream->blockLevel = stream->level +1;
20839ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    }
20849ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchciknext_state:
20859ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    i++;
20862fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard	}
20872fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
2088f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	stream->level++;
20899ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
20902a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	/*
20919ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	* Re/enter the expression.
209297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	* Don't reenter if it's an absolute expression like "/foo",
209397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	*   except "//foo".
20942a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik	*/
20956ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	step = comp->steps[0];
20966ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	if (step.flags & XML_STREAM_STEP_ROOT)
20979ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    goto stream_next;
20989ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
20996ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	desc = step.flags & XML_STREAM_STEP_DESC;
21009ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	if (stream->flags & XML_PATTERN_NOTPATTERN) {
21019ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    /*
21029ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * Re/enter the expression if it is a "descendant" one,
21039ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * or if we are at the 1st level of evaluation.
21049ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    */
2105f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
21069ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if (stream->level == 1) {
21079ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		if (XML_STREAM_XS_IDC(stream)) {
21089ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    /*
21099ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    * XS-IDC: The missing "self::node()" will always
21109ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    * match the first given node.
21119ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    */
21129ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    goto stream_next;
21139ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		} else
21149ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		    goto compare;
2115f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    }
21169ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    /*
21179ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * A "//" is always reentrant.
21189ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    */
21199ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if (desc)
21209ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		goto compare;
2121285ebabb07c93921a60e4ab2dbefcbc0c49fb334Kasimier T. Buchcik
21229ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    /*
21239ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * XS-IDC: Process the 2nd level, since the missing
21249ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * "self::node()" is responsible for the 2nd level being
2125f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    * the real start level.
2126f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    */
21279ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if ((stream->level == 2) && XML_STREAM_XS_IDC(stream))
21289ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		goto compare;
2129285ebabb07c93921a60e4ab2dbefcbc0c49fb334Kasimier T. Buchcik
21309ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    goto stream_next;
21319ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	}
2132f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
21339ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcikcompare:
21349ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	/*
21359ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	* Check expected node-type.
2136285ebabb07c93921a60e4ab2dbefcbc0c49fb334Kasimier T. Buchcik	*/
21376ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	if (step.nodeType != nodeType) {
213897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    if (nodeType == XML_ATTRIBUTE_NODE)
213927820270838916fb8ee9192fb80af3adb9ca120bKasimier T. Buchcik		goto stream_next;
21406ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    else if (step.nodeType != XML_STREAM_ANY_NODE)
2141f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		goto stream_next;
214227820270838916fb8ee9192fb80af3adb9ca120bKasimier T. Buchcik	}
21439ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	/*
21449ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	* Compare local/namespace-name.
21459ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	*/
21469ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	match = 0;
21476ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	if (step.nodeType == XML_STREAM_ANY_NODE) {
214897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    match = 1;
21496ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	} else if (step.name == NULL) {
21506ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    if (step.ns == NULL) {
21516ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		/*
21526ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		* This lets through all elements/attributes.
21536ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		*/
21549ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		match = 1;
21556ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    } else if (ns != NULL)
21566ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik		match = xmlStrEqual(step.ns, ns);
21576ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	} else if (((step.ns != NULL) == (ns != NULL)) &&
21586ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    (name != NULL) &&
21596ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    (step.name[0] == name[0]) &&
21606ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    xmlStrEqual(step.name, name) &&
21616ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    ((step.ns == ns) || xmlStrEqual(step.ns, ns)))
21626ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	{
2163f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	    match = 1;
2164f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	}
21656ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	final = step.flags & XML_STREAM_STEP_FINAL;
2166f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	if (match) {
21679ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if (final)
21689ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		ret = 1;
21699ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    else
21709ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		xmlStreamCtxtAddState(stream, 1, stream->level);
21716ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
2172bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		/*
2173bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		* Check if we have a special case like "foo//.", where
2174bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		* "foo" is selected as well.
2175bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		*/
2176bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik		ret = 1;
2177bb80f544d4c431bcfbc267d573b6578806c617e5Kasimier T. Buchcik	    }
21789ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	}
21799ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	if (((comp->flags & XML_STREAM_DESC) == 0) &&
21809ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    ((! match) || final))  {
21819ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    /*
21829ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * Mark this expression as blocked for any evaluation at
21839ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    * deeper levels.
21849ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    */
21859ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    stream->blockLevel = stream->level;
21869ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	}
2187940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik
21882a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcikstream_next:
2189f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard        stream = stream->next;
2190f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    } /* while stream != NULL */
2191f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
2192f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    if (err > 0)
2193f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard        ret = -1;
21942b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard#ifdef DEBUG_STREAMING
21952b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard    xmlDebugStreamCtxt(orig, ret);
21962b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard#endif
21972fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    return(ret);
21982fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
21992fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
22002fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
22012a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * xmlStreamPush:
22022a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * @stream: the stream context
22032a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * @name: the current name
22042a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * @ns: the namespace name
22052a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik *
2206fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
2207fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * indicated a dictionary, then strings for name and ns will be expected
22082a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * to come from the dictionary.
22092a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * Both @name and @ns being NULL means the / i.e. the root of the document.
22102a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * This can also act as a reset.
221197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * Otherwise the function will act as if it has been given an element-node.
22122a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik *
22132a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik * Returns: -1 in case of error, 1 if the current state in the stream is a
22142a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik *    match and 0 otherwise.
22152a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik */
22162a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcikint
22172a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. BuchcikxmlStreamPush(xmlStreamCtxtPtr stream,
22182a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik              const xmlChar *name, const xmlChar *ns) {
221997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    return (xmlStreamPushInternal(stream, name, ns, (int) XML_ELEMENT_NODE));
222097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik}
222197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
222297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik/**
22236795260135a78da60182504a2d7efb4e3177eb57Daniel Veillard * xmlStreamPushNode:
222497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * @stream: the stream context
222597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * @name: the current name
222697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * @ns: the namespace name
222797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * @nodeType: the type of the node being pushed
222897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik *
222997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
223097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * indicated a dictionary, then strings for name and ns will be expected
223197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * to come from the dictionary.
223297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * Both @name and @ns being NULL means the / i.e. the root of the document.
223397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * This can also act as a reset.
223497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * Different from xmlStreamPush() this function can be fed with nodes of type:
223597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * element-, attribute-, text-, cdata-section-, comment- and
223697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * processing-instruction-node.
223797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik *
223897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * Returns: -1 in case of error, 1 if the current state in the stream is a
223997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik *    match and 0 otherwise.
224097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik */
224197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcikint
224297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. BuchcikxmlStreamPushNode(xmlStreamCtxtPtr stream,
224397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		  const xmlChar *name, const xmlChar *ns,
224497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik		  int nodeType)
224597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik{
224697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    return (xmlStreamPushInternal(stream, name, ns,
224797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	nodeType));
22482a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik}
22492a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik
22502a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik/**
22512a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik* xmlStreamPushAttr:
22522a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik* @stream: the stream context
22532a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik* @name: the current name
22542a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik* @ns: the namespace name
22552a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik*
2256fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack* Push new attribute data onto the stream. NOTE: if the call xmlPatterncompile()
2257fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack* indicated a dictionary, then strings for name and ns will be expected
22582a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik* to come from the dictionary.
22592a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik* Both @name and @ns being NULL means the / i.e. the root of the document.
22602a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik* This can also act as a reset.
226197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik* Otherwise the function will act as if it has been given an attribute-node.
22622a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik*
22632a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik* Returns: -1 in case of error, 1 if the current state in the stream is a
22642a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik*    match and 0 otherwise.
22652a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik*/
22662a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcikint
22672a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. BuchcikxmlStreamPushAttr(xmlStreamCtxtPtr stream,
22682a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik		  const xmlChar *name, const xmlChar *ns) {
226997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    return (xmlStreamPushInternal(stream, name, ns, (int) XML_ATTRIBUTE_NODE));
22702a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik}
22712a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik
22722a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik/**
22732fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlStreamPop:
22742fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @stream: the stream context
22752fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
22762fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * push one level from the stream.
22772fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
22782fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Returns: -1 in case of error, 0 otherwise.
22792fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
22802fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillardint
22812fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlStreamPop(xmlStreamCtxtPtr stream) {
22829ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik    int i, lev;
2283f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
22842fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if (stream == NULL)
22852fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        return(-1);
2286f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    while (stream != NULL) {
22879ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	/*
22889ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	* Reset block-level.
22899ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	*/
22909ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	if (stream->blockLevel == stream->level)
22919ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    stream->blockLevel = -1;
22929ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik
2293f8477005ab036338fb1af8781037f7a9f5f3911cWilliam M. Brack	/*
2294f8477005ab036338fb1af8781037f7a9f5f3911cWilliam M. Brack	 *  stream->level can be zero when XML_FINAL_IS_ANY_NODE is set
2295f8477005ab036338fb1af8781037f7a9f5f3911cWilliam M. Brack	 *  (see the thread at
2296f8477005ab036338fb1af8781037f7a9f5f3911cWilliam M. Brack	 *  http://mail.gnome.org/archives/xslt/2008-July/msg00027.html)
2297f8477005ab036338fb1af8781037f7a9f5f3911cWilliam M. Brack	 */
2298f8477005ab036338fb1af8781037f7a9f5f3911cWilliam M. Brack	if (stream->level)
2299f8477005ab036338fb1af8781037f7a9f5f3911cWilliam M. Brack	    stream->level--;
2300f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	/*
2301f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	 * Check evolution of existing states
2302f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	 */
23039ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	for (i = stream->nbState -1; i >= 0; i--) {
2304f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    /* discard obsoleted states */
23059ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    lev = stream->states[(2 * i) + 1];
23069ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if (lev > stream->level)
23079ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		stream->nbState--;
23089ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik	    if (lev <= stream->level)
23099ca11bfc3dcd4616cad1c90a025591ebba940839Kasimier T. Buchcik		break;
2310f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	}
2311f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	stream = stream->next;
23129740d1d42595ec01cafcfe49c7217229fd8b5bb8Daniel Veillard    }
23132fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    return(0);
23142fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
23152fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
231697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik/**
231797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * xmlStreamWantsAnyNode:
23186795260135a78da60182504a2d7efb4e3177eb57Daniel Veillard * @streamCtxt: the stream context
231997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik *
232097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * Query if the streaming pattern additionally needs to be fed with
232197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * text-, cdata-section-, comment- and processing-instruction-nodes.
232297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * If the result is 0 then only element-nodes and attribute-nodes
232397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * need to be pushed.
232497258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik *
232597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik * Returns: 1 in case of need of nodes of the above described types,
232697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik *          0 otherwise. -1 on API errors.
232797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik */
232897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcikint
232997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. BuchcikxmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt)
2330f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard{
233197258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    if (streamCtxt == NULL)
233297258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	return(-1);
233397258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    while (streamCtxt != NULL) {
2334f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	if (streamCtxt->comp->flags & XML_STREAM_FINAL_IS_ANY_NODE)
233597258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	    return(1);
233697258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik	streamCtxt = streamCtxt->next;
233797258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    }
233897258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik    return(0);
233997258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik}
234097258713d37a6a9f42dd7e2b5a99b26f3e80789dKasimier T. Buchcik
2341b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/************************************************************************
2342b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *									*
2343b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *			The public interfaces				*
2344b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *									*
2345b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard ************************************************************************/
2346b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
2347b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
2348b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlPatterncompile:
2349b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @pattern: the pattern to compile
2350fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * @dict: an optional dictionary for interned strings
2351ed6c54971fdb7fa37c183b1a36c2e581c750984bDaniel Veillard * @flags: compilation flags, see xmlPatternFlags
2352ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
2353b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
2354ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard * Compile a pattern.
2355b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
2356fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * Returns the compiled form of the pattern or NULL in case of error
2357b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
2358b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlPatternPtr
2359ed6c54971fdb7fa37c183b1a36c2e581c750984bDaniel VeillardxmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
2360ffa7b7e2ba3841a80f9c5a69e89cc4b4e457840bDaniel Veillard                  const xmlChar **namespaces) {
2361f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    xmlPatternPtr ret = NULL, cur;
2362b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    xmlPatParserContextPtr ctxt = NULL;
2363f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    const xmlChar *or, *start;
2364f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    xmlChar *tmp = NULL;
2365fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    int type = 0;
2366fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    int streamable = 1;
2367f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard
2368f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    if (pattern == NULL)
2369f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard        return(NULL);
2370f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard
2371f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    start = pattern;
23722b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard    or = start;
2373f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    while (*or != 0) {
2374f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	tmp = NULL;
2375f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	while ((*or != 0) && (*or != '|')) or++;
2376f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard        if (*or == 0)
2377f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    ctxt = xmlNewPatParserContext(start, dict, namespaces);
2378f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	else {
2379f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    tmp = xmlStrndup(start, or - start);
2380f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    if (tmp != NULL) {
2381f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard		ctxt = xmlNewPatParserContext(tmp, dict, namespaces);
2382f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    }
2383f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    or++;
2384f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	}
2385f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	if (ctxt == NULL) goto error;
2386f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	cur = xmlNewPattern();
2387f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	if (cur == NULL) goto error;
23886ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	/*
23896ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	* Assign string dict.
23906ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	*/
2391f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard	if (dict) {
23926ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    cur->dict = dict;
23936ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	    xmlDictReference(dict);
23946ed2eb47fcf485283c6dc2dbd0ba0270f22a23b6Kasimier T. Buchcik	}
2395f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	if (ret == NULL)
2396f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    ret = cur;
2397f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	else {
2398f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    cur->next = ret->next;
2399f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    ret->next = cur;
2400f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	}
2401285ebabb07c93921a60e4ab2dbefcbc0c49fb334Kasimier T. Buchcik	cur->flags = flags;
2402f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	ctxt->comp = cur;
2403b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
2404940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	if (XML_STREAM_XS_IDC(cur))
2405940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    xmlCompileIDCXPathPath(ctxt);
2406940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	else
2407940ab0c67628bee90b60e3e80362e2425f248bd7Kasimier T. Buchcik	    xmlCompilePathPattern(ctxt);
240856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (ctxt->error != 0)
240956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    goto error;
2410f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	xmlFreePatParserContext(ctxt);
2411fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack	ctxt = NULL;
2412b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
2413b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
2414fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard        if (streamable) {
2415fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    if (type == 0) {
2416fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	        type = cur->flags & (PAT_FROM_ROOT | PAT_FROM_CUR);
2417fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    } else if (type == PAT_FROM_ROOT) {
2418fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	        if (cur->flags & PAT_FROM_CUR)
2419fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard		    streamable = 0;
2420fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    } else if (type == PAT_FROM_CUR) {
2421fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	        if (cur->flags & PAT_FROM_ROOT)
2422fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard		    streamable = 0;
2423fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    }
2424fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	}
2425fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	if (streamable)
2426fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    xmlStreamCompile(cur);
2427f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	if (xmlReversePattern(cur) < 0)
2428f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    goto error;
2429ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	if (tmp != NULL) {
2430f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    xmlFree(tmp);
2431ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	    tmp = NULL;
2432ea152c05b3f3d9e47b282b88ffdb16fcb8c779c1William M. Brack	}
24332b2e02d6bb15ae7c4dc14c1a468158f0b8c3f367Daniel Veillard	start = or;
2434f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    }
2435fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    if (streamable == 0) {
2436fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard        cur = ret;
2437fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	while (cur != NULL) {
2438fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    if (cur->stream != NULL) {
2439fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard		xmlFreeStreamComp(cur->stream);
2440fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard		cur->stream = NULL;
2441fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    }
2442fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	    cur = cur->next;
2443fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard	}
2444fa1f77f2f04d6960b934f9ebf7cdb20bb8f5e8fdDaniel Veillard    }
2445285ebabb07c93921a60e4ab2dbefcbc0c49fb334Kasimier T. Buchcik
2446b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(ret);
2447b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillarderror:
2448b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (ctxt != NULL) xmlFreePatParserContext(ctxt);
2449b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if (ret != NULL) xmlFreePattern(ret);
2450f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    if (tmp != NULL) xmlFree(tmp);
2451b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    return(NULL);
2452b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
2453b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
2454b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard/**
2455b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * xmlPatternMatch:
2456b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @comp: the precompiled pattern
2457b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * @node: a node
2458b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
2459fbb619f4762fd50630e3ec22589838d089cd2f08William M. Brack * Test whether the node matches the pattern
2460b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard *
2461b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
2462b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard */
2463b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillardint
2464b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel VeillardxmlPatternMatch(xmlPatternPtr comp, xmlNodePtr node)
2465b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard{
2466f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    int ret = 0;
2467f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard
2468b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard    if ((comp == NULL) || (node == NULL))
2469b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard        return(-1);
2470f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard
2471f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    while (comp != NULL) {
2472f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard        ret = xmlPatMatch(comp, node);
2473f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	if (ret != 0)
2474f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    return(ret);
2475f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	comp = comp->next;
2476f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    }
2477f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    return(ret);
2478b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard}
2479b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard
24802fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard/**
24812fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * xmlPatternGetStreamCtxt:
24822fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * @comp: the precompiled pattern
24832fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
24842fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Get a streaming context for that pattern
24852fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Use xmlFreeStreamCtxt to free the context.
24862fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard *
24872fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard * Returns a pointer to the context or NULL in case of failure
24882fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard */
24892fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlStreamCtxtPtr
24902fc6df95cc021fb16debe942697eda86eeba39aeDaniel VeillardxmlPatternGetStreamCtxt(xmlPatternPtr comp)
24912fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard{
2492f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    xmlStreamCtxtPtr ret = NULL, cur;
2493f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard
24942fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard    if ((comp == NULL) || (comp->stream == NULL))
24952fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard        return(NULL);
2496f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard
2497f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    while (comp != NULL) {
2498f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard        if (comp->stream == NULL)
2499f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    goto failed;
2500f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	cur = xmlNewStreamCtxt(comp->stream);
2501f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	if (cur == NULL)
2502f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    goto failed;
2503f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	if (ret == NULL)
2504f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    ret = cur;
2505f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	else {
2506f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    cur->next = ret->next;
2507f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	    ret->next = cur;
2508f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	}
2509285ebabb07c93921a60e4ab2dbefcbc0c49fb334Kasimier T. Buchcik	cur->flags = comp->flags;
2510f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard	comp = comp->next;
2511f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    }
2512f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    return(ret);
2513f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillardfailed:
2514f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    xmlFreeStreamCtxt(ret);
2515f1f08cf8dc28095860998f28e392c08ea620bb60Daniel Veillard    return(NULL);
25162fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard}
25172fc6df95cc021fb16debe942697eda86eeba39aeDaniel Veillard
251856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard/**
251956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * xmlPatternStreamable:
252056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @comp: the precompiled pattern
252156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
252256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Check if the pattern is streamable i.e. xmlPatternGetStreamCtxt()
252356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * should work.
252456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
252556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Returns 1 if streamable, 0 if not and -1 in case of error.
252656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard */
252756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardint
252856de87ee0d147d04a041eb1ec95048566375bc3fDaniel VeillardxmlPatternStreamable(xmlPatternPtr comp) {
252956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp == NULL)
253056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(-1);
253156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    while (comp != NULL) {
253256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        if (comp->stream == NULL)
253356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return(0);
253456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	comp = comp->next;
253556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
253656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    return(1);
253756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard}
253856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
253956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard/**
254056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * xmlPatternMaxDepth:
254156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @comp: the precompiled pattern
254256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
254356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Check the maximum depth reachable by a pattern
254456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
254556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Returns -2 if no limit (using //), otherwise the depth,
254656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *         and -1 in case of error
254756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard */
254856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardint
254956de87ee0d147d04a041eb1ec95048566375bc3fDaniel VeillardxmlPatternMaxDepth(xmlPatternPtr comp) {
255056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    int ret = 0, i;
255156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp == NULL)
255256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(-1);
255356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    while (comp != NULL) {
255456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        if (comp->stream == NULL)
255556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return(-1);
255656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	for (i = 0;i < comp->stream->nbStep;i++)
255756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    if (comp->stream->steps[i].flags & XML_STREAM_STEP_DESC)
255856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	        return(-2);
255956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (comp->stream->nbStep > ret)
256056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    ret = comp->stream->nbStep;
256156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	comp = comp->next;
256256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
256356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    return(ret);
2564f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard}
256556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
2566f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard/**
2567f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard * xmlPatternMinDepth:
2568f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard * @comp: the precompiled pattern
2569f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard *
2570f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard * Check the minimum depth reachable by a pattern, 0 mean the / or . are
2571f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard * part of the set.
2572f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard *
2573f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard * Returns -1 in case of error otherwise the depth,
2574f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard *
2575f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard */
2576f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillardint
2577f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel VeillardxmlPatternMinDepth(xmlPatternPtr comp) {
2578f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    int ret = 12345678;
2579f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    if (comp == NULL)
2580f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard        return(-1);
2581f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    while (comp != NULL) {
2582f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard        if (comp->stream == NULL)
2583f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	    return(-1);
2584f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	if (comp->stream->nbStep < ret)
2585f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	    ret = comp->stream->nbStep;
2586f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	if (ret == 0)
2587f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	    return(0);
2588f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard	comp = comp->next;
2589f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    }
2590f03a8cdacdce917d09972c65371953e8a57a2ac3Daniel Veillard    return(ret);
259156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard}
259256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
259356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard/**
259456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * xmlPatternFromRoot:
259556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * @comp: the precompiled pattern
259656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
259756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Check if the pattern must be looked at from the root.
259856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard *
259956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard * Returns 1 if true, 0 if false and -1 in case of error
260056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard */
260156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillardint
260256de87ee0d147d04a041eb1ec95048566375bc3fDaniel VeillardxmlPatternFromRoot(xmlPatternPtr comp) {
260356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    if (comp == NULL)
260456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        return(-1);
260556de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    while (comp != NULL) {
260656de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard        if (comp->stream == NULL)
260756de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return(-1);
260856de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	if (comp->flags & PAT_FROM_ROOT)
260956de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	    return(1);
261056de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard	comp = comp->next;
261156de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    }
261256de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard    return(0);
261356de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard
261456de87ee0d147d04a041eb1ec95048566375bc3fDaniel Veillard}
26152a0fdd9101204b9b8ce68050b50cdd1e0ec71049Kasimier T. Buchcik
26165d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#define bottom_pattern
26175d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#include "elfgcchack.h"
2618b3de70c28294f6c7f7ef8ec0033fb302b0dfbe26Daniel Veillard#endif /* LIBXML_PATTERN_ENABLED */
2619