xref: /aosp_15_r20/external/libxml2/xmlregexp.c (revision 7c5688314b92172186c154356a6374bf7684c3ca)
1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker  * regexp.c: generic and extensible Regular Expression engine
3*7c568831SAndroid Build Coastguard Worker  *
4*7c568831SAndroid Build Coastguard Worker  * Basically designed with the purpose of compiling regexps for
5*7c568831SAndroid Build Coastguard Worker  * the variety of validation/schemas mechanisms now available in
6*7c568831SAndroid Build Coastguard Worker  * XML related specifications these include:
7*7c568831SAndroid Build Coastguard Worker  *    - XML-1.0 DTD validation
8*7c568831SAndroid Build Coastguard Worker  *    - XML Schemas structure part 1
9*7c568831SAndroid Build Coastguard Worker  *    - XML Schemas Datatypes part 2 especially Appendix F
10*7c568831SAndroid Build Coastguard Worker  *    - RELAX-NG/TREX i.e. the counter proposal
11*7c568831SAndroid Build Coastguard Worker  *
12*7c568831SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
13*7c568831SAndroid Build Coastguard Worker  *
14*7c568831SAndroid Build Coastguard Worker  * Daniel Veillard <[email protected]>
15*7c568831SAndroid Build Coastguard Worker  */
16*7c568831SAndroid Build Coastguard Worker 
17*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
18*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
19*7c568831SAndroid Build Coastguard Worker 
20*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_REGEXP_ENABLED
21*7c568831SAndroid Build Coastguard Worker 
22*7c568831SAndroid Build Coastguard Worker #include <stdio.h>
23*7c568831SAndroid Build Coastguard Worker #include <string.h>
24*7c568831SAndroid Build Coastguard Worker #include <limits.h>
25*7c568831SAndroid Build Coastguard Worker 
26*7c568831SAndroid Build Coastguard Worker #include <libxml/tree.h>
27*7c568831SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
28*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlregexp.h>
29*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlautomata.h>
30*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlunicode.h>
31*7c568831SAndroid Build Coastguard Worker 
32*7c568831SAndroid Build Coastguard Worker #include "private/error.h"
33*7c568831SAndroid Build Coastguard Worker #include "private/regexp.h"
34*7c568831SAndroid Build Coastguard Worker 
35*7c568831SAndroid Build Coastguard Worker #ifndef SIZE_MAX
36*7c568831SAndroid Build Coastguard Worker #define SIZE_MAX ((size_t) -1)
37*7c568831SAndroid Build Coastguard Worker #endif
38*7c568831SAndroid Build Coastguard Worker 
39*7c568831SAndroid Build Coastguard Worker #define MAX_PUSH 10000000
40*7c568831SAndroid Build Coastguard Worker 
41*7c568831SAndroid Build Coastguard Worker #ifdef ERROR
42*7c568831SAndroid Build Coastguard Worker #undef ERROR
43*7c568831SAndroid Build Coastguard Worker #endif
44*7c568831SAndroid Build Coastguard Worker #define ERROR(str)							\
45*7c568831SAndroid Build Coastguard Worker     ctxt->error = XML_REGEXP_COMPILE_ERROR;				\
46*7c568831SAndroid Build Coastguard Worker     xmlRegexpErrCompile(ctxt, str);
47*7c568831SAndroid Build Coastguard Worker #define NEXT ctxt->cur++
48*7c568831SAndroid Build Coastguard Worker #define CUR (*(ctxt->cur))
49*7c568831SAndroid Build Coastguard Worker #define NXT(index) (ctxt->cur[index])
50*7c568831SAndroid Build Coastguard Worker 
51*7c568831SAndroid Build Coastguard Worker #define NEXTL(l) ctxt->cur += l;
52*7c568831SAndroid Build Coastguard Worker #define XML_REG_STRING_SEPARATOR '|'
53*7c568831SAndroid Build Coastguard Worker /*
54*7c568831SAndroid Build Coastguard Worker  * Need PREV to check on a '-' within a Character Group. May only be used
55*7c568831SAndroid Build Coastguard Worker  * when it's guaranteed that cur is not at the beginning of ctxt->string!
56*7c568831SAndroid Build Coastguard Worker  */
57*7c568831SAndroid Build Coastguard Worker #define PREV (ctxt->cur[-1])
58*7c568831SAndroid Build Coastguard Worker 
59*7c568831SAndroid Build Coastguard Worker /************************************************************************
60*7c568831SAndroid Build Coastguard Worker  *									*
61*7c568831SAndroid Build Coastguard Worker  *			Datatypes and structures			*
62*7c568831SAndroid Build Coastguard Worker  *									*
63*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
64*7c568831SAndroid Build Coastguard Worker 
65*7c568831SAndroid Build Coastguard Worker /*
66*7c568831SAndroid Build Coastguard Worker  * Note: the order of the enums below is significant, do not shuffle
67*7c568831SAndroid Build Coastguard Worker  */
68*7c568831SAndroid Build Coastguard Worker typedef enum {
69*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_EPSILON = 1,
70*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_CHARVAL,
71*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_RANGES,
72*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SUBREG,  /* used for () sub regexps */
73*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_STRING,
74*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_ANYCHAR, /* . */
75*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_ANYSPACE, /* \s */
76*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NOTSPACE, /* \S */
77*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_INITNAME, /* \l */
78*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NOTINITNAME, /* \L */
79*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NAMECHAR, /* \c */
80*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NOTNAMECHAR, /* \C */
81*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_DECIMAL, /* \d */
82*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NOTDECIMAL, /* \D */
83*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_REALCHAR, /* \w */
84*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NOTREALCHAR, /* \W */
85*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_LETTER = 100,
86*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_LETTER_UPPERCASE,
87*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_LETTER_LOWERCASE,
88*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_LETTER_TITLECASE,
89*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_LETTER_MODIFIER,
90*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_LETTER_OTHERS,
91*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_MARK,
92*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_MARK_NONSPACING,
93*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_MARK_SPACECOMBINING,
94*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_MARK_ENCLOSING,
95*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NUMBER,
96*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NUMBER_DECIMAL,
97*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NUMBER_LETTER,
98*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_NUMBER_OTHERS,
99*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_PUNCT,
100*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_PUNCT_CONNECTOR,
101*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_PUNCT_DASH,
102*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_PUNCT_OPEN,
103*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_PUNCT_CLOSE,
104*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_PUNCT_INITQUOTE,
105*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_PUNCT_FINQUOTE,
106*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_PUNCT_OTHERS,
107*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SEPAR,
108*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SEPAR_SPACE,
109*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SEPAR_LINE,
110*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SEPAR_PARA,
111*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SYMBOL,
112*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SYMBOL_MATH,
113*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SYMBOL_CURRENCY,
114*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SYMBOL_MODIFIER,
115*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SYMBOL_OTHERS,
116*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_OTHER,
117*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_OTHER_CONTROL,
118*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_OTHER_FORMAT,
119*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_OTHER_PRIVATE,
120*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_OTHER_NA,
121*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_BLOCK_NAME
122*7c568831SAndroid Build Coastguard Worker } xmlRegAtomType;
123*7c568831SAndroid Build Coastguard Worker 
124*7c568831SAndroid Build Coastguard Worker typedef enum {
125*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_QUANT_EPSILON = 1,
126*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_QUANT_ONCE,
127*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_QUANT_OPT,
128*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_QUANT_MULT,
129*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_QUANT_PLUS,
130*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_QUANT_ONCEONLY,
131*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_QUANT_ALL,
132*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_QUANT_RANGE
133*7c568831SAndroid Build Coastguard Worker } xmlRegQuantType;
134*7c568831SAndroid Build Coastguard Worker 
135*7c568831SAndroid Build Coastguard Worker typedef enum {
136*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_START_STATE = 1,
137*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_FINAL_STATE,
138*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_TRANS_STATE,
139*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_SINK_STATE,
140*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_UNREACH_STATE
141*7c568831SAndroid Build Coastguard Worker } xmlRegStateType;
142*7c568831SAndroid Build Coastguard Worker 
143*7c568831SAndroid Build Coastguard Worker typedef enum {
144*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_MARK_NORMAL = 0,
145*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_MARK_START,
146*7c568831SAndroid Build Coastguard Worker     XML_REGEXP_MARK_VISITED
147*7c568831SAndroid Build Coastguard Worker } xmlRegMarkedType;
148*7c568831SAndroid Build Coastguard Worker 
149*7c568831SAndroid Build Coastguard Worker typedef struct _xmlRegRange xmlRegRange;
150*7c568831SAndroid Build Coastguard Worker typedef xmlRegRange *xmlRegRangePtr;
151*7c568831SAndroid Build Coastguard Worker 
152*7c568831SAndroid Build Coastguard Worker struct _xmlRegRange {
153*7c568831SAndroid Build Coastguard Worker     int neg;		/* 0 normal, 1 not, 2 exclude */
154*7c568831SAndroid Build Coastguard Worker     xmlRegAtomType type;
155*7c568831SAndroid Build Coastguard Worker     int start;
156*7c568831SAndroid Build Coastguard Worker     int end;
157*7c568831SAndroid Build Coastguard Worker     xmlChar *blockName;
158*7c568831SAndroid Build Coastguard Worker };
159*7c568831SAndroid Build Coastguard Worker 
160*7c568831SAndroid Build Coastguard Worker typedef struct _xmlRegAtom xmlRegAtom;
161*7c568831SAndroid Build Coastguard Worker typedef xmlRegAtom *xmlRegAtomPtr;
162*7c568831SAndroid Build Coastguard Worker 
163*7c568831SAndroid Build Coastguard Worker typedef struct _xmlAutomataState xmlRegState;
164*7c568831SAndroid Build Coastguard Worker typedef xmlRegState *xmlRegStatePtr;
165*7c568831SAndroid Build Coastguard Worker 
166*7c568831SAndroid Build Coastguard Worker struct _xmlRegAtom {
167*7c568831SAndroid Build Coastguard Worker     int no;
168*7c568831SAndroid Build Coastguard Worker     xmlRegAtomType type;
169*7c568831SAndroid Build Coastguard Worker     xmlRegQuantType quant;
170*7c568831SAndroid Build Coastguard Worker     int min;
171*7c568831SAndroid Build Coastguard Worker     int max;
172*7c568831SAndroid Build Coastguard Worker 
173*7c568831SAndroid Build Coastguard Worker     void *valuep;
174*7c568831SAndroid Build Coastguard Worker     void *valuep2;
175*7c568831SAndroid Build Coastguard Worker     int neg;
176*7c568831SAndroid Build Coastguard Worker     int codepoint;
177*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr start;
178*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr start0;
179*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr stop;
180*7c568831SAndroid Build Coastguard Worker     int maxRanges;
181*7c568831SAndroid Build Coastguard Worker     int nbRanges;
182*7c568831SAndroid Build Coastguard Worker     xmlRegRangePtr *ranges;
183*7c568831SAndroid Build Coastguard Worker     void *data;
184*7c568831SAndroid Build Coastguard Worker };
185*7c568831SAndroid Build Coastguard Worker 
186*7c568831SAndroid Build Coastguard Worker typedef struct _xmlRegCounter xmlRegCounter;
187*7c568831SAndroid Build Coastguard Worker typedef xmlRegCounter *xmlRegCounterPtr;
188*7c568831SAndroid Build Coastguard Worker 
189*7c568831SAndroid Build Coastguard Worker struct _xmlRegCounter {
190*7c568831SAndroid Build Coastguard Worker     int min;
191*7c568831SAndroid Build Coastguard Worker     int max;
192*7c568831SAndroid Build Coastguard Worker };
193*7c568831SAndroid Build Coastguard Worker 
194*7c568831SAndroid Build Coastguard Worker typedef struct _xmlRegTrans xmlRegTrans;
195*7c568831SAndroid Build Coastguard Worker typedef xmlRegTrans *xmlRegTransPtr;
196*7c568831SAndroid Build Coastguard Worker 
197*7c568831SAndroid Build Coastguard Worker struct _xmlRegTrans {
198*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
199*7c568831SAndroid Build Coastguard Worker     int to;
200*7c568831SAndroid Build Coastguard Worker     int counter;
201*7c568831SAndroid Build Coastguard Worker     int count;
202*7c568831SAndroid Build Coastguard Worker     int nd;
203*7c568831SAndroid Build Coastguard Worker };
204*7c568831SAndroid Build Coastguard Worker 
205*7c568831SAndroid Build Coastguard Worker struct _xmlAutomataState {
206*7c568831SAndroid Build Coastguard Worker     xmlRegStateType type;
207*7c568831SAndroid Build Coastguard Worker     xmlRegMarkedType mark;
208*7c568831SAndroid Build Coastguard Worker     xmlRegMarkedType markd;
209*7c568831SAndroid Build Coastguard Worker     xmlRegMarkedType reached;
210*7c568831SAndroid Build Coastguard Worker     int no;
211*7c568831SAndroid Build Coastguard Worker     int maxTrans;
212*7c568831SAndroid Build Coastguard Worker     int nbTrans;
213*7c568831SAndroid Build Coastguard Worker     xmlRegTrans *trans;
214*7c568831SAndroid Build Coastguard Worker     /*  knowing states pointing to us can speed things up */
215*7c568831SAndroid Build Coastguard Worker     int maxTransTo;
216*7c568831SAndroid Build Coastguard Worker     int nbTransTo;
217*7c568831SAndroid Build Coastguard Worker     int *transTo;
218*7c568831SAndroid Build Coastguard Worker };
219*7c568831SAndroid Build Coastguard Worker 
220*7c568831SAndroid Build Coastguard Worker typedef struct _xmlAutomata xmlRegParserCtxt;
221*7c568831SAndroid Build Coastguard Worker typedef xmlRegParserCtxt *xmlRegParserCtxtPtr;
222*7c568831SAndroid Build Coastguard Worker 
223*7c568831SAndroid Build Coastguard Worker #define AM_AUTOMATA_RNG 1
224*7c568831SAndroid Build Coastguard Worker 
225*7c568831SAndroid Build Coastguard Worker struct _xmlAutomata {
226*7c568831SAndroid Build Coastguard Worker     xmlChar *string;
227*7c568831SAndroid Build Coastguard Worker     xmlChar *cur;
228*7c568831SAndroid Build Coastguard Worker 
229*7c568831SAndroid Build Coastguard Worker     int error;
230*7c568831SAndroid Build Coastguard Worker     int neg;
231*7c568831SAndroid Build Coastguard Worker 
232*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr start;
233*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr end;
234*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr state;
235*7c568831SAndroid Build Coastguard Worker 
236*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
237*7c568831SAndroid Build Coastguard Worker 
238*7c568831SAndroid Build Coastguard Worker     int maxAtoms;
239*7c568831SAndroid Build Coastguard Worker     int nbAtoms;
240*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr *atoms;
241*7c568831SAndroid Build Coastguard Worker 
242*7c568831SAndroid Build Coastguard Worker     int maxStates;
243*7c568831SAndroid Build Coastguard Worker     int nbStates;
244*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr *states;
245*7c568831SAndroid Build Coastguard Worker 
246*7c568831SAndroid Build Coastguard Worker     int maxCounters;
247*7c568831SAndroid Build Coastguard Worker     int nbCounters;
248*7c568831SAndroid Build Coastguard Worker     xmlRegCounter *counters;
249*7c568831SAndroid Build Coastguard Worker 
250*7c568831SAndroid Build Coastguard Worker     int determinist;
251*7c568831SAndroid Build Coastguard Worker     int negs;
252*7c568831SAndroid Build Coastguard Worker     int flags;
253*7c568831SAndroid Build Coastguard Worker 
254*7c568831SAndroid Build Coastguard Worker     int depth;
255*7c568831SAndroid Build Coastguard Worker };
256*7c568831SAndroid Build Coastguard Worker 
257*7c568831SAndroid Build Coastguard Worker struct _xmlRegexp {
258*7c568831SAndroid Build Coastguard Worker     xmlChar *string;
259*7c568831SAndroid Build Coastguard Worker     int nbStates;
260*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr *states;
261*7c568831SAndroid Build Coastguard Worker     int nbAtoms;
262*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr *atoms;
263*7c568831SAndroid Build Coastguard Worker     int nbCounters;
264*7c568831SAndroid Build Coastguard Worker     xmlRegCounter *counters;
265*7c568831SAndroid Build Coastguard Worker     int determinist;
266*7c568831SAndroid Build Coastguard Worker     int flags;
267*7c568831SAndroid Build Coastguard Worker     /*
268*7c568831SAndroid Build Coastguard Worker      * That's the compact form for determinists automatas
269*7c568831SAndroid Build Coastguard Worker      */
270*7c568831SAndroid Build Coastguard Worker     int nbstates;
271*7c568831SAndroid Build Coastguard Worker     int *compact;
272*7c568831SAndroid Build Coastguard Worker     void **transdata;
273*7c568831SAndroid Build Coastguard Worker     int nbstrings;
274*7c568831SAndroid Build Coastguard Worker     xmlChar **stringMap;
275*7c568831SAndroid Build Coastguard Worker };
276*7c568831SAndroid Build Coastguard Worker 
277*7c568831SAndroid Build Coastguard Worker typedef struct _xmlRegExecRollback xmlRegExecRollback;
278*7c568831SAndroid Build Coastguard Worker typedef xmlRegExecRollback *xmlRegExecRollbackPtr;
279*7c568831SAndroid Build Coastguard Worker 
280*7c568831SAndroid Build Coastguard Worker struct _xmlRegExecRollback {
281*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr state;/* the current state */
282*7c568831SAndroid Build Coastguard Worker     int index;		/* the index in the input stack */
283*7c568831SAndroid Build Coastguard Worker     int nextbranch;	/* the next transition to explore in that state */
284*7c568831SAndroid Build Coastguard Worker     int *counts;	/* save the automata state if it has some */
285*7c568831SAndroid Build Coastguard Worker };
286*7c568831SAndroid Build Coastguard Worker 
287*7c568831SAndroid Build Coastguard Worker typedef struct _xmlRegInputToken xmlRegInputToken;
288*7c568831SAndroid Build Coastguard Worker typedef xmlRegInputToken *xmlRegInputTokenPtr;
289*7c568831SAndroid Build Coastguard Worker 
290*7c568831SAndroid Build Coastguard Worker struct _xmlRegInputToken {
291*7c568831SAndroid Build Coastguard Worker     xmlChar *value;
292*7c568831SAndroid Build Coastguard Worker     void *data;
293*7c568831SAndroid Build Coastguard Worker };
294*7c568831SAndroid Build Coastguard Worker 
295*7c568831SAndroid Build Coastguard Worker struct _xmlRegExecCtxt {
296*7c568831SAndroid Build Coastguard Worker     int status;		/* execution status != 0 indicate an error */
297*7c568831SAndroid Build Coastguard Worker     int determinist;	/* did we find an indeterministic behaviour */
298*7c568831SAndroid Build Coastguard Worker     xmlRegexpPtr comp;	/* the compiled regexp */
299*7c568831SAndroid Build Coastguard Worker     xmlRegExecCallbacks callback;
300*7c568831SAndroid Build Coastguard Worker     void *data;
301*7c568831SAndroid Build Coastguard Worker 
302*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr state;/* the current state */
303*7c568831SAndroid Build Coastguard Worker     int transno;	/* the current transition on that state */
304*7c568831SAndroid Build Coastguard Worker     int transcount;	/* the number of chars in char counted transitions */
305*7c568831SAndroid Build Coastguard Worker 
306*7c568831SAndroid Build Coastguard Worker     /*
307*7c568831SAndroid Build Coastguard Worker      * A stack of rollback states
308*7c568831SAndroid Build Coastguard Worker      */
309*7c568831SAndroid Build Coastguard Worker     int maxRollbacks;
310*7c568831SAndroid Build Coastguard Worker     int nbRollbacks;
311*7c568831SAndroid Build Coastguard Worker     xmlRegExecRollback *rollbacks;
312*7c568831SAndroid Build Coastguard Worker 
313*7c568831SAndroid Build Coastguard Worker     /*
314*7c568831SAndroid Build Coastguard Worker      * The state of the automata if any
315*7c568831SAndroid Build Coastguard Worker      */
316*7c568831SAndroid Build Coastguard Worker     int *counts;
317*7c568831SAndroid Build Coastguard Worker 
318*7c568831SAndroid Build Coastguard Worker     /*
319*7c568831SAndroid Build Coastguard Worker      * The input stack
320*7c568831SAndroid Build Coastguard Worker      */
321*7c568831SAndroid Build Coastguard Worker     int inputStackMax;
322*7c568831SAndroid Build Coastguard Worker     int inputStackNr;
323*7c568831SAndroid Build Coastguard Worker     int index;
324*7c568831SAndroid Build Coastguard Worker     int *charStack;
325*7c568831SAndroid Build Coastguard Worker     const xmlChar *inputString; /* when operating on characters */
326*7c568831SAndroid Build Coastguard Worker     xmlRegInputTokenPtr inputStack;/* when operating on strings */
327*7c568831SAndroid Build Coastguard Worker 
328*7c568831SAndroid Build Coastguard Worker     /*
329*7c568831SAndroid Build Coastguard Worker      * error handling
330*7c568831SAndroid Build Coastguard Worker      */
331*7c568831SAndroid Build Coastguard Worker     int errStateNo;		/* the error state number */
332*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr errState;    /* the error state */
333*7c568831SAndroid Build Coastguard Worker     xmlChar *errString;		/* the string raising the error */
334*7c568831SAndroid Build Coastguard Worker     int *errCounts;		/* counters at the error state */
335*7c568831SAndroid Build Coastguard Worker     int nbPush;
336*7c568831SAndroid Build Coastguard Worker };
337*7c568831SAndroid Build Coastguard Worker 
338*7c568831SAndroid Build Coastguard Worker #define REGEXP_ALL_COUNTER	0x123456
339*7c568831SAndroid Build Coastguard Worker #define REGEXP_ALL_LAX_COUNTER	0x123457
340*7c568831SAndroid Build Coastguard Worker 
341*7c568831SAndroid Build Coastguard Worker static void xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top);
342*7c568831SAndroid Build Coastguard Worker static void xmlRegFreeState(xmlRegStatePtr state);
343*7c568831SAndroid Build Coastguard Worker static void xmlRegFreeAtom(xmlRegAtomPtr atom);
344*7c568831SAndroid Build Coastguard Worker static int xmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr);
345*7c568831SAndroid Build Coastguard Worker static int xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint);
346*7c568831SAndroid Build Coastguard Worker static int xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint,
347*7c568831SAndroid Build Coastguard Worker                   int neg, int start, int end, const xmlChar *blockName);
348*7c568831SAndroid Build Coastguard Worker 
349*7c568831SAndroid Build Coastguard Worker /************************************************************************
350*7c568831SAndroid Build Coastguard Worker  *									*
351*7c568831SAndroid Build Coastguard Worker  *		Regexp memory error handler				*
352*7c568831SAndroid Build Coastguard Worker  *									*
353*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
354*7c568831SAndroid Build Coastguard Worker /**
355*7c568831SAndroid Build Coastguard Worker  * xmlRegexpErrMemory:
356*7c568831SAndroid Build Coastguard Worker  * @extra:  extra information
357*7c568831SAndroid Build Coastguard Worker  *
358*7c568831SAndroid Build Coastguard Worker  * Handle an out of memory condition
359*7c568831SAndroid Build Coastguard Worker  */
360*7c568831SAndroid Build Coastguard Worker static void
xmlRegexpErrMemory(xmlRegParserCtxtPtr ctxt)361*7c568831SAndroid Build Coastguard Worker xmlRegexpErrMemory(xmlRegParserCtxtPtr ctxt)
362*7c568831SAndroid Build Coastguard Worker {
363*7c568831SAndroid Build Coastguard Worker     if (ctxt != NULL)
364*7c568831SAndroid Build Coastguard Worker         ctxt->error = XML_ERR_NO_MEMORY;
365*7c568831SAndroid Build Coastguard Worker 
366*7c568831SAndroid Build Coastguard Worker     xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_REGEXP, NULL);
367*7c568831SAndroid Build Coastguard Worker }
368*7c568831SAndroid Build Coastguard Worker 
369*7c568831SAndroid Build Coastguard Worker /**
370*7c568831SAndroid Build Coastguard Worker  * xmlRegexpErrCompile:
371*7c568831SAndroid Build Coastguard Worker  * @extra:  extra information
372*7c568831SAndroid Build Coastguard Worker  *
373*7c568831SAndroid Build Coastguard Worker  * Handle a compilation failure
374*7c568831SAndroid Build Coastguard Worker  */
375*7c568831SAndroid Build Coastguard Worker static void
xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt,const char * extra)376*7c568831SAndroid Build Coastguard Worker xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const char *extra)
377*7c568831SAndroid Build Coastguard Worker {
378*7c568831SAndroid Build Coastguard Worker     const char *regexp = NULL;
379*7c568831SAndroid Build Coastguard Worker     int idx = 0;
380*7c568831SAndroid Build Coastguard Worker     int res;
381*7c568831SAndroid Build Coastguard Worker 
382*7c568831SAndroid Build Coastguard Worker     if (ctxt != NULL) {
383*7c568831SAndroid Build Coastguard Worker         regexp = (const char *) ctxt->string;
384*7c568831SAndroid Build Coastguard Worker 	idx = ctxt->cur - ctxt->string;
385*7c568831SAndroid Build Coastguard Worker 	ctxt->error = XML_REGEXP_COMPILE_ERROR;
386*7c568831SAndroid Build Coastguard Worker     }
387*7c568831SAndroid Build Coastguard Worker 
388*7c568831SAndroid Build Coastguard Worker     res = xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP,
389*7c568831SAndroid Build Coastguard Worker                         XML_REGEXP_COMPILE_ERROR, XML_ERR_FATAL,
390*7c568831SAndroid Build Coastguard Worker                         NULL, 0, extra, regexp, NULL, idx, 0,
391*7c568831SAndroid Build Coastguard Worker                         "failed to compile: %s\n", extra);
392*7c568831SAndroid Build Coastguard Worker     if (res < 0)
393*7c568831SAndroid Build Coastguard Worker         xmlRegexpErrMemory(ctxt);
394*7c568831SAndroid Build Coastguard Worker }
395*7c568831SAndroid Build Coastguard Worker 
396*7c568831SAndroid Build Coastguard Worker /************************************************************************
397*7c568831SAndroid Build Coastguard Worker  *									*
398*7c568831SAndroid Build Coastguard Worker  *			Allocation/Deallocation				*
399*7c568831SAndroid Build Coastguard Worker  *									*
400*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
401*7c568831SAndroid Build Coastguard Worker 
402*7c568831SAndroid Build Coastguard Worker static int xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt);
403*7c568831SAndroid Build Coastguard Worker 
404*7c568831SAndroid Build Coastguard Worker /**
405*7c568831SAndroid Build Coastguard Worker  * xmlRegCalloc2:
406*7c568831SAndroid Build Coastguard Worker  * @dim1:  size of first dimension
407*7c568831SAndroid Build Coastguard Worker  * @dim2:  size of second dimension
408*7c568831SAndroid Build Coastguard Worker  * @elemSize:  size of element
409*7c568831SAndroid Build Coastguard Worker  *
410*7c568831SAndroid Build Coastguard Worker  * Allocate a two-dimensional array and set all elements to zero.
411*7c568831SAndroid Build Coastguard Worker  *
412*7c568831SAndroid Build Coastguard Worker  * Returns the new array or NULL in case of error.
413*7c568831SAndroid Build Coastguard Worker  */
414*7c568831SAndroid Build Coastguard Worker static void*
xmlRegCalloc2(size_t dim1,size_t dim2,size_t elemSize)415*7c568831SAndroid Build Coastguard Worker xmlRegCalloc2(size_t dim1, size_t dim2, size_t elemSize) {
416*7c568831SAndroid Build Coastguard Worker     size_t totalSize;
417*7c568831SAndroid Build Coastguard Worker     void *ret;
418*7c568831SAndroid Build Coastguard Worker 
419*7c568831SAndroid Build Coastguard Worker     /* Check for overflow */
420*7c568831SAndroid Build Coastguard Worker     if ((dim2 == 0) || (elemSize == 0) ||
421*7c568831SAndroid Build Coastguard Worker         (dim1 > SIZE_MAX / dim2 / elemSize))
422*7c568831SAndroid Build Coastguard Worker         return (NULL);
423*7c568831SAndroid Build Coastguard Worker     totalSize = dim1 * dim2 * elemSize;
424*7c568831SAndroid Build Coastguard Worker     ret = xmlMalloc(totalSize);
425*7c568831SAndroid Build Coastguard Worker     if (ret != NULL)
426*7c568831SAndroid Build Coastguard Worker         memset(ret, 0, totalSize);
427*7c568831SAndroid Build Coastguard Worker     return (ret);
428*7c568831SAndroid Build Coastguard Worker }
429*7c568831SAndroid Build Coastguard Worker 
430*7c568831SAndroid Build Coastguard Worker /**
431*7c568831SAndroid Build Coastguard Worker  * xmlRegEpxFromParse:
432*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the parser context used to build it
433*7c568831SAndroid Build Coastguard Worker  *
434*7c568831SAndroid Build Coastguard Worker  * Allocate a new regexp and fill it with the result from the parser
435*7c568831SAndroid Build Coastguard Worker  *
436*7c568831SAndroid Build Coastguard Worker  * Returns the new regexp or NULL in case of error
437*7c568831SAndroid Build Coastguard Worker  */
438*7c568831SAndroid Build Coastguard Worker static xmlRegexpPtr
xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt)439*7c568831SAndroid Build Coastguard Worker xmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
440*7c568831SAndroid Build Coastguard Worker     xmlRegexpPtr ret;
441*7c568831SAndroid Build Coastguard Worker 
442*7c568831SAndroid Build Coastguard Worker     ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp));
443*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
444*7c568831SAndroid Build Coastguard Worker 	xmlRegexpErrMemory(ctxt);
445*7c568831SAndroid Build Coastguard Worker 	return(NULL);
446*7c568831SAndroid Build Coastguard Worker     }
447*7c568831SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlRegexp));
448*7c568831SAndroid Build Coastguard Worker     ret->string = ctxt->string;
449*7c568831SAndroid Build Coastguard Worker     ret->nbStates = ctxt->nbStates;
450*7c568831SAndroid Build Coastguard Worker     ret->states = ctxt->states;
451*7c568831SAndroid Build Coastguard Worker     ret->nbAtoms = ctxt->nbAtoms;
452*7c568831SAndroid Build Coastguard Worker     ret->atoms = ctxt->atoms;
453*7c568831SAndroid Build Coastguard Worker     ret->nbCounters = ctxt->nbCounters;
454*7c568831SAndroid Build Coastguard Worker     ret->counters = ctxt->counters;
455*7c568831SAndroid Build Coastguard Worker     ret->determinist = ctxt->determinist;
456*7c568831SAndroid Build Coastguard Worker     ret->flags = ctxt->flags;
457*7c568831SAndroid Build Coastguard Worker     if (ret->determinist == -1) {
458*7c568831SAndroid Build Coastguard Worker         if (xmlRegexpIsDeterminist(ret) < 0) {
459*7c568831SAndroid Build Coastguard Worker             xmlRegexpErrMemory(ctxt);
460*7c568831SAndroid Build Coastguard Worker             xmlFree(ret);
461*7c568831SAndroid Build Coastguard Worker             return(NULL);
462*7c568831SAndroid Build Coastguard Worker         }
463*7c568831SAndroid Build Coastguard Worker     }
464*7c568831SAndroid Build Coastguard Worker 
465*7c568831SAndroid Build Coastguard Worker     if ((ret->determinist != 0) &&
466*7c568831SAndroid Build Coastguard Worker 	(ret->nbCounters == 0) &&
467*7c568831SAndroid Build Coastguard Worker 	(ctxt->negs == 0) &&
468*7c568831SAndroid Build Coastguard Worker 	(ret->atoms != NULL) &&
469*7c568831SAndroid Build Coastguard Worker 	(ret->atoms[0] != NULL) &&
470*7c568831SAndroid Build Coastguard Worker 	(ret->atoms[0]->type == XML_REGEXP_STRING)) {
471*7c568831SAndroid Build Coastguard Worker 	int i, j, nbstates = 0, nbatoms = 0;
472*7c568831SAndroid Build Coastguard Worker 	int *stateRemap;
473*7c568831SAndroid Build Coastguard Worker 	int *stringRemap;
474*7c568831SAndroid Build Coastguard Worker 	int *transitions;
475*7c568831SAndroid Build Coastguard Worker 	void **transdata;
476*7c568831SAndroid Build Coastguard Worker 	xmlChar **stringMap;
477*7c568831SAndroid Build Coastguard Worker         xmlChar *value;
478*7c568831SAndroid Build Coastguard Worker 
479*7c568831SAndroid Build Coastguard Worker 	/*
480*7c568831SAndroid Build Coastguard Worker 	 * Switch to a compact representation
481*7c568831SAndroid Build Coastguard Worker 	 * 1/ counting the effective number of states left
482*7c568831SAndroid Build Coastguard Worker 	 * 2/ counting the unique number of atoms, and check that
483*7c568831SAndroid Build Coastguard Worker 	 *    they are all of the string type
484*7c568831SAndroid Build Coastguard Worker 	 * 3/ build a table state x atom for the transitions
485*7c568831SAndroid Build Coastguard Worker 	 */
486*7c568831SAndroid Build Coastguard Worker 
487*7c568831SAndroid Build Coastguard Worker 	stateRemap = xmlMalloc(ret->nbStates * sizeof(int));
488*7c568831SAndroid Build Coastguard Worker 	if (stateRemap == NULL) {
489*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
490*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret);
491*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
492*7c568831SAndroid Build Coastguard Worker 	}
493*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ret->nbStates;i++) {
494*7c568831SAndroid Build Coastguard Worker 	    if (ret->states[i] != NULL) {
495*7c568831SAndroid Build Coastguard Worker 		stateRemap[i] = nbstates;
496*7c568831SAndroid Build Coastguard Worker 		nbstates++;
497*7c568831SAndroid Build Coastguard Worker 	    } else {
498*7c568831SAndroid Build Coastguard Worker 		stateRemap[i] = -1;
499*7c568831SAndroid Build Coastguard Worker 	    }
500*7c568831SAndroid Build Coastguard Worker 	}
501*7c568831SAndroid Build Coastguard Worker 	stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *));
502*7c568831SAndroid Build Coastguard Worker 	if (stringMap == NULL) {
503*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
504*7c568831SAndroid Build Coastguard Worker 	    xmlFree(stateRemap);
505*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret);
506*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
507*7c568831SAndroid Build Coastguard Worker 	}
508*7c568831SAndroid Build Coastguard Worker 	stringRemap = xmlMalloc(ret->nbAtoms * sizeof(int));
509*7c568831SAndroid Build Coastguard Worker 	if (stringRemap == NULL) {
510*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
511*7c568831SAndroid Build Coastguard Worker 	    xmlFree(stringMap);
512*7c568831SAndroid Build Coastguard Worker 	    xmlFree(stateRemap);
513*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret);
514*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
515*7c568831SAndroid Build Coastguard Worker 	}
516*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ret->nbAtoms;i++) {
517*7c568831SAndroid Build Coastguard Worker 	    if ((ret->atoms[i]->type == XML_REGEXP_STRING) &&
518*7c568831SAndroid Build Coastguard Worker 		(ret->atoms[i]->quant == XML_REGEXP_QUANT_ONCE)) {
519*7c568831SAndroid Build Coastguard Worker 		value = ret->atoms[i]->valuep;
520*7c568831SAndroid Build Coastguard Worker                 for (j = 0;j < nbatoms;j++) {
521*7c568831SAndroid Build Coastguard Worker 		    if (xmlStrEqual(stringMap[j], value)) {
522*7c568831SAndroid Build Coastguard Worker 			stringRemap[i] = j;
523*7c568831SAndroid Build Coastguard Worker 			break;
524*7c568831SAndroid Build Coastguard Worker 		    }
525*7c568831SAndroid Build Coastguard Worker 		}
526*7c568831SAndroid Build Coastguard Worker 		if (j >= nbatoms) {
527*7c568831SAndroid Build Coastguard Worker 		    stringRemap[i] = nbatoms;
528*7c568831SAndroid Build Coastguard Worker 		    stringMap[nbatoms] = xmlStrdup(value);
529*7c568831SAndroid Build Coastguard Worker 		    if (stringMap[nbatoms] == NULL) {
530*7c568831SAndroid Build Coastguard Worker 			for (i = 0;i < nbatoms;i++)
531*7c568831SAndroid Build Coastguard Worker 			    xmlFree(stringMap[i]);
532*7c568831SAndroid Build Coastguard Worker 			xmlFree(stringRemap);
533*7c568831SAndroid Build Coastguard Worker 			xmlFree(stringMap);
534*7c568831SAndroid Build Coastguard Worker 			xmlFree(stateRemap);
535*7c568831SAndroid Build Coastguard Worker 			xmlFree(ret);
536*7c568831SAndroid Build Coastguard Worker 			return(NULL);
537*7c568831SAndroid Build Coastguard Worker 		    }
538*7c568831SAndroid Build Coastguard Worker 		    nbatoms++;
539*7c568831SAndroid Build Coastguard Worker 		}
540*7c568831SAndroid Build Coastguard Worker 	    } else {
541*7c568831SAndroid Build Coastguard Worker 		xmlFree(stateRemap);
542*7c568831SAndroid Build Coastguard Worker 		xmlFree(stringRemap);
543*7c568831SAndroid Build Coastguard Worker 		for (i = 0;i < nbatoms;i++)
544*7c568831SAndroid Build Coastguard Worker 		    xmlFree(stringMap[i]);
545*7c568831SAndroid Build Coastguard Worker 		xmlFree(stringMap);
546*7c568831SAndroid Build Coastguard Worker 		xmlFree(ret);
547*7c568831SAndroid Build Coastguard Worker 		return(NULL);
548*7c568831SAndroid Build Coastguard Worker 	    }
549*7c568831SAndroid Build Coastguard Worker 	}
550*7c568831SAndroid Build Coastguard Worker 	transitions = (int *) xmlRegCalloc2(nbstates + 1, nbatoms + 1,
551*7c568831SAndroid Build Coastguard Worker                                             sizeof(int));
552*7c568831SAndroid Build Coastguard Worker 	if (transitions == NULL) {
553*7c568831SAndroid Build Coastguard Worker 	    xmlFree(stateRemap);
554*7c568831SAndroid Build Coastguard Worker 	    xmlFree(stringRemap);
555*7c568831SAndroid Build Coastguard Worker             for (i = 0;i < nbatoms;i++)
556*7c568831SAndroid Build Coastguard Worker 		xmlFree(stringMap[i]);
557*7c568831SAndroid Build Coastguard Worker 	    xmlFree(stringMap);
558*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret);
559*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
560*7c568831SAndroid Build Coastguard Worker 	}
561*7c568831SAndroid Build Coastguard Worker 
562*7c568831SAndroid Build Coastguard Worker 	/*
563*7c568831SAndroid Build Coastguard Worker 	 * Allocate the transition table. The first entry for each
564*7c568831SAndroid Build Coastguard Worker 	 * state corresponds to the state type.
565*7c568831SAndroid Build Coastguard Worker 	 */
566*7c568831SAndroid Build Coastguard Worker 	transdata = NULL;
567*7c568831SAndroid Build Coastguard Worker 
568*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ret->nbStates;i++) {
569*7c568831SAndroid Build Coastguard Worker 	    int stateno, atomno, targetno, prev;
570*7c568831SAndroid Build Coastguard Worker 	    xmlRegStatePtr state;
571*7c568831SAndroid Build Coastguard Worker 	    xmlRegTransPtr trans;
572*7c568831SAndroid Build Coastguard Worker 
573*7c568831SAndroid Build Coastguard Worker 	    stateno = stateRemap[i];
574*7c568831SAndroid Build Coastguard Worker 	    if (stateno == -1)
575*7c568831SAndroid Build Coastguard Worker 		continue;
576*7c568831SAndroid Build Coastguard Worker 	    state = ret->states[i];
577*7c568831SAndroid Build Coastguard Worker 
578*7c568831SAndroid Build Coastguard Worker 	    transitions[stateno * (nbatoms + 1)] = state->type;
579*7c568831SAndroid Build Coastguard Worker 
580*7c568831SAndroid Build Coastguard Worker 	    for (j = 0;j < state->nbTrans;j++) {
581*7c568831SAndroid Build Coastguard Worker 		trans = &(state->trans[j]);
582*7c568831SAndroid Build Coastguard Worker 		if ((trans->to < 0) || (trans->atom == NULL))
583*7c568831SAndroid Build Coastguard Worker 		    continue;
584*7c568831SAndroid Build Coastguard Worker                 atomno = stringRemap[trans->atom->no];
585*7c568831SAndroid Build Coastguard Worker 		if ((trans->atom->data != NULL) && (transdata == NULL)) {
586*7c568831SAndroid Build Coastguard Worker 		    transdata = (void **) xmlRegCalloc2(nbstates, nbatoms,
587*7c568831SAndroid Build Coastguard Worker 			                                sizeof(void *));
588*7c568831SAndroid Build Coastguard Worker 		    if (transdata == NULL) {
589*7c568831SAndroid Build Coastguard Worker 			xmlRegexpErrMemory(ctxt);
590*7c568831SAndroid Build Coastguard Worker 			break;
591*7c568831SAndroid Build Coastguard Worker 		    }
592*7c568831SAndroid Build Coastguard Worker 		}
593*7c568831SAndroid Build Coastguard Worker 		targetno = stateRemap[trans->to];
594*7c568831SAndroid Build Coastguard Worker 		/*
595*7c568831SAndroid Build Coastguard Worker 		 * if the same atom can generate transitions to 2 different
596*7c568831SAndroid Build Coastguard Worker 		 * states then it means the automata is not deterministic and
597*7c568831SAndroid Build Coastguard Worker 		 * the compact form can't be used !
598*7c568831SAndroid Build Coastguard Worker 		 */
599*7c568831SAndroid Build Coastguard Worker 		prev = transitions[stateno * (nbatoms + 1) + atomno + 1];
600*7c568831SAndroid Build Coastguard Worker 		if (prev != 0) {
601*7c568831SAndroid Build Coastguard Worker 		    if (prev != targetno + 1) {
602*7c568831SAndroid Build Coastguard Worker 			ret->determinist = 0;
603*7c568831SAndroid Build Coastguard Worker 			if (transdata != NULL)
604*7c568831SAndroid Build Coastguard Worker 			    xmlFree(transdata);
605*7c568831SAndroid Build Coastguard Worker 			xmlFree(transitions);
606*7c568831SAndroid Build Coastguard Worker 			xmlFree(stateRemap);
607*7c568831SAndroid Build Coastguard Worker 			xmlFree(stringRemap);
608*7c568831SAndroid Build Coastguard Worker 			for (i = 0;i < nbatoms;i++)
609*7c568831SAndroid Build Coastguard Worker 			    xmlFree(stringMap[i]);
610*7c568831SAndroid Build Coastguard Worker 			xmlFree(stringMap);
611*7c568831SAndroid Build Coastguard Worker 			goto not_determ;
612*7c568831SAndroid Build Coastguard Worker 		    }
613*7c568831SAndroid Build Coastguard Worker 		} else {
614*7c568831SAndroid Build Coastguard Worker 		    transitions[stateno * (nbatoms + 1) + atomno + 1] =
615*7c568831SAndroid Build Coastguard Worker 			targetno + 1; /* to avoid 0 */
616*7c568831SAndroid Build Coastguard Worker 		    if (transdata != NULL)
617*7c568831SAndroid Build Coastguard Worker 			transdata[stateno * nbatoms + atomno] =
618*7c568831SAndroid Build Coastguard Worker 			    trans->atom->data;
619*7c568831SAndroid Build Coastguard Worker 		}
620*7c568831SAndroid Build Coastguard Worker 	    }
621*7c568831SAndroid Build Coastguard Worker 	}
622*7c568831SAndroid Build Coastguard Worker 	ret->determinist = 1;
623*7c568831SAndroid Build Coastguard Worker 	/*
624*7c568831SAndroid Build Coastguard Worker 	 * Cleanup of the old data
625*7c568831SAndroid Build Coastguard Worker 	 */
626*7c568831SAndroid Build Coastguard Worker 	if (ret->states != NULL) {
627*7c568831SAndroid Build Coastguard Worker 	    for (i = 0;i < ret->nbStates;i++)
628*7c568831SAndroid Build Coastguard Worker 		xmlRegFreeState(ret->states[i]);
629*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret->states);
630*7c568831SAndroid Build Coastguard Worker 	}
631*7c568831SAndroid Build Coastguard Worker 	ret->states = NULL;
632*7c568831SAndroid Build Coastguard Worker 	ret->nbStates = 0;
633*7c568831SAndroid Build Coastguard Worker 	if (ret->atoms != NULL) {
634*7c568831SAndroid Build Coastguard Worker 	    for (i = 0;i < ret->nbAtoms;i++)
635*7c568831SAndroid Build Coastguard Worker 		xmlRegFreeAtom(ret->atoms[i]);
636*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret->atoms);
637*7c568831SAndroid Build Coastguard Worker 	}
638*7c568831SAndroid Build Coastguard Worker 	ret->atoms = NULL;
639*7c568831SAndroid Build Coastguard Worker 	ret->nbAtoms = 0;
640*7c568831SAndroid Build Coastguard Worker 
641*7c568831SAndroid Build Coastguard Worker 	ret->compact = transitions;
642*7c568831SAndroid Build Coastguard Worker 	ret->transdata = transdata;
643*7c568831SAndroid Build Coastguard Worker 	ret->stringMap = stringMap;
644*7c568831SAndroid Build Coastguard Worker 	ret->nbstrings = nbatoms;
645*7c568831SAndroid Build Coastguard Worker 	ret->nbstates = nbstates;
646*7c568831SAndroid Build Coastguard Worker 	xmlFree(stateRemap);
647*7c568831SAndroid Build Coastguard Worker 	xmlFree(stringRemap);
648*7c568831SAndroid Build Coastguard Worker     }
649*7c568831SAndroid Build Coastguard Worker not_determ:
650*7c568831SAndroid Build Coastguard Worker     ctxt->string = NULL;
651*7c568831SAndroid Build Coastguard Worker     ctxt->nbStates = 0;
652*7c568831SAndroid Build Coastguard Worker     ctxt->states = NULL;
653*7c568831SAndroid Build Coastguard Worker     ctxt->nbAtoms = 0;
654*7c568831SAndroid Build Coastguard Worker     ctxt->atoms = NULL;
655*7c568831SAndroid Build Coastguard Worker     ctxt->nbCounters = 0;
656*7c568831SAndroid Build Coastguard Worker     ctxt->counters = NULL;
657*7c568831SAndroid Build Coastguard Worker     return(ret);
658*7c568831SAndroid Build Coastguard Worker }
659*7c568831SAndroid Build Coastguard Worker 
660*7c568831SAndroid Build Coastguard Worker /**
661*7c568831SAndroid Build Coastguard Worker  * xmlRegNewParserCtxt:
662*7c568831SAndroid Build Coastguard Worker  * @string:  the string to parse
663*7c568831SAndroid Build Coastguard Worker  *
664*7c568831SAndroid Build Coastguard Worker  * Allocate a new regexp parser context
665*7c568831SAndroid Build Coastguard Worker  *
666*7c568831SAndroid Build Coastguard Worker  * Returns the new context or NULL in case of error
667*7c568831SAndroid Build Coastguard Worker  */
668*7c568831SAndroid Build Coastguard Worker static xmlRegParserCtxtPtr
xmlRegNewParserCtxt(const xmlChar * string)669*7c568831SAndroid Build Coastguard Worker xmlRegNewParserCtxt(const xmlChar *string) {
670*7c568831SAndroid Build Coastguard Worker     xmlRegParserCtxtPtr ret;
671*7c568831SAndroid Build Coastguard Worker 
672*7c568831SAndroid Build Coastguard Worker     ret = (xmlRegParserCtxtPtr) xmlMalloc(sizeof(xmlRegParserCtxt));
673*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
674*7c568831SAndroid Build Coastguard Worker 	return(NULL);
675*7c568831SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlRegParserCtxt));
676*7c568831SAndroid Build Coastguard Worker     if (string != NULL) {
677*7c568831SAndroid Build Coastguard Worker 	ret->string = xmlStrdup(string);
678*7c568831SAndroid Build Coastguard Worker         if (ret->string == NULL) {
679*7c568831SAndroid Build Coastguard Worker             xmlFree(ret);
680*7c568831SAndroid Build Coastguard Worker             return(NULL);
681*7c568831SAndroid Build Coastguard Worker         }
682*7c568831SAndroid Build Coastguard Worker     }
683*7c568831SAndroid Build Coastguard Worker     ret->cur = ret->string;
684*7c568831SAndroid Build Coastguard Worker     ret->neg = 0;
685*7c568831SAndroid Build Coastguard Worker     ret->negs = 0;
686*7c568831SAndroid Build Coastguard Worker     ret->error = 0;
687*7c568831SAndroid Build Coastguard Worker     ret->determinist = -1;
688*7c568831SAndroid Build Coastguard Worker     return(ret);
689*7c568831SAndroid Build Coastguard Worker }
690*7c568831SAndroid Build Coastguard Worker 
691*7c568831SAndroid Build Coastguard Worker /**
692*7c568831SAndroid Build Coastguard Worker  * xmlRegNewRange:
693*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the regexp parser context
694*7c568831SAndroid Build Coastguard Worker  * @neg:  is that negative
695*7c568831SAndroid Build Coastguard Worker  * @type:  the type of range
696*7c568831SAndroid Build Coastguard Worker  * @start:  the start codepoint
697*7c568831SAndroid Build Coastguard Worker  * @end:  the end codepoint
698*7c568831SAndroid Build Coastguard Worker  *
699*7c568831SAndroid Build Coastguard Worker  * Allocate a new regexp range
700*7c568831SAndroid Build Coastguard Worker  *
701*7c568831SAndroid Build Coastguard Worker  * Returns the new range or NULL in case of error
702*7c568831SAndroid Build Coastguard Worker  */
703*7c568831SAndroid Build Coastguard Worker static xmlRegRangePtr
xmlRegNewRange(xmlRegParserCtxtPtr ctxt,int neg,xmlRegAtomType type,int start,int end)704*7c568831SAndroid Build Coastguard Worker xmlRegNewRange(xmlRegParserCtxtPtr ctxt,
705*7c568831SAndroid Build Coastguard Worker 	       int neg, xmlRegAtomType type, int start, int end) {
706*7c568831SAndroid Build Coastguard Worker     xmlRegRangePtr ret;
707*7c568831SAndroid Build Coastguard Worker 
708*7c568831SAndroid Build Coastguard Worker     ret = (xmlRegRangePtr) xmlMalloc(sizeof(xmlRegRange));
709*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
710*7c568831SAndroid Build Coastguard Worker 	xmlRegexpErrMemory(ctxt);
711*7c568831SAndroid Build Coastguard Worker 	return(NULL);
712*7c568831SAndroid Build Coastguard Worker     }
713*7c568831SAndroid Build Coastguard Worker     ret->neg = neg;
714*7c568831SAndroid Build Coastguard Worker     ret->type = type;
715*7c568831SAndroid Build Coastguard Worker     ret->start = start;
716*7c568831SAndroid Build Coastguard Worker     ret->end = end;
717*7c568831SAndroid Build Coastguard Worker     return(ret);
718*7c568831SAndroid Build Coastguard Worker }
719*7c568831SAndroid Build Coastguard Worker 
720*7c568831SAndroid Build Coastguard Worker /**
721*7c568831SAndroid Build Coastguard Worker  * xmlRegFreeRange:
722*7c568831SAndroid Build Coastguard Worker  * @range:  the regexp range
723*7c568831SAndroid Build Coastguard Worker  *
724*7c568831SAndroid Build Coastguard Worker  * Free a regexp range
725*7c568831SAndroid Build Coastguard Worker  */
726*7c568831SAndroid Build Coastguard Worker static void
xmlRegFreeRange(xmlRegRangePtr range)727*7c568831SAndroid Build Coastguard Worker xmlRegFreeRange(xmlRegRangePtr range) {
728*7c568831SAndroid Build Coastguard Worker     if (range == NULL)
729*7c568831SAndroid Build Coastguard Worker 	return;
730*7c568831SAndroid Build Coastguard Worker 
731*7c568831SAndroid Build Coastguard Worker     if (range->blockName != NULL)
732*7c568831SAndroid Build Coastguard Worker 	xmlFree(range->blockName);
733*7c568831SAndroid Build Coastguard Worker     xmlFree(range);
734*7c568831SAndroid Build Coastguard Worker }
735*7c568831SAndroid Build Coastguard Worker 
736*7c568831SAndroid Build Coastguard Worker /**
737*7c568831SAndroid Build Coastguard Worker  * xmlRegCopyRange:
738*7c568831SAndroid Build Coastguard Worker  * @range:  the regexp range
739*7c568831SAndroid Build Coastguard Worker  *
740*7c568831SAndroid Build Coastguard Worker  * Copy a regexp range
741*7c568831SAndroid Build Coastguard Worker  *
742*7c568831SAndroid Build Coastguard Worker  * Returns the new copy or NULL in case of error.
743*7c568831SAndroid Build Coastguard Worker  */
744*7c568831SAndroid Build Coastguard Worker static xmlRegRangePtr
xmlRegCopyRange(xmlRegParserCtxtPtr ctxt,xmlRegRangePtr range)745*7c568831SAndroid Build Coastguard Worker xmlRegCopyRange(xmlRegParserCtxtPtr ctxt, xmlRegRangePtr range) {
746*7c568831SAndroid Build Coastguard Worker     xmlRegRangePtr ret;
747*7c568831SAndroid Build Coastguard Worker 
748*7c568831SAndroid Build Coastguard Worker     if (range == NULL)
749*7c568831SAndroid Build Coastguard Worker 	return(NULL);
750*7c568831SAndroid Build Coastguard Worker 
751*7c568831SAndroid Build Coastguard Worker     ret = xmlRegNewRange(ctxt, range->neg, range->type, range->start,
752*7c568831SAndroid Build Coastguard Worker                          range->end);
753*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
754*7c568831SAndroid Build Coastguard Worker         return(NULL);
755*7c568831SAndroid Build Coastguard Worker     if (range->blockName != NULL) {
756*7c568831SAndroid Build Coastguard Worker 	ret->blockName = xmlStrdup(range->blockName);
757*7c568831SAndroid Build Coastguard Worker 	if (ret->blockName == NULL) {
758*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
759*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeRange(ret);
760*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
761*7c568831SAndroid Build Coastguard Worker 	}
762*7c568831SAndroid Build Coastguard Worker     }
763*7c568831SAndroid Build Coastguard Worker     return(ret);
764*7c568831SAndroid Build Coastguard Worker }
765*7c568831SAndroid Build Coastguard Worker 
766*7c568831SAndroid Build Coastguard Worker /**
767*7c568831SAndroid Build Coastguard Worker  * xmlRegNewAtom:
768*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the regexp parser context
769*7c568831SAndroid Build Coastguard Worker  * @type:  the type of atom
770*7c568831SAndroid Build Coastguard Worker  *
771*7c568831SAndroid Build Coastguard Worker  * Allocate a new atom
772*7c568831SAndroid Build Coastguard Worker  *
773*7c568831SAndroid Build Coastguard Worker  * Returns the new atom or NULL in case of error
774*7c568831SAndroid Build Coastguard Worker  */
775*7c568831SAndroid Build Coastguard Worker static xmlRegAtomPtr
xmlRegNewAtom(xmlRegParserCtxtPtr ctxt,xmlRegAtomType type)776*7c568831SAndroid Build Coastguard Worker xmlRegNewAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomType type) {
777*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr ret;
778*7c568831SAndroid Build Coastguard Worker 
779*7c568831SAndroid Build Coastguard Worker     ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom));
780*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
781*7c568831SAndroid Build Coastguard Worker 	xmlRegexpErrMemory(ctxt);
782*7c568831SAndroid Build Coastguard Worker 	return(NULL);
783*7c568831SAndroid Build Coastguard Worker     }
784*7c568831SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlRegAtom));
785*7c568831SAndroid Build Coastguard Worker     ret->type = type;
786*7c568831SAndroid Build Coastguard Worker     ret->quant = XML_REGEXP_QUANT_ONCE;
787*7c568831SAndroid Build Coastguard Worker     ret->min = 0;
788*7c568831SAndroid Build Coastguard Worker     ret->max = 0;
789*7c568831SAndroid Build Coastguard Worker     return(ret);
790*7c568831SAndroid Build Coastguard Worker }
791*7c568831SAndroid Build Coastguard Worker 
792*7c568831SAndroid Build Coastguard Worker /**
793*7c568831SAndroid Build Coastguard Worker  * xmlRegFreeAtom:
794*7c568831SAndroid Build Coastguard Worker  * @atom:  the regexp atom
795*7c568831SAndroid Build Coastguard Worker  *
796*7c568831SAndroid Build Coastguard Worker  * Free a regexp atom
797*7c568831SAndroid Build Coastguard Worker  */
798*7c568831SAndroid Build Coastguard Worker static void
xmlRegFreeAtom(xmlRegAtomPtr atom)799*7c568831SAndroid Build Coastguard Worker xmlRegFreeAtom(xmlRegAtomPtr atom) {
800*7c568831SAndroid Build Coastguard Worker     int i;
801*7c568831SAndroid Build Coastguard Worker 
802*7c568831SAndroid Build Coastguard Worker     if (atom == NULL)
803*7c568831SAndroid Build Coastguard Worker 	return;
804*7c568831SAndroid Build Coastguard Worker 
805*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < atom->nbRanges;i++)
806*7c568831SAndroid Build Coastguard Worker 	xmlRegFreeRange(atom->ranges[i]);
807*7c568831SAndroid Build Coastguard Worker     if (atom->ranges != NULL)
808*7c568831SAndroid Build Coastguard Worker 	xmlFree(atom->ranges);
809*7c568831SAndroid Build Coastguard Worker     if ((atom->type == XML_REGEXP_STRING) && (atom->valuep != NULL))
810*7c568831SAndroid Build Coastguard Worker 	xmlFree(atom->valuep);
811*7c568831SAndroid Build Coastguard Worker     if ((atom->type == XML_REGEXP_STRING) && (atom->valuep2 != NULL))
812*7c568831SAndroid Build Coastguard Worker 	xmlFree(atom->valuep2);
813*7c568831SAndroid Build Coastguard Worker     if ((atom->type == XML_REGEXP_BLOCK_NAME) && (atom->valuep != NULL))
814*7c568831SAndroid Build Coastguard Worker 	xmlFree(atom->valuep);
815*7c568831SAndroid Build Coastguard Worker     xmlFree(atom);
816*7c568831SAndroid Build Coastguard Worker }
817*7c568831SAndroid Build Coastguard Worker 
818*7c568831SAndroid Build Coastguard Worker /**
819*7c568831SAndroid Build Coastguard Worker  * xmlRegCopyAtom:
820*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the regexp parser context
821*7c568831SAndroid Build Coastguard Worker  * @atom:  the original atom
822*7c568831SAndroid Build Coastguard Worker  *
823*7c568831SAndroid Build Coastguard Worker  * Allocate a new regexp range
824*7c568831SAndroid Build Coastguard Worker  *
825*7c568831SAndroid Build Coastguard Worker  * Returns the new atom or NULL in case of error
826*7c568831SAndroid Build Coastguard Worker  */
827*7c568831SAndroid Build Coastguard Worker static xmlRegAtomPtr
xmlRegCopyAtom(xmlRegParserCtxtPtr ctxt,xmlRegAtomPtr atom)828*7c568831SAndroid Build Coastguard Worker xmlRegCopyAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
829*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr ret;
830*7c568831SAndroid Build Coastguard Worker 
831*7c568831SAndroid Build Coastguard Worker     ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom));
832*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
833*7c568831SAndroid Build Coastguard Worker 	xmlRegexpErrMemory(ctxt);
834*7c568831SAndroid Build Coastguard Worker 	return(NULL);
835*7c568831SAndroid Build Coastguard Worker     }
836*7c568831SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlRegAtom));
837*7c568831SAndroid Build Coastguard Worker     ret->type = atom->type;
838*7c568831SAndroid Build Coastguard Worker     ret->quant = atom->quant;
839*7c568831SAndroid Build Coastguard Worker     ret->min = atom->min;
840*7c568831SAndroid Build Coastguard Worker     ret->max = atom->max;
841*7c568831SAndroid Build Coastguard Worker     if (atom->nbRanges > 0) {
842*7c568831SAndroid Build Coastguard Worker         int i;
843*7c568831SAndroid Build Coastguard Worker 
844*7c568831SAndroid Build Coastguard Worker         ret->ranges = (xmlRegRangePtr *) xmlMalloc(sizeof(xmlRegRangePtr) *
845*7c568831SAndroid Build Coastguard Worker 	                                           atom->nbRanges);
846*7c568831SAndroid Build Coastguard Worker 	if (ret->ranges == NULL) {
847*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
848*7c568831SAndroid Build Coastguard Worker 	    goto error;
849*7c568831SAndroid Build Coastguard Worker 	}
850*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < atom->nbRanges;i++) {
851*7c568831SAndroid Build Coastguard Worker 	    ret->ranges[i] = xmlRegCopyRange(ctxt, atom->ranges[i]);
852*7c568831SAndroid Build Coastguard Worker 	    if (ret->ranges[i] == NULL)
853*7c568831SAndroid Build Coastguard Worker 	        goto error;
854*7c568831SAndroid Build Coastguard Worker 	    ret->nbRanges = i + 1;
855*7c568831SAndroid Build Coastguard Worker 	}
856*7c568831SAndroid Build Coastguard Worker     }
857*7c568831SAndroid Build Coastguard Worker     return(ret);
858*7c568831SAndroid Build Coastguard Worker 
859*7c568831SAndroid Build Coastguard Worker error:
860*7c568831SAndroid Build Coastguard Worker     xmlRegFreeAtom(ret);
861*7c568831SAndroid Build Coastguard Worker     return(NULL);
862*7c568831SAndroid Build Coastguard Worker }
863*7c568831SAndroid Build Coastguard Worker 
864*7c568831SAndroid Build Coastguard Worker static xmlRegStatePtr
xmlRegNewState(xmlRegParserCtxtPtr ctxt)865*7c568831SAndroid Build Coastguard Worker xmlRegNewState(xmlRegParserCtxtPtr ctxt) {
866*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr ret;
867*7c568831SAndroid Build Coastguard Worker 
868*7c568831SAndroid Build Coastguard Worker     ret = (xmlRegStatePtr) xmlMalloc(sizeof(xmlRegState));
869*7c568831SAndroid Build Coastguard Worker     if (ret == NULL) {
870*7c568831SAndroid Build Coastguard Worker 	xmlRegexpErrMemory(ctxt);
871*7c568831SAndroid Build Coastguard Worker 	return(NULL);
872*7c568831SAndroid Build Coastguard Worker     }
873*7c568831SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlRegState));
874*7c568831SAndroid Build Coastguard Worker     ret->type = XML_REGEXP_TRANS_STATE;
875*7c568831SAndroid Build Coastguard Worker     ret->mark = XML_REGEXP_MARK_NORMAL;
876*7c568831SAndroid Build Coastguard Worker     return(ret);
877*7c568831SAndroid Build Coastguard Worker }
878*7c568831SAndroid Build Coastguard Worker 
879*7c568831SAndroid Build Coastguard Worker /**
880*7c568831SAndroid Build Coastguard Worker  * xmlRegFreeState:
881*7c568831SAndroid Build Coastguard Worker  * @state:  the regexp state
882*7c568831SAndroid Build Coastguard Worker  *
883*7c568831SAndroid Build Coastguard Worker  * Free a regexp state
884*7c568831SAndroid Build Coastguard Worker  */
885*7c568831SAndroid Build Coastguard Worker static void
xmlRegFreeState(xmlRegStatePtr state)886*7c568831SAndroid Build Coastguard Worker xmlRegFreeState(xmlRegStatePtr state) {
887*7c568831SAndroid Build Coastguard Worker     if (state == NULL)
888*7c568831SAndroid Build Coastguard Worker 	return;
889*7c568831SAndroid Build Coastguard Worker 
890*7c568831SAndroid Build Coastguard Worker     if (state->trans != NULL)
891*7c568831SAndroid Build Coastguard Worker 	xmlFree(state->trans);
892*7c568831SAndroid Build Coastguard Worker     if (state->transTo != NULL)
893*7c568831SAndroid Build Coastguard Worker 	xmlFree(state->transTo);
894*7c568831SAndroid Build Coastguard Worker     xmlFree(state);
895*7c568831SAndroid Build Coastguard Worker }
896*7c568831SAndroid Build Coastguard Worker 
897*7c568831SAndroid Build Coastguard Worker /**
898*7c568831SAndroid Build Coastguard Worker  * xmlRegFreeParserCtxt:
899*7c568831SAndroid Build Coastguard Worker  * @ctxt:  the regexp parser context
900*7c568831SAndroid Build Coastguard Worker  *
901*7c568831SAndroid Build Coastguard Worker  * Free a regexp parser context
902*7c568831SAndroid Build Coastguard Worker  */
903*7c568831SAndroid Build Coastguard Worker static void
xmlRegFreeParserCtxt(xmlRegParserCtxtPtr ctxt)904*7c568831SAndroid Build Coastguard Worker xmlRegFreeParserCtxt(xmlRegParserCtxtPtr ctxt) {
905*7c568831SAndroid Build Coastguard Worker     int i;
906*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
907*7c568831SAndroid Build Coastguard Worker 	return;
908*7c568831SAndroid Build Coastguard Worker 
909*7c568831SAndroid Build Coastguard Worker     if (ctxt->string != NULL)
910*7c568831SAndroid Build Coastguard Worker 	xmlFree(ctxt->string);
911*7c568831SAndroid Build Coastguard Worker     if (ctxt->states != NULL) {
912*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ctxt->nbStates;i++)
913*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeState(ctxt->states[i]);
914*7c568831SAndroid Build Coastguard Worker 	xmlFree(ctxt->states);
915*7c568831SAndroid Build Coastguard Worker     }
916*7c568831SAndroid Build Coastguard Worker     if (ctxt->atoms != NULL) {
917*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < ctxt->nbAtoms;i++)
918*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeAtom(ctxt->atoms[i]);
919*7c568831SAndroid Build Coastguard Worker 	xmlFree(ctxt->atoms);
920*7c568831SAndroid Build Coastguard Worker     }
921*7c568831SAndroid Build Coastguard Worker     if (ctxt->counters != NULL)
922*7c568831SAndroid Build Coastguard Worker 	xmlFree(ctxt->counters);
923*7c568831SAndroid Build Coastguard Worker     xmlFree(ctxt);
924*7c568831SAndroid Build Coastguard Worker }
925*7c568831SAndroid Build Coastguard Worker 
926*7c568831SAndroid Build Coastguard Worker /************************************************************************
927*7c568831SAndroid Build Coastguard Worker  *									*
928*7c568831SAndroid Build Coastguard Worker  *			Display of Data structures			*
929*7c568831SAndroid Build Coastguard Worker  *									*
930*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
931*7c568831SAndroid Build Coastguard Worker 
932*7c568831SAndroid Build Coastguard Worker static void
xmlRegPrintAtomType(FILE * output,xmlRegAtomType type)933*7c568831SAndroid Build Coastguard Worker xmlRegPrintAtomType(FILE *output, xmlRegAtomType type) {
934*7c568831SAndroid Build Coastguard Worker     switch (type) {
935*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_EPSILON:
936*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "epsilon "); break;
937*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_CHARVAL:
938*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "charval "); break;
939*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_RANGES:
940*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "ranges "); break;
941*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SUBREG:
942*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "subexpr "); break;
943*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_STRING:
944*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "string "); break;
945*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_ANYCHAR:
946*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "anychar "); break;
947*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_ANYSPACE:
948*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "anyspace "); break;
949*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTSPACE:
950*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "notspace "); break;
951*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_INITNAME:
952*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "initname "); break;
953*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTINITNAME:
954*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "notinitname "); break;
955*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NAMECHAR:
956*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "namechar "); break;
957*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTNAMECHAR:
958*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "notnamechar "); break;
959*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_DECIMAL:
960*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "decimal "); break;
961*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTDECIMAL:
962*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "notdecimal "); break;
963*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_REALCHAR:
964*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "realchar "); break;
965*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTREALCHAR:
966*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "notrealchar "); break;
967*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER:
968*7c568831SAndroid Build Coastguard Worker             fprintf(output, "LETTER "); break;
969*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_UPPERCASE:
970*7c568831SAndroid Build Coastguard Worker             fprintf(output, "LETTER_UPPERCASE "); break;
971*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_LOWERCASE:
972*7c568831SAndroid Build Coastguard Worker             fprintf(output, "LETTER_LOWERCASE "); break;
973*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_TITLECASE:
974*7c568831SAndroid Build Coastguard Worker             fprintf(output, "LETTER_TITLECASE "); break;
975*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_MODIFIER:
976*7c568831SAndroid Build Coastguard Worker             fprintf(output, "LETTER_MODIFIER "); break;
977*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_OTHERS:
978*7c568831SAndroid Build Coastguard Worker             fprintf(output, "LETTER_OTHERS "); break;
979*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK:
980*7c568831SAndroid Build Coastguard Worker             fprintf(output, "MARK "); break;
981*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_NONSPACING:
982*7c568831SAndroid Build Coastguard Worker             fprintf(output, "MARK_NONSPACING "); break;
983*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_SPACECOMBINING:
984*7c568831SAndroid Build Coastguard Worker             fprintf(output, "MARK_SPACECOMBINING "); break;
985*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_ENCLOSING:
986*7c568831SAndroid Build Coastguard Worker             fprintf(output, "MARK_ENCLOSING "); break;
987*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER:
988*7c568831SAndroid Build Coastguard Worker             fprintf(output, "NUMBER "); break;
989*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_DECIMAL:
990*7c568831SAndroid Build Coastguard Worker             fprintf(output, "NUMBER_DECIMAL "); break;
991*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_LETTER:
992*7c568831SAndroid Build Coastguard Worker             fprintf(output, "NUMBER_LETTER "); break;
993*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_OTHERS:
994*7c568831SAndroid Build Coastguard Worker             fprintf(output, "NUMBER_OTHERS "); break;
995*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT:
996*7c568831SAndroid Build Coastguard Worker             fprintf(output, "PUNCT "); break;
997*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_CONNECTOR:
998*7c568831SAndroid Build Coastguard Worker             fprintf(output, "PUNCT_CONNECTOR "); break;
999*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_DASH:
1000*7c568831SAndroid Build Coastguard Worker             fprintf(output, "PUNCT_DASH "); break;
1001*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_OPEN:
1002*7c568831SAndroid Build Coastguard Worker             fprintf(output, "PUNCT_OPEN "); break;
1003*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_CLOSE:
1004*7c568831SAndroid Build Coastguard Worker             fprintf(output, "PUNCT_CLOSE "); break;
1005*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_INITQUOTE:
1006*7c568831SAndroid Build Coastguard Worker             fprintf(output, "PUNCT_INITQUOTE "); break;
1007*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_FINQUOTE:
1008*7c568831SAndroid Build Coastguard Worker             fprintf(output, "PUNCT_FINQUOTE "); break;
1009*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_OTHERS:
1010*7c568831SAndroid Build Coastguard Worker             fprintf(output, "PUNCT_OTHERS "); break;
1011*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR:
1012*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SEPAR "); break;
1013*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_SPACE:
1014*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SEPAR_SPACE "); break;
1015*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_LINE:
1016*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SEPAR_LINE "); break;
1017*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_PARA:
1018*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SEPAR_PARA "); break;
1019*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL:
1020*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SYMBOL "); break;
1021*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_MATH:
1022*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SYMBOL_MATH "); break;
1023*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_CURRENCY:
1024*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SYMBOL_CURRENCY "); break;
1025*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_MODIFIER:
1026*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SYMBOL_MODIFIER "); break;
1027*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_OTHERS:
1028*7c568831SAndroid Build Coastguard Worker             fprintf(output, "SYMBOL_OTHERS "); break;
1029*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER:
1030*7c568831SAndroid Build Coastguard Worker             fprintf(output, "OTHER "); break;
1031*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_CONTROL:
1032*7c568831SAndroid Build Coastguard Worker             fprintf(output, "OTHER_CONTROL "); break;
1033*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_FORMAT:
1034*7c568831SAndroid Build Coastguard Worker             fprintf(output, "OTHER_FORMAT "); break;
1035*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_PRIVATE:
1036*7c568831SAndroid Build Coastguard Worker             fprintf(output, "OTHER_PRIVATE "); break;
1037*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_NA:
1038*7c568831SAndroid Build Coastguard Worker             fprintf(output, "OTHER_NA "); break;
1039*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_BLOCK_NAME:
1040*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "BLOCK "); break;
1041*7c568831SAndroid Build Coastguard Worker     }
1042*7c568831SAndroid Build Coastguard Worker }
1043*7c568831SAndroid Build Coastguard Worker 
1044*7c568831SAndroid Build Coastguard Worker static void
xmlRegPrintQuantType(FILE * output,xmlRegQuantType type)1045*7c568831SAndroid Build Coastguard Worker xmlRegPrintQuantType(FILE *output, xmlRegQuantType type) {
1046*7c568831SAndroid Build Coastguard Worker     switch (type) {
1047*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_QUANT_EPSILON:
1048*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "epsilon "); break;
1049*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_QUANT_ONCE:
1050*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "once "); break;
1051*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_QUANT_OPT:
1052*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "? "); break;
1053*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_QUANT_MULT:
1054*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "* "); break;
1055*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_QUANT_PLUS:
1056*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "+ "); break;
1057*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_QUANT_RANGE:
1058*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "range "); break;
1059*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_QUANT_ONCEONLY:
1060*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "onceonly "); break;
1061*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_QUANT_ALL:
1062*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "all "); break;
1063*7c568831SAndroid Build Coastguard Worker     }
1064*7c568831SAndroid Build Coastguard Worker }
1065*7c568831SAndroid Build Coastguard Worker static void
xmlRegPrintRange(FILE * output,xmlRegRangePtr range)1066*7c568831SAndroid Build Coastguard Worker xmlRegPrintRange(FILE *output, xmlRegRangePtr range) {
1067*7c568831SAndroid Build Coastguard Worker     fprintf(output, "  range: ");
1068*7c568831SAndroid Build Coastguard Worker     if (range->neg)
1069*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "negative ");
1070*7c568831SAndroid Build Coastguard Worker     xmlRegPrintAtomType(output, range->type);
1071*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%c - %c\n", range->start, range->end);
1072*7c568831SAndroid Build Coastguard Worker }
1073*7c568831SAndroid Build Coastguard Worker 
1074*7c568831SAndroid Build Coastguard Worker static void
xmlRegPrintAtom(FILE * output,xmlRegAtomPtr atom)1075*7c568831SAndroid Build Coastguard Worker xmlRegPrintAtom(FILE *output, xmlRegAtomPtr atom) {
1076*7c568831SAndroid Build Coastguard Worker     fprintf(output, " atom: ");
1077*7c568831SAndroid Build Coastguard Worker     if (atom == NULL) {
1078*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "NULL\n");
1079*7c568831SAndroid Build Coastguard Worker 	return;
1080*7c568831SAndroid Build Coastguard Worker     }
1081*7c568831SAndroid Build Coastguard Worker     if (atom->neg)
1082*7c568831SAndroid Build Coastguard Worker         fprintf(output, "not ");
1083*7c568831SAndroid Build Coastguard Worker     xmlRegPrintAtomType(output, atom->type);
1084*7c568831SAndroid Build Coastguard Worker     xmlRegPrintQuantType(output, atom->quant);
1085*7c568831SAndroid Build Coastguard Worker     if (atom->quant == XML_REGEXP_QUANT_RANGE)
1086*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "%d-%d ", atom->min, atom->max);
1087*7c568831SAndroid Build Coastguard Worker     if (atom->type == XML_REGEXP_STRING)
1088*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "'%s' ", (char *) atom->valuep);
1089*7c568831SAndroid Build Coastguard Worker     if (atom->type == XML_REGEXP_CHARVAL)
1090*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "char %c\n", atom->codepoint);
1091*7c568831SAndroid Build Coastguard Worker     else if (atom->type == XML_REGEXP_RANGES) {
1092*7c568831SAndroid Build Coastguard Worker 	int i;
1093*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "%d entries\n", atom->nbRanges);
1094*7c568831SAndroid Build Coastguard Worker 	for (i = 0; i < atom->nbRanges;i++)
1095*7c568831SAndroid Build Coastguard Worker 	    xmlRegPrintRange(output, atom->ranges[i]);
1096*7c568831SAndroid Build Coastguard Worker     } else if (atom->type == XML_REGEXP_SUBREG) {
1097*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "start %d end %d\n", atom->start->no, atom->stop->no);
1098*7c568831SAndroid Build Coastguard Worker     } else {
1099*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "\n");
1100*7c568831SAndroid Build Coastguard Worker     }
1101*7c568831SAndroid Build Coastguard Worker }
1102*7c568831SAndroid Build Coastguard Worker 
1103*7c568831SAndroid Build Coastguard Worker static void
xmlRegPrintTrans(FILE * output,xmlRegTransPtr trans)1104*7c568831SAndroid Build Coastguard Worker xmlRegPrintTrans(FILE *output, xmlRegTransPtr trans) {
1105*7c568831SAndroid Build Coastguard Worker     fprintf(output, "  trans: ");
1106*7c568831SAndroid Build Coastguard Worker     if (trans == NULL) {
1107*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "NULL\n");
1108*7c568831SAndroid Build Coastguard Worker 	return;
1109*7c568831SAndroid Build Coastguard Worker     }
1110*7c568831SAndroid Build Coastguard Worker     if (trans->to < 0) {
1111*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "removed\n");
1112*7c568831SAndroid Build Coastguard Worker 	return;
1113*7c568831SAndroid Build Coastguard Worker     }
1114*7c568831SAndroid Build Coastguard Worker     if (trans->nd != 0) {
1115*7c568831SAndroid Build Coastguard Worker 	if (trans->nd == 2)
1116*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "last not determinist, ");
1117*7c568831SAndroid Build Coastguard Worker 	else
1118*7c568831SAndroid Build Coastguard Worker 	    fprintf(output, "not determinist, ");
1119*7c568831SAndroid Build Coastguard Worker     }
1120*7c568831SAndroid Build Coastguard Worker     if (trans->counter >= 0) {
1121*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "counted %d, ", trans->counter);
1122*7c568831SAndroid Build Coastguard Worker     }
1123*7c568831SAndroid Build Coastguard Worker     if (trans->count == REGEXP_ALL_COUNTER) {
1124*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "all transition, ");
1125*7c568831SAndroid Build Coastguard Worker     } else if (trans->count >= 0) {
1126*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "count based %d, ", trans->count);
1127*7c568831SAndroid Build Coastguard Worker     }
1128*7c568831SAndroid Build Coastguard Worker     if (trans->atom == NULL) {
1129*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "epsilon to %d\n", trans->to);
1130*7c568831SAndroid Build Coastguard Worker 	return;
1131*7c568831SAndroid Build Coastguard Worker     }
1132*7c568831SAndroid Build Coastguard Worker     if (trans->atom->type == XML_REGEXP_CHARVAL)
1133*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "char %c ", trans->atom->codepoint);
1134*7c568831SAndroid Build Coastguard Worker     fprintf(output, "atom %d, to %d\n", trans->atom->no, trans->to);
1135*7c568831SAndroid Build Coastguard Worker }
1136*7c568831SAndroid Build Coastguard Worker 
1137*7c568831SAndroid Build Coastguard Worker static void
xmlRegPrintState(FILE * output,xmlRegStatePtr state)1138*7c568831SAndroid Build Coastguard Worker xmlRegPrintState(FILE *output, xmlRegStatePtr state) {
1139*7c568831SAndroid Build Coastguard Worker     int i;
1140*7c568831SAndroid Build Coastguard Worker 
1141*7c568831SAndroid Build Coastguard Worker     fprintf(output, " state: ");
1142*7c568831SAndroid Build Coastguard Worker     if (state == NULL) {
1143*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "NULL\n");
1144*7c568831SAndroid Build Coastguard Worker 	return;
1145*7c568831SAndroid Build Coastguard Worker     }
1146*7c568831SAndroid Build Coastguard Worker     if (state->type == XML_REGEXP_START_STATE)
1147*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "START ");
1148*7c568831SAndroid Build Coastguard Worker     if (state->type == XML_REGEXP_FINAL_STATE)
1149*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "FINAL ");
1150*7c568831SAndroid Build Coastguard Worker 
1151*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%d, %d transitions:\n", state->no, state->nbTrans);
1152*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < state->nbTrans; i++) {
1153*7c568831SAndroid Build Coastguard Worker 	xmlRegPrintTrans(output, &(state->trans[i]));
1154*7c568831SAndroid Build Coastguard Worker     }
1155*7c568831SAndroid Build Coastguard Worker }
1156*7c568831SAndroid Build Coastguard Worker 
1157*7c568831SAndroid Build Coastguard Worker /************************************************************************
1158*7c568831SAndroid Build Coastguard Worker  *									*
1159*7c568831SAndroid Build Coastguard Worker  *		 Finite Automata structures manipulations		*
1160*7c568831SAndroid Build Coastguard Worker  *									*
1161*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
1162*7c568831SAndroid Build Coastguard Worker 
1163*7c568831SAndroid Build Coastguard Worker static xmlRegRangePtr
xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt,xmlRegAtomPtr atom,int neg,xmlRegAtomType type,int start,int end,xmlChar * blockName)1164*7c568831SAndroid Build Coastguard Worker xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom,
1165*7c568831SAndroid Build Coastguard Worker 	           int neg, xmlRegAtomType type, int start, int end,
1166*7c568831SAndroid Build Coastguard Worker 		   xmlChar *blockName) {
1167*7c568831SAndroid Build Coastguard Worker     xmlRegRangePtr range;
1168*7c568831SAndroid Build Coastguard Worker 
1169*7c568831SAndroid Build Coastguard Worker     if (atom == NULL) {
1170*7c568831SAndroid Build Coastguard Worker 	ERROR("add range: atom is NULL");
1171*7c568831SAndroid Build Coastguard Worker 	return(NULL);
1172*7c568831SAndroid Build Coastguard Worker     }
1173*7c568831SAndroid Build Coastguard Worker     if (atom->type != XML_REGEXP_RANGES) {
1174*7c568831SAndroid Build Coastguard Worker 	ERROR("add range: atom is not ranges");
1175*7c568831SAndroid Build Coastguard Worker 	return(NULL);
1176*7c568831SAndroid Build Coastguard Worker     }
1177*7c568831SAndroid Build Coastguard Worker     if (atom->maxRanges == 0) {
1178*7c568831SAndroid Build Coastguard Worker 	atom->maxRanges = 4;
1179*7c568831SAndroid Build Coastguard Worker 	atom->ranges = (xmlRegRangePtr *) xmlMalloc(atom->maxRanges *
1180*7c568831SAndroid Build Coastguard Worker 		                             sizeof(xmlRegRangePtr));
1181*7c568831SAndroid Build Coastguard Worker 	if (atom->ranges == NULL) {
1182*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1183*7c568831SAndroid Build Coastguard Worker 	    atom->maxRanges = 0;
1184*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
1185*7c568831SAndroid Build Coastguard Worker 	}
1186*7c568831SAndroid Build Coastguard Worker     } else if (atom->nbRanges >= atom->maxRanges) {
1187*7c568831SAndroid Build Coastguard Worker 	xmlRegRangePtr *tmp;
1188*7c568831SAndroid Build Coastguard Worker 	atom->maxRanges *= 2;
1189*7c568831SAndroid Build Coastguard Worker 	tmp = (xmlRegRangePtr *) xmlRealloc(atom->ranges, atom->maxRanges *
1190*7c568831SAndroid Build Coastguard Worker 		                             sizeof(xmlRegRangePtr));
1191*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
1192*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1193*7c568831SAndroid Build Coastguard Worker 	    atom->maxRanges /= 2;
1194*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
1195*7c568831SAndroid Build Coastguard Worker 	}
1196*7c568831SAndroid Build Coastguard Worker 	atom->ranges = tmp;
1197*7c568831SAndroid Build Coastguard Worker     }
1198*7c568831SAndroid Build Coastguard Worker     range = xmlRegNewRange(ctxt, neg, type, start, end);
1199*7c568831SAndroid Build Coastguard Worker     if (range == NULL)
1200*7c568831SAndroid Build Coastguard Worker 	return(NULL);
1201*7c568831SAndroid Build Coastguard Worker     range->blockName = blockName;
1202*7c568831SAndroid Build Coastguard Worker     atom->ranges[atom->nbRanges++] = range;
1203*7c568831SAndroid Build Coastguard Worker 
1204*7c568831SAndroid Build Coastguard Worker     return(range);
1205*7c568831SAndroid Build Coastguard Worker }
1206*7c568831SAndroid Build Coastguard Worker 
1207*7c568831SAndroid Build Coastguard Worker static int
xmlRegGetCounter(xmlRegParserCtxtPtr ctxt)1208*7c568831SAndroid Build Coastguard Worker xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) {
1209*7c568831SAndroid Build Coastguard Worker     if (ctxt->maxCounters == 0) {
1210*7c568831SAndroid Build Coastguard Worker 	ctxt->maxCounters = 4;
1211*7c568831SAndroid Build Coastguard Worker 	ctxt->counters = (xmlRegCounter *) xmlMalloc(ctxt->maxCounters *
1212*7c568831SAndroid Build Coastguard Worker 		                             sizeof(xmlRegCounter));
1213*7c568831SAndroid Build Coastguard Worker 	if (ctxt->counters == NULL) {
1214*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1215*7c568831SAndroid Build Coastguard Worker 	    ctxt->maxCounters = 0;
1216*7c568831SAndroid Build Coastguard Worker 	    return(-1);
1217*7c568831SAndroid Build Coastguard Worker 	}
1218*7c568831SAndroid Build Coastguard Worker     } else if (ctxt->nbCounters >= ctxt->maxCounters) {
1219*7c568831SAndroid Build Coastguard Worker 	xmlRegCounter *tmp;
1220*7c568831SAndroid Build Coastguard Worker 	ctxt->maxCounters *= 2;
1221*7c568831SAndroid Build Coastguard Worker 	tmp = (xmlRegCounter *) xmlRealloc(ctxt->counters, ctxt->maxCounters *
1222*7c568831SAndroid Build Coastguard Worker 		                           sizeof(xmlRegCounter));
1223*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
1224*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1225*7c568831SAndroid Build Coastguard Worker 	    ctxt->maxCounters /= 2;
1226*7c568831SAndroid Build Coastguard Worker 	    return(-1);
1227*7c568831SAndroid Build Coastguard Worker 	}
1228*7c568831SAndroid Build Coastguard Worker 	ctxt->counters = tmp;
1229*7c568831SAndroid Build Coastguard Worker     }
1230*7c568831SAndroid Build Coastguard Worker     ctxt->counters[ctxt->nbCounters].min = -1;
1231*7c568831SAndroid Build Coastguard Worker     ctxt->counters[ctxt->nbCounters].max = -1;
1232*7c568831SAndroid Build Coastguard Worker     return(ctxt->nbCounters++);
1233*7c568831SAndroid Build Coastguard Worker }
1234*7c568831SAndroid Build Coastguard Worker 
1235*7c568831SAndroid Build Coastguard Worker static int
xmlRegAtomPush(xmlRegParserCtxtPtr ctxt,xmlRegAtomPtr atom)1236*7c568831SAndroid Build Coastguard Worker xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
1237*7c568831SAndroid Build Coastguard Worker     if (atom == NULL) {
1238*7c568831SAndroid Build Coastguard Worker 	ERROR("atom push: atom is NULL");
1239*7c568831SAndroid Build Coastguard Worker 	return(-1);
1240*7c568831SAndroid Build Coastguard Worker     }
1241*7c568831SAndroid Build Coastguard Worker     if (ctxt->nbAtoms >= ctxt->maxAtoms) {
1242*7c568831SAndroid Build Coastguard Worker         size_t newSize = ctxt->maxAtoms ? ctxt->maxAtoms * 2 : 4;
1243*7c568831SAndroid Build Coastguard Worker 	xmlRegAtomPtr *tmp;
1244*7c568831SAndroid Build Coastguard Worker 
1245*7c568831SAndroid Build Coastguard Worker 	tmp = xmlRealloc(ctxt->atoms, newSize * sizeof(xmlRegAtomPtr));
1246*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
1247*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1248*7c568831SAndroid Build Coastguard Worker 	    return(-1);
1249*7c568831SAndroid Build Coastguard Worker 	}
1250*7c568831SAndroid Build Coastguard Worker 	ctxt->atoms = tmp;
1251*7c568831SAndroid Build Coastguard Worker         ctxt->maxAtoms = newSize;
1252*7c568831SAndroid Build Coastguard Worker     }
1253*7c568831SAndroid Build Coastguard Worker     atom->no = ctxt->nbAtoms;
1254*7c568831SAndroid Build Coastguard Worker     ctxt->atoms[ctxt->nbAtoms++] = atom;
1255*7c568831SAndroid Build Coastguard Worker     return(0);
1256*7c568831SAndroid Build Coastguard Worker }
1257*7c568831SAndroid Build Coastguard Worker 
1258*7c568831SAndroid Build Coastguard Worker static void
xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr target,int from)1259*7c568831SAndroid Build Coastguard Worker xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target,
1260*7c568831SAndroid Build Coastguard Worker                       int from) {
1261*7c568831SAndroid Build Coastguard Worker     if (target->maxTransTo == 0) {
1262*7c568831SAndroid Build Coastguard Worker 	target->maxTransTo = 8;
1263*7c568831SAndroid Build Coastguard Worker 	target->transTo = (int *) xmlMalloc(target->maxTransTo *
1264*7c568831SAndroid Build Coastguard Worker 		                             sizeof(int));
1265*7c568831SAndroid Build Coastguard Worker 	if (target->transTo == NULL) {
1266*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1267*7c568831SAndroid Build Coastguard Worker 	    target->maxTransTo = 0;
1268*7c568831SAndroid Build Coastguard Worker 	    return;
1269*7c568831SAndroid Build Coastguard Worker 	}
1270*7c568831SAndroid Build Coastguard Worker     } else if (target->nbTransTo >= target->maxTransTo) {
1271*7c568831SAndroid Build Coastguard Worker 	int *tmp;
1272*7c568831SAndroid Build Coastguard Worker 	target->maxTransTo *= 2;
1273*7c568831SAndroid Build Coastguard Worker 	tmp = (int *) xmlRealloc(target->transTo, target->maxTransTo *
1274*7c568831SAndroid Build Coastguard Worker 		                             sizeof(int));
1275*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
1276*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1277*7c568831SAndroid Build Coastguard Worker 	    target->maxTransTo /= 2;
1278*7c568831SAndroid Build Coastguard Worker 	    return;
1279*7c568831SAndroid Build Coastguard Worker 	}
1280*7c568831SAndroid Build Coastguard Worker 	target->transTo = tmp;
1281*7c568831SAndroid Build Coastguard Worker     }
1282*7c568831SAndroid Build Coastguard Worker     target->transTo[target->nbTransTo] = from;
1283*7c568831SAndroid Build Coastguard Worker     target->nbTransTo++;
1284*7c568831SAndroid Build Coastguard Worker }
1285*7c568831SAndroid Build Coastguard Worker 
1286*7c568831SAndroid Build Coastguard Worker static void
xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr state,xmlRegAtomPtr atom,xmlRegStatePtr target,int counter,int count)1287*7c568831SAndroid Build Coastguard Worker xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
1288*7c568831SAndroid Build Coastguard Worker 	            xmlRegAtomPtr atom, xmlRegStatePtr target,
1289*7c568831SAndroid Build Coastguard Worker 		    int counter, int count) {
1290*7c568831SAndroid Build Coastguard Worker 
1291*7c568831SAndroid Build Coastguard Worker     int nrtrans;
1292*7c568831SAndroid Build Coastguard Worker 
1293*7c568831SAndroid Build Coastguard Worker     if (state == NULL) {
1294*7c568831SAndroid Build Coastguard Worker 	ERROR("add state: state is NULL");
1295*7c568831SAndroid Build Coastguard Worker 	return;
1296*7c568831SAndroid Build Coastguard Worker     }
1297*7c568831SAndroid Build Coastguard Worker     if (target == NULL) {
1298*7c568831SAndroid Build Coastguard Worker 	ERROR("add state: target is NULL");
1299*7c568831SAndroid Build Coastguard Worker 	return;
1300*7c568831SAndroid Build Coastguard Worker     }
1301*7c568831SAndroid Build Coastguard Worker     /*
1302*7c568831SAndroid Build Coastguard Worker      * Other routines follow the philosophy 'When in doubt, add a transition'
1303*7c568831SAndroid Build Coastguard Worker      * so we check here whether such a transition is already present and, if
1304*7c568831SAndroid Build Coastguard Worker      * so, silently ignore this request.
1305*7c568831SAndroid Build Coastguard Worker      */
1306*7c568831SAndroid Build Coastguard Worker 
1307*7c568831SAndroid Build Coastguard Worker     for (nrtrans = state->nbTrans - 1; nrtrans >= 0; nrtrans--) {
1308*7c568831SAndroid Build Coastguard Worker 	xmlRegTransPtr trans = &(state->trans[nrtrans]);
1309*7c568831SAndroid Build Coastguard Worker 	if ((trans->atom == atom) &&
1310*7c568831SAndroid Build Coastguard Worker 	    (trans->to == target->no) &&
1311*7c568831SAndroid Build Coastguard Worker 	    (trans->counter == counter) &&
1312*7c568831SAndroid Build Coastguard Worker 	    (trans->count == count)) {
1313*7c568831SAndroid Build Coastguard Worker 	    return;
1314*7c568831SAndroid Build Coastguard Worker 	}
1315*7c568831SAndroid Build Coastguard Worker     }
1316*7c568831SAndroid Build Coastguard Worker 
1317*7c568831SAndroid Build Coastguard Worker     if (state->maxTrans == 0) {
1318*7c568831SAndroid Build Coastguard Worker 	state->maxTrans = 8;
1319*7c568831SAndroid Build Coastguard Worker 	state->trans = (xmlRegTrans *) xmlMalloc(state->maxTrans *
1320*7c568831SAndroid Build Coastguard Worker 		                             sizeof(xmlRegTrans));
1321*7c568831SAndroid Build Coastguard Worker 	if (state->trans == NULL) {
1322*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1323*7c568831SAndroid Build Coastguard Worker 	    state->maxTrans = 0;
1324*7c568831SAndroid Build Coastguard Worker 	    return;
1325*7c568831SAndroid Build Coastguard Worker 	}
1326*7c568831SAndroid Build Coastguard Worker     } else if (state->nbTrans >= state->maxTrans) {
1327*7c568831SAndroid Build Coastguard Worker 	xmlRegTrans *tmp;
1328*7c568831SAndroid Build Coastguard Worker 	state->maxTrans *= 2;
1329*7c568831SAndroid Build Coastguard Worker 	tmp = (xmlRegTrans *) xmlRealloc(state->trans, state->maxTrans *
1330*7c568831SAndroid Build Coastguard Worker 		                             sizeof(xmlRegTrans));
1331*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
1332*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1333*7c568831SAndroid Build Coastguard Worker 	    state->maxTrans /= 2;
1334*7c568831SAndroid Build Coastguard Worker 	    return;
1335*7c568831SAndroid Build Coastguard Worker 	}
1336*7c568831SAndroid Build Coastguard Worker 	state->trans = tmp;
1337*7c568831SAndroid Build Coastguard Worker     }
1338*7c568831SAndroid Build Coastguard Worker 
1339*7c568831SAndroid Build Coastguard Worker     state->trans[state->nbTrans].atom = atom;
1340*7c568831SAndroid Build Coastguard Worker     state->trans[state->nbTrans].to = target->no;
1341*7c568831SAndroid Build Coastguard Worker     state->trans[state->nbTrans].counter = counter;
1342*7c568831SAndroid Build Coastguard Worker     state->trans[state->nbTrans].count = count;
1343*7c568831SAndroid Build Coastguard Worker     state->trans[state->nbTrans].nd = 0;
1344*7c568831SAndroid Build Coastguard Worker     state->nbTrans++;
1345*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTransTo(ctxt, target, state->no);
1346*7c568831SAndroid Build Coastguard Worker }
1347*7c568831SAndroid Build Coastguard Worker 
1348*7c568831SAndroid Build Coastguard Worker static xmlRegStatePtr
xmlRegStatePush(xmlRegParserCtxtPtr ctxt)1349*7c568831SAndroid Build Coastguard Worker xmlRegStatePush(xmlRegParserCtxtPtr ctxt) {
1350*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr state;
1351*7c568831SAndroid Build Coastguard Worker 
1352*7c568831SAndroid Build Coastguard Worker     if (ctxt->nbStates >= ctxt->maxStates) {
1353*7c568831SAndroid Build Coastguard Worker         size_t newSize = ctxt->maxStates ? ctxt->maxStates * 2 : 4;
1354*7c568831SAndroid Build Coastguard Worker 	xmlRegStatePtr *tmp;
1355*7c568831SAndroid Build Coastguard Worker 
1356*7c568831SAndroid Build Coastguard Worker 	tmp = xmlRealloc(ctxt->states, newSize * sizeof(tmp[0]));
1357*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
1358*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
1359*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
1360*7c568831SAndroid Build Coastguard Worker 	}
1361*7c568831SAndroid Build Coastguard Worker 	ctxt->states = tmp;
1362*7c568831SAndroid Build Coastguard Worker 	ctxt->maxStates = newSize;
1363*7c568831SAndroid Build Coastguard Worker     }
1364*7c568831SAndroid Build Coastguard Worker 
1365*7c568831SAndroid Build Coastguard Worker     state = xmlRegNewState(ctxt);
1366*7c568831SAndroid Build Coastguard Worker     if (state == NULL)
1367*7c568831SAndroid Build Coastguard Worker         return(NULL);
1368*7c568831SAndroid Build Coastguard Worker 
1369*7c568831SAndroid Build Coastguard Worker     state->no = ctxt->nbStates;
1370*7c568831SAndroid Build Coastguard Worker     ctxt->states[ctxt->nbStates++] = state;
1371*7c568831SAndroid Build Coastguard Worker 
1372*7c568831SAndroid Build Coastguard Worker     return(state);
1373*7c568831SAndroid Build Coastguard Worker }
1374*7c568831SAndroid Build Coastguard Worker 
1375*7c568831SAndroid Build Coastguard Worker /**
1376*7c568831SAndroid Build Coastguard Worker  * xmlFAGenerateAllTransition:
1377*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1378*7c568831SAndroid Build Coastguard Worker  * @from:  the from state
1379*7c568831SAndroid Build Coastguard Worker  * @to:  the target state or NULL for building a new one
1380*7c568831SAndroid Build Coastguard Worker  * @lax:
1381*7c568831SAndroid Build Coastguard Worker  *
1382*7c568831SAndroid Build Coastguard Worker  */
1383*7c568831SAndroid Build Coastguard Worker static int
xmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr from,xmlRegStatePtr to,int lax)1384*7c568831SAndroid Build Coastguard Worker xmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt,
1385*7c568831SAndroid Build Coastguard Worker 			   xmlRegStatePtr from, xmlRegStatePtr to,
1386*7c568831SAndroid Build Coastguard Worker 			   int lax) {
1387*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
1388*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(ctxt);
1389*7c568831SAndroid Build Coastguard Worker         if (to == NULL)
1390*7c568831SAndroid Build Coastguard Worker             return(-1);
1391*7c568831SAndroid Build Coastguard Worker 	ctxt->state = to;
1392*7c568831SAndroid Build Coastguard Worker     }
1393*7c568831SAndroid Build Coastguard Worker     if (lax)
1394*7c568831SAndroid Build Coastguard Worker 	xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_LAX_COUNTER);
1395*7c568831SAndroid Build Coastguard Worker     else
1396*7c568831SAndroid Build Coastguard Worker 	xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_COUNTER);
1397*7c568831SAndroid Build Coastguard Worker     return(0);
1398*7c568831SAndroid Build Coastguard Worker }
1399*7c568831SAndroid Build Coastguard Worker 
1400*7c568831SAndroid Build Coastguard Worker /**
1401*7c568831SAndroid Build Coastguard Worker  * xmlFAGenerateEpsilonTransition:
1402*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1403*7c568831SAndroid Build Coastguard Worker  * @from:  the from state
1404*7c568831SAndroid Build Coastguard Worker  * @to:  the target state or NULL for building a new one
1405*7c568831SAndroid Build Coastguard Worker  *
1406*7c568831SAndroid Build Coastguard Worker  */
1407*7c568831SAndroid Build Coastguard Worker static int
xmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr from,xmlRegStatePtr to)1408*7c568831SAndroid Build Coastguard Worker xmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt,
1409*7c568831SAndroid Build Coastguard Worker 			       xmlRegStatePtr from, xmlRegStatePtr to) {
1410*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
1411*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(ctxt);
1412*7c568831SAndroid Build Coastguard Worker         if (to == NULL)
1413*7c568831SAndroid Build Coastguard Worker             return(-1);
1414*7c568831SAndroid Build Coastguard Worker 	ctxt->state = to;
1415*7c568831SAndroid Build Coastguard Worker     }
1416*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTrans(ctxt, from, NULL, to, -1, -1);
1417*7c568831SAndroid Build Coastguard Worker     return(0);
1418*7c568831SAndroid Build Coastguard Worker }
1419*7c568831SAndroid Build Coastguard Worker 
1420*7c568831SAndroid Build Coastguard Worker /**
1421*7c568831SAndroid Build Coastguard Worker  * xmlFAGenerateCountedEpsilonTransition:
1422*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1423*7c568831SAndroid Build Coastguard Worker  * @from:  the from state
1424*7c568831SAndroid Build Coastguard Worker  * @to:  the target state or NULL for building a new one
1425*7c568831SAndroid Build Coastguard Worker  * counter:  the counter for that transition
1426*7c568831SAndroid Build Coastguard Worker  *
1427*7c568831SAndroid Build Coastguard Worker  */
1428*7c568831SAndroid Build Coastguard Worker static int
xmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr from,xmlRegStatePtr to,int counter)1429*7c568831SAndroid Build Coastguard Worker xmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt,
1430*7c568831SAndroid Build Coastguard Worker 	    xmlRegStatePtr from, xmlRegStatePtr to, int counter) {
1431*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
1432*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(ctxt);
1433*7c568831SAndroid Build Coastguard Worker         if (to == NULL)
1434*7c568831SAndroid Build Coastguard Worker             return(-1);
1435*7c568831SAndroid Build Coastguard Worker 	ctxt->state = to;
1436*7c568831SAndroid Build Coastguard Worker     }
1437*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTrans(ctxt, from, NULL, to, counter, -1);
1438*7c568831SAndroid Build Coastguard Worker     return(0);
1439*7c568831SAndroid Build Coastguard Worker }
1440*7c568831SAndroid Build Coastguard Worker 
1441*7c568831SAndroid Build Coastguard Worker /**
1442*7c568831SAndroid Build Coastguard Worker  * xmlFAGenerateCountedTransition:
1443*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1444*7c568831SAndroid Build Coastguard Worker  * @from:  the from state
1445*7c568831SAndroid Build Coastguard Worker  * @to:  the target state or NULL for building a new one
1446*7c568831SAndroid Build Coastguard Worker  * counter:  the counter for that transition
1447*7c568831SAndroid Build Coastguard Worker  *
1448*7c568831SAndroid Build Coastguard Worker  */
1449*7c568831SAndroid Build Coastguard Worker static int
xmlFAGenerateCountedTransition(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr from,xmlRegStatePtr to,int counter)1450*7c568831SAndroid Build Coastguard Worker xmlFAGenerateCountedTransition(xmlRegParserCtxtPtr ctxt,
1451*7c568831SAndroid Build Coastguard Worker 	    xmlRegStatePtr from, xmlRegStatePtr to, int counter) {
1452*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
1453*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(ctxt);
1454*7c568831SAndroid Build Coastguard Worker         if (to == NULL)
1455*7c568831SAndroid Build Coastguard Worker             return(-1);
1456*7c568831SAndroid Build Coastguard Worker 	ctxt->state = to;
1457*7c568831SAndroid Build Coastguard Worker     }
1458*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTrans(ctxt, from, NULL, to, -1, counter);
1459*7c568831SAndroid Build Coastguard Worker     return(0);
1460*7c568831SAndroid Build Coastguard Worker }
1461*7c568831SAndroid Build Coastguard Worker 
1462*7c568831SAndroid Build Coastguard Worker /**
1463*7c568831SAndroid Build Coastguard Worker  * xmlFAGenerateTransitions:
1464*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1465*7c568831SAndroid Build Coastguard Worker  * @from:  the from state
1466*7c568831SAndroid Build Coastguard Worker  * @to:  the target state or NULL for building a new one
1467*7c568831SAndroid Build Coastguard Worker  * @atom:  the atom generating the transition
1468*7c568831SAndroid Build Coastguard Worker  *
1469*7c568831SAndroid Build Coastguard Worker  * Returns 0 if success and -1 in case of error.
1470*7c568831SAndroid Build Coastguard Worker  */
1471*7c568831SAndroid Build Coastguard Worker static int
xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr from,xmlRegStatePtr to,xmlRegAtomPtr atom)1472*7c568831SAndroid Build Coastguard Worker xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
1473*7c568831SAndroid Build Coastguard Worker 	                 xmlRegStatePtr to, xmlRegAtomPtr atom) {
1474*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr end;
1475*7c568831SAndroid Build Coastguard Worker     int nullable = 0;
1476*7c568831SAndroid Build Coastguard Worker 
1477*7c568831SAndroid Build Coastguard Worker     if (atom == NULL) {
1478*7c568831SAndroid Build Coastguard Worker 	ERROR("generate transition: atom == NULL");
1479*7c568831SAndroid Build Coastguard Worker 	return(-1);
1480*7c568831SAndroid Build Coastguard Worker     }
1481*7c568831SAndroid Build Coastguard Worker     if (atom->type == XML_REGEXP_SUBREG) {
1482*7c568831SAndroid Build Coastguard Worker 	/*
1483*7c568831SAndroid Build Coastguard Worker 	 * this is a subexpression handling one should not need to
1484*7c568831SAndroid Build Coastguard Worker 	 * create a new node except for XML_REGEXP_QUANT_RANGE.
1485*7c568831SAndroid Build Coastguard Worker 	 */
1486*7c568831SAndroid Build Coastguard Worker 	if ((to != NULL) && (atom->stop != to) &&
1487*7c568831SAndroid Build Coastguard Worker 	    (atom->quant != XML_REGEXP_QUANT_RANGE)) {
1488*7c568831SAndroid Build Coastguard Worker 	    /*
1489*7c568831SAndroid Build Coastguard Worker 	     * Generate an epsilon transition to link to the target
1490*7c568831SAndroid Build Coastguard Worker 	     */
1491*7c568831SAndroid Build Coastguard Worker 	    xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to);
1492*7c568831SAndroid Build Coastguard Worker #ifdef DV
1493*7c568831SAndroid Build Coastguard Worker 	} else if ((to == NULL) && (atom->quant != XML_REGEXP_QUANT_RANGE) &&
1494*7c568831SAndroid Build Coastguard Worker 		   (atom->quant != XML_REGEXP_QUANT_ONCE)) {
1495*7c568831SAndroid Build Coastguard Worker 	    to = xmlRegStatePush(ctxt, to);
1496*7c568831SAndroid Build Coastguard Worker             if (to == NULL)
1497*7c568831SAndroid Build Coastguard Worker                 return(-1);
1498*7c568831SAndroid Build Coastguard Worker 	    ctxt->state = to;
1499*7c568831SAndroid Build Coastguard Worker 	    xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to);
1500*7c568831SAndroid Build Coastguard Worker #endif
1501*7c568831SAndroid Build Coastguard Worker 	}
1502*7c568831SAndroid Build Coastguard Worker 	switch (atom->quant) {
1503*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_QUANT_OPT:
1504*7c568831SAndroid Build Coastguard Worker 		atom->quant = XML_REGEXP_QUANT_ONCE;
1505*7c568831SAndroid Build Coastguard Worker 		/*
1506*7c568831SAndroid Build Coastguard Worker 		 * transition done to the state after end of atom.
1507*7c568831SAndroid Build Coastguard Worker 		 *      1. set transition from atom start to new state
1508*7c568831SAndroid Build Coastguard Worker 		 *      2. set transition from atom end to this state.
1509*7c568831SAndroid Build Coastguard Worker 		 */
1510*7c568831SAndroid Build Coastguard Worker                 if (to == NULL) {
1511*7c568831SAndroid Build Coastguard Worker                     xmlFAGenerateEpsilonTransition(ctxt, atom->start, 0);
1512*7c568831SAndroid Build Coastguard Worker                     xmlFAGenerateEpsilonTransition(ctxt, atom->stop,
1513*7c568831SAndroid Build Coastguard Worker                                                    ctxt->state);
1514*7c568831SAndroid Build Coastguard Worker                 } else {
1515*7c568831SAndroid Build Coastguard Worker                     xmlFAGenerateEpsilonTransition(ctxt, atom->start, to);
1516*7c568831SAndroid Build Coastguard Worker                 }
1517*7c568831SAndroid Build Coastguard Worker 		break;
1518*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_QUANT_MULT:
1519*7c568831SAndroid Build Coastguard Worker 		atom->quant = XML_REGEXP_QUANT_ONCE;
1520*7c568831SAndroid Build Coastguard Worker 		xmlFAGenerateEpsilonTransition(ctxt, atom->start, atom->stop);
1521*7c568831SAndroid Build Coastguard Worker 		xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start);
1522*7c568831SAndroid Build Coastguard Worker 		break;
1523*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_QUANT_PLUS:
1524*7c568831SAndroid Build Coastguard Worker 		atom->quant = XML_REGEXP_QUANT_ONCE;
1525*7c568831SAndroid Build Coastguard Worker 		xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start);
1526*7c568831SAndroid Build Coastguard Worker 		break;
1527*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_QUANT_RANGE: {
1528*7c568831SAndroid Build Coastguard Worker 		int counter;
1529*7c568831SAndroid Build Coastguard Worker 		xmlRegStatePtr inter, newstate;
1530*7c568831SAndroid Build Coastguard Worker 
1531*7c568831SAndroid Build Coastguard Worker 		/*
1532*7c568831SAndroid Build Coastguard Worker 		 * create the final state now if needed
1533*7c568831SAndroid Build Coastguard Worker 		 */
1534*7c568831SAndroid Build Coastguard Worker 		if (to != NULL) {
1535*7c568831SAndroid Build Coastguard Worker 		    newstate = to;
1536*7c568831SAndroid Build Coastguard Worker 		} else {
1537*7c568831SAndroid Build Coastguard Worker 		    newstate = xmlRegStatePush(ctxt);
1538*7c568831SAndroid Build Coastguard Worker                     if (newstate == NULL)
1539*7c568831SAndroid Build Coastguard Worker                         return(-1);
1540*7c568831SAndroid Build Coastguard Worker 		}
1541*7c568831SAndroid Build Coastguard Worker 
1542*7c568831SAndroid Build Coastguard Worker 		/*
1543*7c568831SAndroid Build Coastguard Worker 		 * The principle here is to use counted transition
1544*7c568831SAndroid Build Coastguard Worker 		 * to avoid explosion in the number of states in the
1545*7c568831SAndroid Build Coastguard Worker 		 * graph. This is clearly more complex but should not
1546*7c568831SAndroid Build Coastguard Worker 		 * be exploitable at runtime.
1547*7c568831SAndroid Build Coastguard Worker 		 */
1548*7c568831SAndroid Build Coastguard Worker 		if ((atom->min == 0) && (atom->start0 == NULL)) {
1549*7c568831SAndroid Build Coastguard Worker 		    xmlRegAtomPtr copy;
1550*7c568831SAndroid Build Coastguard Worker 		    /*
1551*7c568831SAndroid Build Coastguard Worker 		     * duplicate a transition based on atom to count next
1552*7c568831SAndroid Build Coastguard Worker 		     * occurrences after 1. We cannot loop to atom->start
1553*7c568831SAndroid Build Coastguard Worker 		     * directly because we need an epsilon transition to
1554*7c568831SAndroid Build Coastguard Worker 		     * newstate.
1555*7c568831SAndroid Build Coastguard Worker 		     */
1556*7c568831SAndroid Build Coastguard Worker 		     /* ???? For some reason it seems we never reach that
1557*7c568831SAndroid Build Coastguard Worker 		        case, I suppose this got optimized out before when
1558*7c568831SAndroid Build Coastguard Worker 			building the automata */
1559*7c568831SAndroid Build Coastguard Worker 		    copy = xmlRegCopyAtom(ctxt, atom);
1560*7c568831SAndroid Build Coastguard Worker 		    if (copy == NULL)
1561*7c568831SAndroid Build Coastguard Worker 		        return(-1);
1562*7c568831SAndroid Build Coastguard Worker 		    copy->quant = XML_REGEXP_QUANT_ONCE;
1563*7c568831SAndroid Build Coastguard Worker 		    copy->min = 0;
1564*7c568831SAndroid Build Coastguard Worker 		    copy->max = 0;
1565*7c568831SAndroid Build Coastguard Worker 
1566*7c568831SAndroid Build Coastguard Worker 		    if (xmlFAGenerateTransitions(ctxt, atom->start, NULL, copy)
1567*7c568831SAndroid Build Coastguard Worker 		        < 0) {
1568*7c568831SAndroid Build Coastguard Worker                         xmlRegFreeAtom(copy);
1569*7c568831SAndroid Build Coastguard Worker 			return(-1);
1570*7c568831SAndroid Build Coastguard Worker                     }
1571*7c568831SAndroid Build Coastguard Worker 		    inter = ctxt->state;
1572*7c568831SAndroid Build Coastguard Worker 		    counter = xmlRegGetCounter(ctxt);
1573*7c568831SAndroid Build Coastguard Worker                     if (counter < 0)
1574*7c568831SAndroid Build Coastguard Worker                         return(-1);
1575*7c568831SAndroid Build Coastguard Worker 		    ctxt->counters[counter].min = atom->min - 1;
1576*7c568831SAndroid Build Coastguard Worker 		    ctxt->counters[counter].max = atom->max - 1;
1577*7c568831SAndroid Build Coastguard Worker 		    /* count the number of times we see it again */
1578*7c568831SAndroid Build Coastguard Worker 		    xmlFAGenerateCountedEpsilonTransition(ctxt, inter,
1579*7c568831SAndroid Build Coastguard Worker 						   atom->stop, counter);
1580*7c568831SAndroid Build Coastguard Worker 		    /* allow a way out based on the count */
1581*7c568831SAndroid Build Coastguard Worker 		    xmlFAGenerateCountedTransition(ctxt, inter,
1582*7c568831SAndroid Build Coastguard Worker 			                           newstate, counter);
1583*7c568831SAndroid Build Coastguard Worker 		    /* and also allow a direct exit for 0 */
1584*7c568831SAndroid Build Coastguard Worker 		    xmlFAGenerateEpsilonTransition(ctxt, atom->start,
1585*7c568831SAndroid Build Coastguard Worker 		                                   newstate);
1586*7c568831SAndroid Build Coastguard Worker 		} else {
1587*7c568831SAndroid Build Coastguard Worker 		    /*
1588*7c568831SAndroid Build Coastguard Worker 		     * either we need the atom at least once or there
1589*7c568831SAndroid Build Coastguard Worker 		     * is an atom->start0 allowing to easily plug the
1590*7c568831SAndroid Build Coastguard Worker 		     * epsilon transition.
1591*7c568831SAndroid Build Coastguard Worker 		     */
1592*7c568831SAndroid Build Coastguard Worker 		    counter = xmlRegGetCounter(ctxt);
1593*7c568831SAndroid Build Coastguard Worker                     if (counter < 0)
1594*7c568831SAndroid Build Coastguard Worker                         return(-1);
1595*7c568831SAndroid Build Coastguard Worker 		    ctxt->counters[counter].min = atom->min - 1;
1596*7c568831SAndroid Build Coastguard Worker 		    ctxt->counters[counter].max = atom->max - 1;
1597*7c568831SAndroid Build Coastguard Worker 		    /* allow a way out based on the count */
1598*7c568831SAndroid Build Coastguard Worker 		    xmlFAGenerateCountedTransition(ctxt, atom->stop,
1599*7c568831SAndroid Build Coastguard Worker 			                           newstate, counter);
1600*7c568831SAndroid Build Coastguard Worker 		    /* count the number of times we see it again */
1601*7c568831SAndroid Build Coastguard Worker 		    xmlFAGenerateCountedEpsilonTransition(ctxt, atom->stop,
1602*7c568831SAndroid Build Coastguard Worker 						   atom->start, counter);
1603*7c568831SAndroid Build Coastguard Worker 		    /* and if needed allow a direct exit for 0 */
1604*7c568831SAndroid Build Coastguard Worker 		    if (atom->min == 0)
1605*7c568831SAndroid Build Coastguard Worker 			xmlFAGenerateEpsilonTransition(ctxt, atom->start0,
1606*7c568831SAndroid Build Coastguard Worker 						       newstate);
1607*7c568831SAndroid Build Coastguard Worker 
1608*7c568831SAndroid Build Coastguard Worker 		}
1609*7c568831SAndroid Build Coastguard Worker 		atom->min = 0;
1610*7c568831SAndroid Build Coastguard Worker 		atom->max = 0;
1611*7c568831SAndroid Build Coastguard Worker 		atom->quant = XML_REGEXP_QUANT_ONCE;
1612*7c568831SAndroid Build Coastguard Worker 		ctxt->state = newstate;
1613*7c568831SAndroid Build Coastguard Worker 	    }
1614*7c568831SAndroid Build Coastguard Worker 	    default:
1615*7c568831SAndroid Build Coastguard Worker 		break;
1616*7c568831SAndroid Build Coastguard Worker 	}
1617*7c568831SAndroid Build Coastguard Worker 	if (xmlRegAtomPush(ctxt, atom) < 0)
1618*7c568831SAndroid Build Coastguard Worker 	    return(-1);
1619*7c568831SAndroid Build Coastguard Worker 	return(0);
1620*7c568831SAndroid Build Coastguard Worker     }
1621*7c568831SAndroid Build Coastguard Worker     if ((atom->min == 0) && (atom->max == 0) &&
1622*7c568831SAndroid Build Coastguard Worker                (atom->quant == XML_REGEXP_QUANT_RANGE)) {
1623*7c568831SAndroid Build Coastguard Worker         /*
1624*7c568831SAndroid Build Coastguard Worker 	 * we can discard the atom and generate an epsilon transition instead
1625*7c568831SAndroid Build Coastguard Worker 	 */
1626*7c568831SAndroid Build Coastguard Worker 	if (to == NULL) {
1627*7c568831SAndroid Build Coastguard Worker 	    to = xmlRegStatePush(ctxt);
1628*7c568831SAndroid Build Coastguard Worker 	    if (to == NULL)
1629*7c568831SAndroid Build Coastguard Worker 		return(-1);
1630*7c568831SAndroid Build Coastguard Worker 	}
1631*7c568831SAndroid Build Coastguard Worker 	xmlFAGenerateEpsilonTransition(ctxt, from, to);
1632*7c568831SAndroid Build Coastguard Worker 	ctxt->state = to;
1633*7c568831SAndroid Build Coastguard Worker 	xmlRegFreeAtom(atom);
1634*7c568831SAndroid Build Coastguard Worker 	return(0);
1635*7c568831SAndroid Build Coastguard Worker     }
1636*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
1637*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(ctxt);
1638*7c568831SAndroid Build Coastguard Worker 	if (to == NULL)
1639*7c568831SAndroid Build Coastguard Worker 	    return(-1);
1640*7c568831SAndroid Build Coastguard Worker     }
1641*7c568831SAndroid Build Coastguard Worker     end = to;
1642*7c568831SAndroid Build Coastguard Worker     if ((atom->quant == XML_REGEXP_QUANT_MULT) ||
1643*7c568831SAndroid Build Coastguard Worker         (atom->quant == XML_REGEXP_QUANT_PLUS)) {
1644*7c568831SAndroid Build Coastguard Worker 	/*
1645*7c568831SAndroid Build Coastguard Worker 	 * Do not pollute the target state by adding transitions from
1646*7c568831SAndroid Build Coastguard Worker 	 * it as it is likely to be the shared target of multiple branches.
1647*7c568831SAndroid Build Coastguard Worker 	 * So isolate with an epsilon transition.
1648*7c568831SAndroid Build Coastguard Worker 	 */
1649*7c568831SAndroid Build Coastguard Worker         xmlRegStatePtr tmp;
1650*7c568831SAndroid Build Coastguard Worker 
1651*7c568831SAndroid Build Coastguard Worker 	tmp = xmlRegStatePush(ctxt);
1652*7c568831SAndroid Build Coastguard Worker         if (tmp == NULL)
1653*7c568831SAndroid Build Coastguard Worker 	    return(-1);
1654*7c568831SAndroid Build Coastguard Worker 	xmlFAGenerateEpsilonTransition(ctxt, tmp, to);
1655*7c568831SAndroid Build Coastguard Worker 	to = tmp;
1656*7c568831SAndroid Build Coastguard Worker     }
1657*7c568831SAndroid Build Coastguard Worker     if ((atom->quant == XML_REGEXP_QUANT_RANGE) &&
1658*7c568831SAndroid Build Coastguard Worker         (atom->min == 0) && (atom->max > 0)) {
1659*7c568831SAndroid Build Coastguard Worker 	nullable = 1;
1660*7c568831SAndroid Build Coastguard Worker 	atom->min = 1;
1661*7c568831SAndroid Build Coastguard Worker         if (atom->max == 1)
1662*7c568831SAndroid Build Coastguard Worker 	    atom->quant = XML_REGEXP_QUANT_OPT;
1663*7c568831SAndroid Build Coastguard Worker     }
1664*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTrans(ctxt, from, atom, to, -1, -1);
1665*7c568831SAndroid Build Coastguard Worker     ctxt->state = end;
1666*7c568831SAndroid Build Coastguard Worker     switch (atom->quant) {
1667*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_QUANT_OPT:
1668*7c568831SAndroid Build Coastguard Worker 	    atom->quant = XML_REGEXP_QUANT_ONCE;
1669*7c568831SAndroid Build Coastguard Worker 	    xmlFAGenerateEpsilonTransition(ctxt, from, to);
1670*7c568831SAndroid Build Coastguard Worker 	    break;
1671*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_QUANT_MULT:
1672*7c568831SAndroid Build Coastguard Worker 	    atom->quant = XML_REGEXP_QUANT_ONCE;
1673*7c568831SAndroid Build Coastguard Worker 	    xmlFAGenerateEpsilonTransition(ctxt, from, to);
1674*7c568831SAndroid Build Coastguard Worker 	    xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1);
1675*7c568831SAndroid Build Coastguard Worker 	    break;
1676*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_QUANT_PLUS:
1677*7c568831SAndroid Build Coastguard Worker 	    atom->quant = XML_REGEXP_QUANT_ONCE;
1678*7c568831SAndroid Build Coastguard Worker 	    xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1);
1679*7c568831SAndroid Build Coastguard Worker 	    break;
1680*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_QUANT_RANGE:
1681*7c568831SAndroid Build Coastguard Worker 	    if (nullable)
1682*7c568831SAndroid Build Coastguard Worker 		xmlFAGenerateEpsilonTransition(ctxt, from, to);
1683*7c568831SAndroid Build Coastguard Worker 	    break;
1684*7c568831SAndroid Build Coastguard Worker 	default:
1685*7c568831SAndroid Build Coastguard Worker 	    break;
1686*7c568831SAndroid Build Coastguard Worker     }
1687*7c568831SAndroid Build Coastguard Worker     if (xmlRegAtomPush(ctxt, atom) < 0)
1688*7c568831SAndroid Build Coastguard Worker 	return(-1);
1689*7c568831SAndroid Build Coastguard Worker     return(0);
1690*7c568831SAndroid Build Coastguard Worker }
1691*7c568831SAndroid Build Coastguard Worker 
1692*7c568831SAndroid Build Coastguard Worker /**
1693*7c568831SAndroid Build Coastguard Worker  * xmlFAReduceEpsilonTransitions:
1694*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1695*7c568831SAndroid Build Coastguard Worker  * @fromnr:  the from state
1696*7c568831SAndroid Build Coastguard Worker  * @tonr:  the to state
1697*7c568831SAndroid Build Coastguard Worker  * @counter:  should that transition be associated to a counted
1698*7c568831SAndroid Build Coastguard Worker  *
1699*7c568831SAndroid Build Coastguard Worker  */
1700*7c568831SAndroid Build Coastguard Worker static void
xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt,int fromnr,int tonr,int counter)1701*7c568831SAndroid Build Coastguard Worker xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr,
1702*7c568831SAndroid Build Coastguard Worker 	                      int tonr, int counter) {
1703*7c568831SAndroid Build Coastguard Worker     int transnr;
1704*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr from;
1705*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr to;
1706*7c568831SAndroid Build Coastguard Worker 
1707*7c568831SAndroid Build Coastguard Worker     from = ctxt->states[fromnr];
1708*7c568831SAndroid Build Coastguard Worker     if (from == NULL)
1709*7c568831SAndroid Build Coastguard Worker 	return;
1710*7c568831SAndroid Build Coastguard Worker     to = ctxt->states[tonr];
1711*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
1712*7c568831SAndroid Build Coastguard Worker 	return;
1713*7c568831SAndroid Build Coastguard Worker     if ((to->mark == XML_REGEXP_MARK_START) ||
1714*7c568831SAndroid Build Coastguard Worker 	(to->mark == XML_REGEXP_MARK_VISITED))
1715*7c568831SAndroid Build Coastguard Worker 	return;
1716*7c568831SAndroid Build Coastguard Worker 
1717*7c568831SAndroid Build Coastguard Worker     to->mark = XML_REGEXP_MARK_VISITED;
1718*7c568831SAndroid Build Coastguard Worker     if (to->type == XML_REGEXP_FINAL_STATE) {
1719*7c568831SAndroid Build Coastguard Worker 	from->type = XML_REGEXP_FINAL_STATE;
1720*7c568831SAndroid Build Coastguard Worker     }
1721*7c568831SAndroid Build Coastguard Worker     for (transnr = 0;transnr < to->nbTrans;transnr++) {
1722*7c568831SAndroid Build Coastguard Worker         xmlRegTransPtr t1 = &to->trans[transnr];
1723*7c568831SAndroid Build Coastguard Worker         int tcounter;
1724*7c568831SAndroid Build Coastguard Worker 
1725*7c568831SAndroid Build Coastguard Worker         if (t1->to < 0)
1726*7c568831SAndroid Build Coastguard Worker 	    continue;
1727*7c568831SAndroid Build Coastguard Worker         if (t1->counter >= 0) {
1728*7c568831SAndroid Build Coastguard Worker             /* assert(counter < 0); */
1729*7c568831SAndroid Build Coastguard Worker             tcounter = t1->counter;
1730*7c568831SAndroid Build Coastguard Worker         } else {
1731*7c568831SAndroid Build Coastguard Worker             tcounter = counter;
1732*7c568831SAndroid Build Coastguard Worker         }
1733*7c568831SAndroid Build Coastguard Worker 	if (t1->atom == NULL) {
1734*7c568831SAndroid Build Coastguard Worker 	    /*
1735*7c568831SAndroid Build Coastguard Worker 	     * Don't remove counted transitions
1736*7c568831SAndroid Build Coastguard Worker 	     * Don't loop either
1737*7c568831SAndroid Build Coastguard Worker 	     */
1738*7c568831SAndroid Build Coastguard Worker 	    if (t1->to != fromnr) {
1739*7c568831SAndroid Build Coastguard Worker 		if (t1->count >= 0) {
1740*7c568831SAndroid Build Coastguard Worker 		    xmlRegStateAddTrans(ctxt, from, NULL, ctxt->states[t1->to],
1741*7c568831SAndroid Build Coastguard Worker 					-1, t1->count);
1742*7c568831SAndroid Build Coastguard Worker 		} else {
1743*7c568831SAndroid Build Coastguard Worker                     xmlFAReduceEpsilonTransitions(ctxt, fromnr, t1->to,
1744*7c568831SAndroid Build Coastguard Worker                                                   tcounter);
1745*7c568831SAndroid Build Coastguard Worker 		}
1746*7c568831SAndroid Build Coastguard Worker 	    }
1747*7c568831SAndroid Build Coastguard Worker 	} else {
1748*7c568831SAndroid Build Coastguard Worker             xmlRegStateAddTrans(ctxt, from, t1->atom,
1749*7c568831SAndroid Build Coastguard Worker                                 ctxt->states[t1->to], tcounter, -1);
1750*7c568831SAndroid Build Coastguard Worker 	}
1751*7c568831SAndroid Build Coastguard Worker     }
1752*7c568831SAndroid Build Coastguard Worker }
1753*7c568831SAndroid Build Coastguard Worker 
1754*7c568831SAndroid Build Coastguard Worker /**
1755*7c568831SAndroid Build Coastguard Worker  * xmlFAFinishReduceEpsilonTransitions:
1756*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1757*7c568831SAndroid Build Coastguard Worker  * @fromnr:  the from state
1758*7c568831SAndroid Build Coastguard Worker  * @tonr:  the to state
1759*7c568831SAndroid Build Coastguard Worker  * @counter:  should that transition be associated to a counted
1760*7c568831SAndroid Build Coastguard Worker  *
1761*7c568831SAndroid Build Coastguard Worker  */
1762*7c568831SAndroid Build Coastguard Worker static void
xmlFAFinishReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt,int tonr)1763*7c568831SAndroid Build Coastguard Worker xmlFAFinishReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int tonr) {
1764*7c568831SAndroid Build Coastguard Worker     int transnr;
1765*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr to;
1766*7c568831SAndroid Build Coastguard Worker 
1767*7c568831SAndroid Build Coastguard Worker     to = ctxt->states[tonr];
1768*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
1769*7c568831SAndroid Build Coastguard Worker 	return;
1770*7c568831SAndroid Build Coastguard Worker     if ((to->mark == XML_REGEXP_MARK_START) ||
1771*7c568831SAndroid Build Coastguard Worker 	(to->mark == XML_REGEXP_MARK_NORMAL))
1772*7c568831SAndroid Build Coastguard Worker 	return;
1773*7c568831SAndroid Build Coastguard Worker 
1774*7c568831SAndroid Build Coastguard Worker     to->mark = XML_REGEXP_MARK_NORMAL;
1775*7c568831SAndroid Build Coastguard Worker     for (transnr = 0;transnr < to->nbTrans;transnr++) {
1776*7c568831SAndroid Build Coastguard Worker 	xmlRegTransPtr t1 = &to->trans[transnr];
1777*7c568831SAndroid Build Coastguard Worker 	if ((t1->to >= 0) && (t1->atom == NULL))
1778*7c568831SAndroid Build Coastguard Worker             xmlFAFinishReduceEpsilonTransitions(ctxt, t1->to);
1779*7c568831SAndroid Build Coastguard Worker     }
1780*7c568831SAndroid Build Coastguard Worker }
1781*7c568831SAndroid Build Coastguard Worker 
1782*7c568831SAndroid Build Coastguard Worker /**
1783*7c568831SAndroid Build Coastguard Worker  * xmlFAEliminateSimpleEpsilonTransitions:
1784*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1785*7c568831SAndroid Build Coastguard Worker  *
1786*7c568831SAndroid Build Coastguard Worker  * Eliminating general epsilon transitions can get costly in the general
1787*7c568831SAndroid Build Coastguard Worker  * algorithm due to the large amount of generated new transitions and
1788*7c568831SAndroid Build Coastguard Worker  * associated comparisons. However for simple epsilon transition used just
1789*7c568831SAndroid Build Coastguard Worker  * to separate building blocks when generating the automata this can be
1790*7c568831SAndroid Build Coastguard Worker  * reduced to state elimination:
1791*7c568831SAndroid Build Coastguard Worker  *    - if there exists an epsilon from X to Y
1792*7c568831SAndroid Build Coastguard Worker  *    - if there is no other transition from X
1793*7c568831SAndroid Build Coastguard Worker  * then X and Y are semantically equivalent and X can be eliminated
1794*7c568831SAndroid Build Coastguard Worker  * If X is the start state then make Y the start state, else replace the
1795*7c568831SAndroid Build Coastguard Worker  * target of all transitions to X by transitions to Y.
1796*7c568831SAndroid Build Coastguard Worker  *
1797*7c568831SAndroid Build Coastguard Worker  * If X is a final state, skip it.
1798*7c568831SAndroid Build Coastguard Worker  * Otherwise it would be necessary to manipulate counters for this case when
1799*7c568831SAndroid Build Coastguard Worker  * eliminating state 2:
1800*7c568831SAndroid Build Coastguard Worker  * State 1 has a transition with an atom to state 2.
1801*7c568831SAndroid Build Coastguard Worker  * State 2 is final and has an epsilon transition to state 1.
1802*7c568831SAndroid Build Coastguard Worker  */
1803*7c568831SAndroid Build Coastguard Worker static void
xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt)1804*7c568831SAndroid Build Coastguard Worker xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
1805*7c568831SAndroid Build Coastguard Worker     int statenr, i, j, newto;
1806*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr state, tmp;
1807*7c568831SAndroid Build Coastguard Worker 
1808*7c568831SAndroid Build Coastguard Worker     for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
1809*7c568831SAndroid Build Coastguard Worker 	state = ctxt->states[statenr];
1810*7c568831SAndroid Build Coastguard Worker 	if (state == NULL)
1811*7c568831SAndroid Build Coastguard Worker 	    continue;
1812*7c568831SAndroid Build Coastguard Worker 	if (state->nbTrans != 1)
1813*7c568831SAndroid Build Coastguard Worker 	    continue;
1814*7c568831SAndroid Build Coastguard Worker        if (state->type == XML_REGEXP_UNREACH_STATE ||
1815*7c568831SAndroid Build Coastguard Worker            state->type == XML_REGEXP_FINAL_STATE)
1816*7c568831SAndroid Build Coastguard Worker 	    continue;
1817*7c568831SAndroid Build Coastguard Worker 	/* is the only transition out a basic transition */
1818*7c568831SAndroid Build Coastguard Worker 	if ((state->trans[0].atom == NULL) &&
1819*7c568831SAndroid Build Coastguard Worker 	    (state->trans[0].to >= 0) &&
1820*7c568831SAndroid Build Coastguard Worker 	    (state->trans[0].to != statenr) &&
1821*7c568831SAndroid Build Coastguard Worker 	    (state->trans[0].counter < 0) &&
1822*7c568831SAndroid Build Coastguard Worker 	    (state->trans[0].count < 0)) {
1823*7c568831SAndroid Build Coastguard Worker 	    newto = state->trans[0].to;
1824*7c568831SAndroid Build Coastguard Worker 
1825*7c568831SAndroid Build Coastguard Worker             if (state->type == XML_REGEXP_START_STATE) {
1826*7c568831SAndroid Build Coastguard Worker             } else {
1827*7c568831SAndroid Build Coastguard Worker 	        for (i = 0;i < state->nbTransTo;i++) {
1828*7c568831SAndroid Build Coastguard Worker 		    tmp = ctxt->states[state->transTo[i]];
1829*7c568831SAndroid Build Coastguard Worker 		    for (j = 0;j < tmp->nbTrans;j++) {
1830*7c568831SAndroid Build Coastguard Worker 			if (tmp->trans[j].to == statenr) {
1831*7c568831SAndroid Build Coastguard Worker 			    tmp->trans[j].to = -1;
1832*7c568831SAndroid Build Coastguard Worker 			    xmlRegStateAddTrans(ctxt, tmp, tmp->trans[j].atom,
1833*7c568831SAndroid Build Coastguard Worker 						ctxt->states[newto],
1834*7c568831SAndroid Build Coastguard Worker 					        tmp->trans[j].counter,
1835*7c568831SAndroid Build Coastguard Worker 						tmp->trans[j].count);
1836*7c568831SAndroid Build Coastguard Worker 			}
1837*7c568831SAndroid Build Coastguard Worker 		    }
1838*7c568831SAndroid Build Coastguard Worker 		}
1839*7c568831SAndroid Build Coastguard Worker 		if (state->type == XML_REGEXP_FINAL_STATE)
1840*7c568831SAndroid Build Coastguard Worker 		    ctxt->states[newto]->type = XML_REGEXP_FINAL_STATE;
1841*7c568831SAndroid Build Coastguard Worker 		/* eliminate the transition completely */
1842*7c568831SAndroid Build Coastguard Worker 		state->nbTrans = 0;
1843*7c568831SAndroid Build Coastguard Worker 
1844*7c568831SAndroid Build Coastguard Worker                 state->type = XML_REGEXP_UNREACH_STATE;
1845*7c568831SAndroid Build Coastguard Worker 
1846*7c568831SAndroid Build Coastguard Worker 	    }
1847*7c568831SAndroid Build Coastguard Worker 
1848*7c568831SAndroid Build Coastguard Worker 	}
1849*7c568831SAndroid Build Coastguard Worker     }
1850*7c568831SAndroid Build Coastguard Worker }
1851*7c568831SAndroid Build Coastguard Worker /**
1852*7c568831SAndroid Build Coastguard Worker  * xmlFAEliminateEpsilonTransitions:
1853*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
1854*7c568831SAndroid Build Coastguard Worker  *
1855*7c568831SAndroid Build Coastguard Worker  */
1856*7c568831SAndroid Build Coastguard Worker static void
xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt)1857*7c568831SAndroid Build Coastguard Worker xmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
1858*7c568831SAndroid Build Coastguard Worker     int statenr, transnr;
1859*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr state;
1860*7c568831SAndroid Build Coastguard Worker     int has_epsilon;
1861*7c568831SAndroid Build Coastguard Worker 
1862*7c568831SAndroid Build Coastguard Worker     if (ctxt->states == NULL) return;
1863*7c568831SAndroid Build Coastguard Worker 
1864*7c568831SAndroid Build Coastguard Worker     /*
1865*7c568831SAndroid Build Coastguard Worker      * Eliminate simple epsilon transition and the associated unreachable
1866*7c568831SAndroid Build Coastguard Worker      * states.
1867*7c568831SAndroid Build Coastguard Worker      */
1868*7c568831SAndroid Build Coastguard Worker     xmlFAEliminateSimpleEpsilonTransitions(ctxt);
1869*7c568831SAndroid Build Coastguard Worker     for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
1870*7c568831SAndroid Build Coastguard Worker 	state = ctxt->states[statenr];
1871*7c568831SAndroid Build Coastguard Worker 	if ((state != NULL) && (state->type == XML_REGEXP_UNREACH_STATE)) {
1872*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeState(state);
1873*7c568831SAndroid Build Coastguard Worker 	    ctxt->states[statenr] = NULL;
1874*7c568831SAndroid Build Coastguard Worker 	}
1875*7c568831SAndroid Build Coastguard Worker     }
1876*7c568831SAndroid Build Coastguard Worker 
1877*7c568831SAndroid Build Coastguard Worker     has_epsilon = 0;
1878*7c568831SAndroid Build Coastguard Worker 
1879*7c568831SAndroid Build Coastguard Worker     /*
1880*7c568831SAndroid Build Coastguard Worker      * Build the completed transitions bypassing the epsilons
1881*7c568831SAndroid Build Coastguard Worker      * Use a marking algorithm to avoid loops
1882*7c568831SAndroid Build Coastguard Worker      * Mark sink states too.
1883*7c568831SAndroid Build Coastguard Worker      * Process from the latest states backward to the start when
1884*7c568831SAndroid Build Coastguard Worker      * there is long cascading epsilon chains this minimize the
1885*7c568831SAndroid Build Coastguard Worker      * recursions and transition compares when adding the new ones
1886*7c568831SAndroid Build Coastguard Worker      */
1887*7c568831SAndroid Build Coastguard Worker     for (statenr = ctxt->nbStates - 1;statenr >= 0;statenr--) {
1888*7c568831SAndroid Build Coastguard Worker 	state = ctxt->states[statenr];
1889*7c568831SAndroid Build Coastguard Worker 	if (state == NULL)
1890*7c568831SAndroid Build Coastguard Worker 	    continue;
1891*7c568831SAndroid Build Coastguard Worker 	if ((state->nbTrans == 0) &&
1892*7c568831SAndroid Build Coastguard Worker 	    (state->type != XML_REGEXP_FINAL_STATE)) {
1893*7c568831SAndroid Build Coastguard Worker 	    state->type = XML_REGEXP_SINK_STATE;
1894*7c568831SAndroid Build Coastguard Worker 	}
1895*7c568831SAndroid Build Coastguard Worker 	for (transnr = 0;transnr < state->nbTrans;transnr++) {
1896*7c568831SAndroid Build Coastguard Worker 	    if ((state->trans[transnr].atom == NULL) &&
1897*7c568831SAndroid Build Coastguard Worker 		(state->trans[transnr].to >= 0)) {
1898*7c568831SAndroid Build Coastguard Worker 		if (state->trans[transnr].to == statenr) {
1899*7c568831SAndroid Build Coastguard Worker 		    state->trans[transnr].to = -1;
1900*7c568831SAndroid Build Coastguard Worker 		} else if (state->trans[transnr].count < 0) {
1901*7c568831SAndroid Build Coastguard Worker 		    int newto = state->trans[transnr].to;
1902*7c568831SAndroid Build Coastguard Worker 
1903*7c568831SAndroid Build Coastguard Worker 		    has_epsilon = 1;
1904*7c568831SAndroid Build Coastguard Worker 		    state->trans[transnr].to = -2;
1905*7c568831SAndroid Build Coastguard Worker 		    state->mark = XML_REGEXP_MARK_START;
1906*7c568831SAndroid Build Coastguard Worker 		    xmlFAReduceEpsilonTransitions(ctxt, statenr,
1907*7c568831SAndroid Build Coastguard Worker 				      newto, state->trans[transnr].counter);
1908*7c568831SAndroid Build Coastguard Worker 		    xmlFAFinishReduceEpsilonTransitions(ctxt, newto);
1909*7c568831SAndroid Build Coastguard Worker 		    state->mark = XML_REGEXP_MARK_NORMAL;
1910*7c568831SAndroid Build Coastguard Worker 	        }
1911*7c568831SAndroid Build Coastguard Worker 	    }
1912*7c568831SAndroid Build Coastguard Worker 	}
1913*7c568831SAndroid Build Coastguard Worker     }
1914*7c568831SAndroid Build Coastguard Worker     /*
1915*7c568831SAndroid Build Coastguard Worker      * Eliminate the epsilon transitions
1916*7c568831SAndroid Build Coastguard Worker      */
1917*7c568831SAndroid Build Coastguard Worker     if (has_epsilon) {
1918*7c568831SAndroid Build Coastguard Worker 	for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
1919*7c568831SAndroid Build Coastguard Worker 	    state = ctxt->states[statenr];
1920*7c568831SAndroid Build Coastguard Worker 	    if (state == NULL)
1921*7c568831SAndroid Build Coastguard Worker 		continue;
1922*7c568831SAndroid Build Coastguard Worker 	    for (transnr = 0;transnr < state->nbTrans;transnr++) {
1923*7c568831SAndroid Build Coastguard Worker 		xmlRegTransPtr trans = &(state->trans[transnr]);
1924*7c568831SAndroid Build Coastguard Worker 		if ((trans->atom == NULL) &&
1925*7c568831SAndroid Build Coastguard Worker 		    (trans->count < 0) &&
1926*7c568831SAndroid Build Coastguard Worker 		    (trans->to >= 0)) {
1927*7c568831SAndroid Build Coastguard Worker 		    trans->to = -1;
1928*7c568831SAndroid Build Coastguard Worker 		}
1929*7c568831SAndroid Build Coastguard Worker 	    }
1930*7c568831SAndroid Build Coastguard Worker 	}
1931*7c568831SAndroid Build Coastguard Worker     }
1932*7c568831SAndroid Build Coastguard Worker 
1933*7c568831SAndroid Build Coastguard Worker     /*
1934*7c568831SAndroid Build Coastguard Worker      * Use this pass to detect unreachable states too
1935*7c568831SAndroid Build Coastguard Worker      */
1936*7c568831SAndroid Build Coastguard Worker     for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
1937*7c568831SAndroid Build Coastguard Worker 	state = ctxt->states[statenr];
1938*7c568831SAndroid Build Coastguard Worker 	if (state != NULL)
1939*7c568831SAndroid Build Coastguard Worker 	    state->reached = XML_REGEXP_MARK_NORMAL;
1940*7c568831SAndroid Build Coastguard Worker     }
1941*7c568831SAndroid Build Coastguard Worker     state = ctxt->states[0];
1942*7c568831SAndroid Build Coastguard Worker     if (state != NULL)
1943*7c568831SAndroid Build Coastguard Worker 	state->reached = XML_REGEXP_MARK_START;
1944*7c568831SAndroid Build Coastguard Worker     while (state != NULL) {
1945*7c568831SAndroid Build Coastguard Worker 	xmlRegStatePtr target = NULL;
1946*7c568831SAndroid Build Coastguard Worker 	state->reached = XML_REGEXP_MARK_VISITED;
1947*7c568831SAndroid Build Coastguard Worker 	/*
1948*7c568831SAndroid Build Coastguard Worker 	 * Mark all states reachable from the current reachable state
1949*7c568831SAndroid Build Coastguard Worker 	 */
1950*7c568831SAndroid Build Coastguard Worker 	for (transnr = 0;transnr < state->nbTrans;transnr++) {
1951*7c568831SAndroid Build Coastguard Worker 	    if ((state->trans[transnr].to >= 0) &&
1952*7c568831SAndroid Build Coastguard Worker 		((state->trans[transnr].atom != NULL) ||
1953*7c568831SAndroid Build Coastguard Worker 		 (state->trans[transnr].count >= 0))) {
1954*7c568831SAndroid Build Coastguard Worker 		int newto = state->trans[transnr].to;
1955*7c568831SAndroid Build Coastguard Worker 
1956*7c568831SAndroid Build Coastguard Worker 		if (ctxt->states[newto] == NULL)
1957*7c568831SAndroid Build Coastguard Worker 		    continue;
1958*7c568831SAndroid Build Coastguard Worker 		if (ctxt->states[newto]->reached == XML_REGEXP_MARK_NORMAL) {
1959*7c568831SAndroid Build Coastguard Worker 		    ctxt->states[newto]->reached = XML_REGEXP_MARK_START;
1960*7c568831SAndroid Build Coastguard Worker 		    target = ctxt->states[newto];
1961*7c568831SAndroid Build Coastguard Worker 		}
1962*7c568831SAndroid Build Coastguard Worker 	    }
1963*7c568831SAndroid Build Coastguard Worker 	}
1964*7c568831SAndroid Build Coastguard Worker 
1965*7c568831SAndroid Build Coastguard Worker 	/*
1966*7c568831SAndroid Build Coastguard Worker 	 * find the next accessible state not explored
1967*7c568831SAndroid Build Coastguard Worker 	 */
1968*7c568831SAndroid Build Coastguard Worker 	if (target == NULL) {
1969*7c568831SAndroid Build Coastguard Worker 	    for (statenr = 1;statenr < ctxt->nbStates;statenr++) {
1970*7c568831SAndroid Build Coastguard Worker 		state = ctxt->states[statenr];
1971*7c568831SAndroid Build Coastguard Worker 		if ((state != NULL) && (state->reached ==
1972*7c568831SAndroid Build Coastguard Worker 			XML_REGEXP_MARK_START)) {
1973*7c568831SAndroid Build Coastguard Worker 		    target = state;
1974*7c568831SAndroid Build Coastguard Worker 		    break;
1975*7c568831SAndroid Build Coastguard Worker 		}
1976*7c568831SAndroid Build Coastguard Worker 	    }
1977*7c568831SAndroid Build Coastguard Worker 	}
1978*7c568831SAndroid Build Coastguard Worker 	state = target;
1979*7c568831SAndroid Build Coastguard Worker     }
1980*7c568831SAndroid Build Coastguard Worker     for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
1981*7c568831SAndroid Build Coastguard Worker 	state = ctxt->states[statenr];
1982*7c568831SAndroid Build Coastguard Worker 	if ((state != NULL) && (state->reached == XML_REGEXP_MARK_NORMAL)) {
1983*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeState(state);
1984*7c568831SAndroid Build Coastguard Worker 	    ctxt->states[statenr] = NULL;
1985*7c568831SAndroid Build Coastguard Worker 	}
1986*7c568831SAndroid Build Coastguard Worker     }
1987*7c568831SAndroid Build Coastguard Worker 
1988*7c568831SAndroid Build Coastguard Worker }
1989*7c568831SAndroid Build Coastguard Worker 
1990*7c568831SAndroid Build Coastguard Worker static int
xmlFACompareRanges(xmlRegRangePtr range1,xmlRegRangePtr range2)1991*7c568831SAndroid Build Coastguard Worker xmlFACompareRanges(xmlRegRangePtr range1, xmlRegRangePtr range2) {
1992*7c568831SAndroid Build Coastguard Worker     int ret = 0;
1993*7c568831SAndroid Build Coastguard Worker 
1994*7c568831SAndroid Build Coastguard Worker     if ((range1->type == XML_REGEXP_RANGES) ||
1995*7c568831SAndroid Build Coastguard Worker         (range2->type == XML_REGEXP_RANGES) ||
1996*7c568831SAndroid Build Coastguard Worker         (range2->type == XML_REGEXP_SUBREG) ||
1997*7c568831SAndroid Build Coastguard Worker         (range1->type == XML_REGEXP_SUBREG) ||
1998*7c568831SAndroid Build Coastguard Worker         (range1->type == XML_REGEXP_STRING) ||
1999*7c568831SAndroid Build Coastguard Worker         (range2->type == XML_REGEXP_STRING))
2000*7c568831SAndroid Build Coastguard Worker 	return(-1);
2001*7c568831SAndroid Build Coastguard Worker 
2002*7c568831SAndroid Build Coastguard Worker     /* put them in order */
2003*7c568831SAndroid Build Coastguard Worker     if (range1->type > range2->type) {
2004*7c568831SAndroid Build Coastguard Worker         xmlRegRangePtr tmp;
2005*7c568831SAndroid Build Coastguard Worker 
2006*7c568831SAndroid Build Coastguard Worker 	tmp = range1;
2007*7c568831SAndroid Build Coastguard Worker 	range1 = range2;
2008*7c568831SAndroid Build Coastguard Worker 	range2 = tmp;
2009*7c568831SAndroid Build Coastguard Worker     }
2010*7c568831SAndroid Build Coastguard Worker     if ((range1->type == XML_REGEXP_ANYCHAR) ||
2011*7c568831SAndroid Build Coastguard Worker         (range2->type == XML_REGEXP_ANYCHAR)) {
2012*7c568831SAndroid Build Coastguard Worker 	ret = 1;
2013*7c568831SAndroid Build Coastguard Worker     } else if ((range1->type == XML_REGEXP_EPSILON) ||
2014*7c568831SAndroid Build Coastguard Worker                (range2->type == XML_REGEXP_EPSILON)) {
2015*7c568831SAndroid Build Coastguard Worker 	return(0);
2016*7c568831SAndroid Build Coastguard Worker     } else if (range1->type == range2->type) {
2017*7c568831SAndroid Build Coastguard Worker         if (range1->type != XML_REGEXP_CHARVAL)
2018*7c568831SAndroid Build Coastguard Worker             ret = 1;
2019*7c568831SAndroid Build Coastguard Worker         else if ((range1->end < range2->start) ||
2020*7c568831SAndroid Build Coastguard Worker 	         (range2->end < range1->start))
2021*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2022*7c568831SAndroid Build Coastguard Worker 	else
2023*7c568831SAndroid Build Coastguard Worker 	    ret = 1;
2024*7c568831SAndroid Build Coastguard Worker     } else if (range1->type == XML_REGEXP_CHARVAL) {
2025*7c568831SAndroid Build Coastguard Worker         int codepoint;
2026*7c568831SAndroid Build Coastguard Worker 	int neg = 0;
2027*7c568831SAndroid Build Coastguard Worker 
2028*7c568831SAndroid Build Coastguard Worker 	/*
2029*7c568831SAndroid Build Coastguard Worker 	 * just check all codepoints in the range for acceptance,
2030*7c568831SAndroid Build Coastguard Worker 	 * this is usually way cheaper since done only once at
2031*7c568831SAndroid Build Coastguard Worker 	 * compilation than testing over and over at runtime or
2032*7c568831SAndroid Build Coastguard Worker 	 * pushing too many states when evaluating.
2033*7c568831SAndroid Build Coastguard Worker 	 */
2034*7c568831SAndroid Build Coastguard Worker 	if (((range1->neg == 0) && (range2->neg != 0)) ||
2035*7c568831SAndroid Build Coastguard Worker 	    ((range1->neg != 0) && (range2->neg == 0)))
2036*7c568831SAndroid Build Coastguard Worker 	    neg = 1;
2037*7c568831SAndroid Build Coastguard Worker 
2038*7c568831SAndroid Build Coastguard Worker 	for (codepoint = range1->start;codepoint <= range1->end ;codepoint++) {
2039*7c568831SAndroid Build Coastguard Worker 	    ret = xmlRegCheckCharacterRange(range2->type, codepoint,
2040*7c568831SAndroid Build Coastguard Worker 					    0, range2->start, range2->end,
2041*7c568831SAndroid Build Coastguard Worker 					    range2->blockName);
2042*7c568831SAndroid Build Coastguard Worker 	    if (ret < 0)
2043*7c568831SAndroid Build Coastguard Worker 	        return(-1);
2044*7c568831SAndroid Build Coastguard Worker 	    if (((neg == 1) && (ret == 0)) ||
2045*7c568831SAndroid Build Coastguard Worker 	        ((neg == 0) && (ret == 1)))
2046*7c568831SAndroid Build Coastguard Worker 		return(1);
2047*7c568831SAndroid Build Coastguard Worker 	}
2048*7c568831SAndroid Build Coastguard Worker 	return(0);
2049*7c568831SAndroid Build Coastguard Worker     } else if ((range1->type == XML_REGEXP_BLOCK_NAME) ||
2050*7c568831SAndroid Build Coastguard Worker                (range2->type == XML_REGEXP_BLOCK_NAME)) {
2051*7c568831SAndroid Build Coastguard Worker 	if (range1->type == range2->type) {
2052*7c568831SAndroid Build Coastguard Worker 	    ret = xmlStrEqual(range1->blockName, range2->blockName);
2053*7c568831SAndroid Build Coastguard Worker 	} else {
2054*7c568831SAndroid Build Coastguard Worker 	    /*
2055*7c568831SAndroid Build Coastguard Worker 	     * comparing a block range with anything else is way
2056*7c568831SAndroid Build Coastguard Worker 	     * too costly, and maintaining the table is like too much
2057*7c568831SAndroid Build Coastguard Worker 	     * memory too, so let's force the automata to save state
2058*7c568831SAndroid Build Coastguard Worker 	     * here.
2059*7c568831SAndroid Build Coastguard Worker 	     */
2060*7c568831SAndroid Build Coastguard Worker 	    return(1);
2061*7c568831SAndroid Build Coastguard Worker 	}
2062*7c568831SAndroid Build Coastguard Worker     } else if ((range1->type < XML_REGEXP_LETTER) ||
2063*7c568831SAndroid Build Coastguard Worker                (range2->type < XML_REGEXP_LETTER)) {
2064*7c568831SAndroid Build Coastguard Worker 	if ((range1->type == XML_REGEXP_ANYSPACE) &&
2065*7c568831SAndroid Build Coastguard Worker 	    (range2->type == XML_REGEXP_NOTSPACE))
2066*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2067*7c568831SAndroid Build Coastguard Worker 	else if ((range1->type == XML_REGEXP_INITNAME) &&
2068*7c568831SAndroid Build Coastguard Worker 	         (range2->type == XML_REGEXP_NOTINITNAME))
2069*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2070*7c568831SAndroid Build Coastguard Worker 	else if ((range1->type == XML_REGEXP_NAMECHAR) &&
2071*7c568831SAndroid Build Coastguard Worker 	         (range2->type == XML_REGEXP_NOTNAMECHAR))
2072*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2073*7c568831SAndroid Build Coastguard Worker 	else if ((range1->type == XML_REGEXP_DECIMAL) &&
2074*7c568831SAndroid Build Coastguard Worker 	         (range2->type == XML_REGEXP_NOTDECIMAL))
2075*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2076*7c568831SAndroid Build Coastguard Worker 	else if ((range1->type == XML_REGEXP_REALCHAR) &&
2077*7c568831SAndroid Build Coastguard Worker 	         (range2->type == XML_REGEXP_NOTREALCHAR))
2078*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2079*7c568831SAndroid Build Coastguard Worker 	else {
2080*7c568831SAndroid Build Coastguard Worker 	    /* same thing to limit complexity */
2081*7c568831SAndroid Build Coastguard Worker 	    return(1);
2082*7c568831SAndroid Build Coastguard Worker 	}
2083*7c568831SAndroid Build Coastguard Worker     } else {
2084*7c568831SAndroid Build Coastguard Worker         ret = 0;
2085*7c568831SAndroid Build Coastguard Worker         /* range1->type < range2->type here */
2086*7c568831SAndroid Build Coastguard Worker         switch (range1->type) {
2087*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_LETTER:
2088*7c568831SAndroid Build Coastguard Worker 	         /* all disjoint except in the subgroups */
2089*7c568831SAndroid Build Coastguard Worker 	         if ((range2->type == XML_REGEXP_LETTER_UPPERCASE) ||
2090*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_LETTER_LOWERCASE) ||
2091*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_LETTER_TITLECASE) ||
2092*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_LETTER_MODIFIER) ||
2093*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_LETTER_OTHERS))
2094*7c568831SAndroid Build Coastguard Worker 		     ret = 1;
2095*7c568831SAndroid Build Coastguard Worker 		 break;
2096*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_MARK:
2097*7c568831SAndroid Build Coastguard Worker 	         if ((range2->type == XML_REGEXP_MARK_NONSPACING) ||
2098*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_MARK_SPACECOMBINING) ||
2099*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_MARK_ENCLOSING))
2100*7c568831SAndroid Build Coastguard Worker 		     ret = 1;
2101*7c568831SAndroid Build Coastguard Worker 		 break;
2102*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_NUMBER:
2103*7c568831SAndroid Build Coastguard Worker 	         if ((range2->type == XML_REGEXP_NUMBER_DECIMAL) ||
2104*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_NUMBER_LETTER) ||
2105*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_NUMBER_OTHERS))
2106*7c568831SAndroid Build Coastguard Worker 		     ret = 1;
2107*7c568831SAndroid Build Coastguard Worker 		 break;
2108*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_PUNCT:
2109*7c568831SAndroid Build Coastguard Worker 	         if ((range2->type == XML_REGEXP_PUNCT_CONNECTOR) ||
2110*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_PUNCT_DASH) ||
2111*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_PUNCT_OPEN) ||
2112*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_PUNCT_CLOSE) ||
2113*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_PUNCT_INITQUOTE) ||
2114*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_PUNCT_FINQUOTE) ||
2115*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_PUNCT_OTHERS))
2116*7c568831SAndroid Build Coastguard Worker 		     ret = 1;
2117*7c568831SAndroid Build Coastguard Worker 		 break;
2118*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_SEPAR:
2119*7c568831SAndroid Build Coastguard Worker 	         if ((range2->type == XML_REGEXP_SEPAR_SPACE) ||
2120*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_SEPAR_LINE) ||
2121*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_SEPAR_PARA))
2122*7c568831SAndroid Build Coastguard Worker 		     ret = 1;
2123*7c568831SAndroid Build Coastguard Worker 		 break;
2124*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_SYMBOL:
2125*7c568831SAndroid Build Coastguard Worker 	         if ((range2->type == XML_REGEXP_SYMBOL_MATH) ||
2126*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_SYMBOL_CURRENCY) ||
2127*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_SYMBOL_MODIFIER) ||
2128*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_SYMBOL_OTHERS))
2129*7c568831SAndroid Build Coastguard Worker 		     ret = 1;
2130*7c568831SAndroid Build Coastguard Worker 		 break;
2131*7c568831SAndroid Build Coastguard Worker 	    case XML_REGEXP_OTHER:
2132*7c568831SAndroid Build Coastguard Worker 	         if ((range2->type == XML_REGEXP_OTHER_CONTROL) ||
2133*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_OTHER_FORMAT) ||
2134*7c568831SAndroid Build Coastguard Worker 		     (range2->type == XML_REGEXP_OTHER_PRIVATE))
2135*7c568831SAndroid Build Coastguard Worker 		     ret = 1;
2136*7c568831SAndroid Build Coastguard Worker 		 break;
2137*7c568831SAndroid Build Coastguard Worker             default:
2138*7c568831SAndroid Build Coastguard Worker 	         if ((range2->type >= XML_REGEXP_LETTER) &&
2139*7c568831SAndroid Build Coastguard Worker 		     (range2->type < XML_REGEXP_BLOCK_NAME))
2140*7c568831SAndroid Build Coastguard Worker 		     ret = 0;
2141*7c568831SAndroid Build Coastguard Worker 		 else {
2142*7c568831SAndroid Build Coastguard Worker 		     /* safety net ! */
2143*7c568831SAndroid Build Coastguard Worker 		     return(1);
2144*7c568831SAndroid Build Coastguard Worker 		 }
2145*7c568831SAndroid Build Coastguard Worker 	}
2146*7c568831SAndroid Build Coastguard Worker     }
2147*7c568831SAndroid Build Coastguard Worker     if (((range1->neg == 0) && (range2->neg != 0)) ||
2148*7c568831SAndroid Build Coastguard Worker         ((range1->neg != 0) && (range2->neg == 0)))
2149*7c568831SAndroid Build Coastguard Worker 	ret = !ret;
2150*7c568831SAndroid Build Coastguard Worker     return(ret);
2151*7c568831SAndroid Build Coastguard Worker }
2152*7c568831SAndroid Build Coastguard Worker 
2153*7c568831SAndroid Build Coastguard Worker /**
2154*7c568831SAndroid Build Coastguard Worker  * xmlFACompareAtomTypes:
2155*7c568831SAndroid Build Coastguard Worker  * @type1:  an atom type
2156*7c568831SAndroid Build Coastguard Worker  * @type2:  an atom type
2157*7c568831SAndroid Build Coastguard Worker  *
2158*7c568831SAndroid Build Coastguard Worker  * Compares two atoms type to check whether they intersect in some ways,
2159*7c568831SAndroid Build Coastguard Worker  * this is used by xmlFACompareAtoms only
2160*7c568831SAndroid Build Coastguard Worker  *
2161*7c568831SAndroid Build Coastguard Worker  * Returns 1 if they may intersect and 0 otherwise
2162*7c568831SAndroid Build Coastguard Worker  */
2163*7c568831SAndroid Build Coastguard Worker static int
xmlFACompareAtomTypes(xmlRegAtomType type1,xmlRegAtomType type2)2164*7c568831SAndroid Build Coastguard Worker xmlFACompareAtomTypes(xmlRegAtomType type1, xmlRegAtomType type2) {
2165*7c568831SAndroid Build Coastguard Worker     if ((type1 == XML_REGEXP_EPSILON) ||
2166*7c568831SAndroid Build Coastguard Worker         (type1 == XML_REGEXP_CHARVAL) ||
2167*7c568831SAndroid Build Coastguard Worker 	(type1 == XML_REGEXP_RANGES) ||
2168*7c568831SAndroid Build Coastguard Worker 	(type1 == XML_REGEXP_SUBREG) ||
2169*7c568831SAndroid Build Coastguard Worker 	(type1 == XML_REGEXP_STRING) ||
2170*7c568831SAndroid Build Coastguard Worker 	(type1 == XML_REGEXP_ANYCHAR))
2171*7c568831SAndroid Build Coastguard Worker 	return(1);
2172*7c568831SAndroid Build Coastguard Worker     if ((type2 == XML_REGEXP_EPSILON) ||
2173*7c568831SAndroid Build Coastguard Worker         (type2 == XML_REGEXP_CHARVAL) ||
2174*7c568831SAndroid Build Coastguard Worker 	(type2 == XML_REGEXP_RANGES) ||
2175*7c568831SAndroid Build Coastguard Worker 	(type2 == XML_REGEXP_SUBREG) ||
2176*7c568831SAndroid Build Coastguard Worker 	(type2 == XML_REGEXP_STRING) ||
2177*7c568831SAndroid Build Coastguard Worker 	(type2 == XML_REGEXP_ANYCHAR))
2178*7c568831SAndroid Build Coastguard Worker 	return(1);
2179*7c568831SAndroid Build Coastguard Worker 
2180*7c568831SAndroid Build Coastguard Worker     if (type1 == type2) return(1);
2181*7c568831SAndroid Build Coastguard Worker 
2182*7c568831SAndroid Build Coastguard Worker     /* simplify subsequent compares by making sure type1 < type2 */
2183*7c568831SAndroid Build Coastguard Worker     if (type1 > type2) {
2184*7c568831SAndroid Build Coastguard Worker         xmlRegAtomType tmp = type1;
2185*7c568831SAndroid Build Coastguard Worker 	type1 = type2;
2186*7c568831SAndroid Build Coastguard Worker 	type2 = tmp;
2187*7c568831SAndroid Build Coastguard Worker     }
2188*7c568831SAndroid Build Coastguard Worker     switch (type1) {
2189*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_ANYSPACE: /* \s */
2190*7c568831SAndroid Build Coastguard Worker 	    /* can't be a letter, number, mark, punctuation, symbol */
2191*7c568831SAndroid Build Coastguard Worker 	    if ((type2 == XML_REGEXP_NOTSPACE) ||
2192*7c568831SAndroid Build Coastguard Worker 		((type2 >= XML_REGEXP_LETTER) &&
2193*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_LETTER_OTHERS)) ||
2194*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_NUMBER) &&
2195*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_NUMBER_OTHERS)) ||
2196*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_MARK) &&
2197*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2198*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_PUNCT) &&
2199*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2200*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SYMBOL) &&
2201*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SYMBOL_OTHERS))
2202*7c568831SAndroid Build Coastguard Worker 	        ) return(0);
2203*7c568831SAndroid Build Coastguard Worker 	    break;
2204*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTSPACE: /* \S */
2205*7c568831SAndroid Build Coastguard Worker 	    break;
2206*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_INITNAME: /* \l */
2207*7c568831SAndroid Build Coastguard Worker 	    /* can't be a number, mark, separator, punctuation, symbol or other */
2208*7c568831SAndroid Build Coastguard Worker 	    if ((type2 == XML_REGEXP_NOTINITNAME) ||
2209*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_NUMBER) &&
2210*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_NUMBER_OTHERS)) ||
2211*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_MARK) &&
2212*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2213*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SEPAR) &&
2214*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2215*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_PUNCT) &&
2216*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2217*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SYMBOL) &&
2218*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2219*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_OTHER) &&
2220*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_OTHER_NA))
2221*7c568831SAndroid Build Coastguard Worker 		) return(0);
2222*7c568831SAndroid Build Coastguard Worker 	    break;
2223*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTINITNAME: /* \L */
2224*7c568831SAndroid Build Coastguard Worker 	    break;
2225*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NAMECHAR: /* \c */
2226*7c568831SAndroid Build Coastguard Worker 	    /* can't be a mark, separator, punctuation, symbol or other */
2227*7c568831SAndroid Build Coastguard Worker 	    if ((type2 == XML_REGEXP_NOTNAMECHAR) ||
2228*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_MARK) &&
2229*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2230*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_PUNCT) &&
2231*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2232*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SEPAR) &&
2233*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2234*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SYMBOL) &&
2235*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2236*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_OTHER) &&
2237*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_OTHER_NA))
2238*7c568831SAndroid Build Coastguard Worker 		) return(0);
2239*7c568831SAndroid Build Coastguard Worker 	    break;
2240*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTNAMECHAR: /* \C */
2241*7c568831SAndroid Build Coastguard Worker 	    break;
2242*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_DECIMAL: /* \d */
2243*7c568831SAndroid Build Coastguard Worker 	    /* can't be a letter, mark, separator, punctuation, symbol or other */
2244*7c568831SAndroid Build Coastguard Worker 	    if ((type2 == XML_REGEXP_NOTDECIMAL) ||
2245*7c568831SAndroid Build Coastguard Worker 	        (type2 == XML_REGEXP_REALCHAR) ||
2246*7c568831SAndroid Build Coastguard Worker 		((type2 >= XML_REGEXP_LETTER) &&
2247*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_LETTER_OTHERS)) ||
2248*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_MARK) &&
2249*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2250*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_PUNCT) &&
2251*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2252*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SEPAR) &&
2253*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2254*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SYMBOL) &&
2255*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2256*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_OTHER) &&
2257*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_OTHER_NA))
2258*7c568831SAndroid Build Coastguard Worker 		)return(0);
2259*7c568831SAndroid Build Coastguard Worker 	    break;
2260*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTDECIMAL: /* \D */
2261*7c568831SAndroid Build Coastguard Worker 	    break;
2262*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_REALCHAR: /* \w */
2263*7c568831SAndroid Build Coastguard Worker 	    /* can't be a mark, separator, punctuation, symbol or other */
2264*7c568831SAndroid Build Coastguard Worker 	    if ((type2 == XML_REGEXP_NOTDECIMAL) ||
2265*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_MARK) &&
2266*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2267*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_PUNCT) &&
2268*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2269*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SEPAR) &&
2270*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2271*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_SYMBOL) &&
2272*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2273*7c568831SAndroid Build Coastguard Worker 	        ((type2 >= XML_REGEXP_OTHER) &&
2274*7c568831SAndroid Build Coastguard Worker 		 (type2 <= XML_REGEXP_OTHER_NA))
2275*7c568831SAndroid Build Coastguard Worker 		)return(0);
2276*7c568831SAndroid Build Coastguard Worker 	    break;
2277*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTREALCHAR: /* \W */
2278*7c568831SAndroid Build Coastguard Worker 	    break;
2279*7c568831SAndroid Build Coastguard Worker 	/*
2280*7c568831SAndroid Build Coastguard Worker 	 * at that point we know both type 1 and type2 are from
2281*7c568831SAndroid Build Coastguard Worker 	 * character categories are ordered and are different,
2282*7c568831SAndroid Build Coastguard Worker 	 * it becomes simple because this is a partition
2283*7c568831SAndroid Build Coastguard Worker 	 */
2284*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER:
2285*7c568831SAndroid Build Coastguard Worker 	    if (type2 <= XML_REGEXP_LETTER_OTHERS)
2286*7c568831SAndroid Build Coastguard Worker 	        return(1);
2287*7c568831SAndroid Build Coastguard Worker 	    return(0);
2288*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_UPPERCASE:
2289*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_LOWERCASE:
2290*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_TITLECASE:
2291*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_MODIFIER:
2292*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_OTHERS:
2293*7c568831SAndroid Build Coastguard Worker 	    return(0);
2294*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK:
2295*7c568831SAndroid Build Coastguard Worker 	    if (type2 <= XML_REGEXP_MARK_ENCLOSING)
2296*7c568831SAndroid Build Coastguard Worker 	        return(1);
2297*7c568831SAndroid Build Coastguard Worker 	    return(0);
2298*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_NONSPACING:
2299*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_SPACECOMBINING:
2300*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_ENCLOSING:
2301*7c568831SAndroid Build Coastguard Worker 	    return(0);
2302*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER:
2303*7c568831SAndroid Build Coastguard Worker 	    if (type2 <= XML_REGEXP_NUMBER_OTHERS)
2304*7c568831SAndroid Build Coastguard Worker 	        return(1);
2305*7c568831SAndroid Build Coastguard Worker 	    return(0);
2306*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_DECIMAL:
2307*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_LETTER:
2308*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_OTHERS:
2309*7c568831SAndroid Build Coastguard Worker 	    return(0);
2310*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT:
2311*7c568831SAndroid Build Coastguard Worker 	    if (type2 <= XML_REGEXP_PUNCT_OTHERS)
2312*7c568831SAndroid Build Coastguard Worker 	        return(1);
2313*7c568831SAndroid Build Coastguard Worker 	    return(0);
2314*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_CONNECTOR:
2315*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_DASH:
2316*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_OPEN:
2317*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_CLOSE:
2318*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_INITQUOTE:
2319*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_FINQUOTE:
2320*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_OTHERS:
2321*7c568831SAndroid Build Coastguard Worker 	    return(0);
2322*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR:
2323*7c568831SAndroid Build Coastguard Worker 	    if (type2 <= XML_REGEXP_SEPAR_PARA)
2324*7c568831SAndroid Build Coastguard Worker 	        return(1);
2325*7c568831SAndroid Build Coastguard Worker 	    return(0);
2326*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_SPACE:
2327*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_LINE:
2328*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_PARA:
2329*7c568831SAndroid Build Coastguard Worker 	    return(0);
2330*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL:
2331*7c568831SAndroid Build Coastguard Worker 	    if (type2 <= XML_REGEXP_SYMBOL_OTHERS)
2332*7c568831SAndroid Build Coastguard Worker 	        return(1);
2333*7c568831SAndroid Build Coastguard Worker 	    return(0);
2334*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_MATH:
2335*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_CURRENCY:
2336*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_MODIFIER:
2337*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_OTHERS:
2338*7c568831SAndroid Build Coastguard Worker 	    return(0);
2339*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER:
2340*7c568831SAndroid Build Coastguard Worker 	    if (type2 <= XML_REGEXP_OTHER_NA)
2341*7c568831SAndroid Build Coastguard Worker 	        return(1);
2342*7c568831SAndroid Build Coastguard Worker 	    return(0);
2343*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_CONTROL:
2344*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_FORMAT:
2345*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_PRIVATE:
2346*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_NA:
2347*7c568831SAndroid Build Coastguard Worker 	    return(0);
2348*7c568831SAndroid Build Coastguard Worker 	default:
2349*7c568831SAndroid Build Coastguard Worker 	    break;
2350*7c568831SAndroid Build Coastguard Worker     }
2351*7c568831SAndroid Build Coastguard Worker     return(1);
2352*7c568831SAndroid Build Coastguard Worker }
2353*7c568831SAndroid Build Coastguard Worker 
2354*7c568831SAndroid Build Coastguard Worker /**
2355*7c568831SAndroid Build Coastguard Worker  * xmlFAEqualAtoms:
2356*7c568831SAndroid Build Coastguard Worker  * @atom1:  an atom
2357*7c568831SAndroid Build Coastguard Worker  * @atom2:  an atom
2358*7c568831SAndroid Build Coastguard Worker  * @deep: if not set only compare string pointers
2359*7c568831SAndroid Build Coastguard Worker  *
2360*7c568831SAndroid Build Coastguard Worker  * Compares two atoms to check whether they are the same exactly
2361*7c568831SAndroid Build Coastguard Worker  * this is used to remove equivalent transitions
2362*7c568831SAndroid Build Coastguard Worker  *
2363*7c568831SAndroid Build Coastguard Worker  * Returns 1 if same and 0 otherwise
2364*7c568831SAndroid Build Coastguard Worker  */
2365*7c568831SAndroid Build Coastguard Worker static int
xmlFAEqualAtoms(xmlRegAtomPtr atom1,xmlRegAtomPtr atom2,int deep)2366*7c568831SAndroid Build Coastguard Worker xmlFAEqualAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2, int deep) {
2367*7c568831SAndroid Build Coastguard Worker     int ret = 0;
2368*7c568831SAndroid Build Coastguard Worker 
2369*7c568831SAndroid Build Coastguard Worker     if (atom1 == atom2)
2370*7c568831SAndroid Build Coastguard Worker 	return(1);
2371*7c568831SAndroid Build Coastguard Worker     if ((atom1 == NULL) || (atom2 == NULL))
2372*7c568831SAndroid Build Coastguard Worker 	return(0);
2373*7c568831SAndroid Build Coastguard Worker 
2374*7c568831SAndroid Build Coastguard Worker     if (atom1->type != atom2->type)
2375*7c568831SAndroid Build Coastguard Worker         return(0);
2376*7c568831SAndroid Build Coastguard Worker     switch (atom1->type) {
2377*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_EPSILON:
2378*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2379*7c568831SAndroid Build Coastguard Worker 	    break;
2380*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_STRING:
2381*7c568831SAndroid Build Coastguard Worker             if (!deep)
2382*7c568831SAndroid Build Coastguard Worker                 ret = (atom1->valuep == atom2->valuep);
2383*7c568831SAndroid Build Coastguard Worker             else
2384*7c568831SAndroid Build Coastguard Worker                 ret = xmlStrEqual((xmlChar *)atom1->valuep,
2385*7c568831SAndroid Build Coastguard Worker                                   (xmlChar *)atom2->valuep);
2386*7c568831SAndroid Build Coastguard Worker 	    break;
2387*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_CHARVAL:
2388*7c568831SAndroid Build Coastguard Worker 	    ret = (atom1->codepoint == atom2->codepoint);
2389*7c568831SAndroid Build Coastguard Worker 	    break;
2390*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_RANGES:
2391*7c568831SAndroid Build Coastguard Worker 	    /* too hard to do in the general case */
2392*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2393*7c568831SAndroid Build Coastguard Worker 	default:
2394*7c568831SAndroid Build Coastguard Worker 	    break;
2395*7c568831SAndroid Build Coastguard Worker     }
2396*7c568831SAndroid Build Coastguard Worker     return(ret);
2397*7c568831SAndroid Build Coastguard Worker }
2398*7c568831SAndroid Build Coastguard Worker 
2399*7c568831SAndroid Build Coastguard Worker /**
2400*7c568831SAndroid Build Coastguard Worker  * xmlFACompareAtoms:
2401*7c568831SAndroid Build Coastguard Worker  * @atom1:  an atom
2402*7c568831SAndroid Build Coastguard Worker  * @atom2:  an atom
2403*7c568831SAndroid Build Coastguard Worker  * @deep: if not set only compare string pointers
2404*7c568831SAndroid Build Coastguard Worker  *
2405*7c568831SAndroid Build Coastguard Worker  * Compares two atoms to check whether they intersect in some ways,
2406*7c568831SAndroid Build Coastguard Worker  * this is used by xmlFAComputesDeterminism and xmlFARecurseDeterminism only
2407*7c568831SAndroid Build Coastguard Worker  *
2408*7c568831SAndroid Build Coastguard Worker  * Returns 1 if yes and 0 otherwise
2409*7c568831SAndroid Build Coastguard Worker  */
2410*7c568831SAndroid Build Coastguard Worker static int
xmlFACompareAtoms(xmlRegAtomPtr atom1,xmlRegAtomPtr atom2,int deep)2411*7c568831SAndroid Build Coastguard Worker xmlFACompareAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2, int deep) {
2412*7c568831SAndroid Build Coastguard Worker     int ret = 1;
2413*7c568831SAndroid Build Coastguard Worker 
2414*7c568831SAndroid Build Coastguard Worker     if (atom1 == atom2)
2415*7c568831SAndroid Build Coastguard Worker 	return(1);
2416*7c568831SAndroid Build Coastguard Worker     if ((atom1 == NULL) || (atom2 == NULL))
2417*7c568831SAndroid Build Coastguard Worker 	return(0);
2418*7c568831SAndroid Build Coastguard Worker 
2419*7c568831SAndroid Build Coastguard Worker     if ((atom1->type == XML_REGEXP_ANYCHAR) ||
2420*7c568831SAndroid Build Coastguard Worker         (atom2->type == XML_REGEXP_ANYCHAR))
2421*7c568831SAndroid Build Coastguard Worker 	return(1);
2422*7c568831SAndroid Build Coastguard Worker 
2423*7c568831SAndroid Build Coastguard Worker     if (atom1->type > atom2->type) {
2424*7c568831SAndroid Build Coastguard Worker 	xmlRegAtomPtr tmp;
2425*7c568831SAndroid Build Coastguard Worker 	tmp = atom1;
2426*7c568831SAndroid Build Coastguard Worker 	atom1 = atom2;
2427*7c568831SAndroid Build Coastguard Worker 	atom2 = tmp;
2428*7c568831SAndroid Build Coastguard Worker     }
2429*7c568831SAndroid Build Coastguard Worker     if (atom1->type != atom2->type) {
2430*7c568831SAndroid Build Coastguard Worker         ret = xmlFACompareAtomTypes(atom1->type, atom2->type);
2431*7c568831SAndroid Build Coastguard Worker 	/* if they can't intersect at the type level break now */
2432*7c568831SAndroid Build Coastguard Worker 	if (ret == 0)
2433*7c568831SAndroid Build Coastguard Worker 	    return(0);
2434*7c568831SAndroid Build Coastguard Worker     }
2435*7c568831SAndroid Build Coastguard Worker     switch (atom1->type) {
2436*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_STRING:
2437*7c568831SAndroid Build Coastguard Worker             if (!deep)
2438*7c568831SAndroid Build Coastguard Worker                 ret = (atom1->valuep != atom2->valuep);
2439*7c568831SAndroid Build Coastguard Worker             else {
2440*7c568831SAndroid Build Coastguard Worker                 xmlChar *val1 = (xmlChar *)atom1->valuep;
2441*7c568831SAndroid Build Coastguard Worker                 xmlChar *val2 = (xmlChar *)atom2->valuep;
2442*7c568831SAndroid Build Coastguard Worker                 int compound1 = (xmlStrchr(val1, '|') != NULL);
2443*7c568831SAndroid Build Coastguard Worker                 int compound2 = (xmlStrchr(val2, '|') != NULL);
2444*7c568831SAndroid Build Coastguard Worker 
2445*7c568831SAndroid Build Coastguard Worker                 /* Ignore negative match flag for ##other namespaces */
2446*7c568831SAndroid Build Coastguard Worker                 if (compound1 != compound2)
2447*7c568831SAndroid Build Coastguard Worker                     return(0);
2448*7c568831SAndroid Build Coastguard Worker 
2449*7c568831SAndroid Build Coastguard Worker                 ret = xmlRegStrEqualWildcard(val1, val2);
2450*7c568831SAndroid Build Coastguard Worker             }
2451*7c568831SAndroid Build Coastguard Worker 	    break;
2452*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_EPSILON:
2453*7c568831SAndroid Build Coastguard Worker 	    goto not_determinist;
2454*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_CHARVAL:
2455*7c568831SAndroid Build Coastguard Worker 	    if (atom2->type == XML_REGEXP_CHARVAL) {
2456*7c568831SAndroid Build Coastguard Worker 		ret = (atom1->codepoint == atom2->codepoint);
2457*7c568831SAndroid Build Coastguard Worker 	    } else {
2458*7c568831SAndroid Build Coastguard Worker 	        ret = xmlRegCheckCharacter(atom2, atom1->codepoint);
2459*7c568831SAndroid Build Coastguard Worker 		if (ret < 0)
2460*7c568831SAndroid Build Coastguard Worker 		    ret = 1;
2461*7c568831SAndroid Build Coastguard Worker 	    }
2462*7c568831SAndroid Build Coastguard Worker 	    break;
2463*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_RANGES:
2464*7c568831SAndroid Build Coastguard Worker 	    if (atom2->type == XML_REGEXP_RANGES) {
2465*7c568831SAndroid Build Coastguard Worker 	        int i, j, res;
2466*7c568831SAndroid Build Coastguard Worker 		xmlRegRangePtr r1, r2;
2467*7c568831SAndroid Build Coastguard Worker 
2468*7c568831SAndroid Build Coastguard Worker 		/*
2469*7c568831SAndroid Build Coastguard Worker 		 * need to check that none of the ranges eventually matches
2470*7c568831SAndroid Build Coastguard Worker 		 */
2471*7c568831SAndroid Build Coastguard Worker 		for (i = 0;i < atom1->nbRanges;i++) {
2472*7c568831SAndroid Build Coastguard Worker 		    for (j = 0;j < atom2->nbRanges;j++) {
2473*7c568831SAndroid Build Coastguard Worker 			r1 = atom1->ranges[i];
2474*7c568831SAndroid Build Coastguard Worker 			r2 = atom2->ranges[j];
2475*7c568831SAndroid Build Coastguard Worker 			res = xmlFACompareRanges(r1, r2);
2476*7c568831SAndroid Build Coastguard Worker 			if (res == 1) {
2477*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
2478*7c568831SAndroid Build Coastguard Worker 			    goto done;
2479*7c568831SAndroid Build Coastguard Worker 			}
2480*7c568831SAndroid Build Coastguard Worker 		    }
2481*7c568831SAndroid Build Coastguard Worker 		}
2482*7c568831SAndroid Build Coastguard Worker 		ret = 0;
2483*7c568831SAndroid Build Coastguard Worker 	    }
2484*7c568831SAndroid Build Coastguard Worker 	    break;
2485*7c568831SAndroid Build Coastguard Worker 	default:
2486*7c568831SAndroid Build Coastguard Worker 	    goto not_determinist;
2487*7c568831SAndroid Build Coastguard Worker     }
2488*7c568831SAndroid Build Coastguard Worker done:
2489*7c568831SAndroid Build Coastguard Worker     if (atom1->neg != atom2->neg) {
2490*7c568831SAndroid Build Coastguard Worker         ret = !ret;
2491*7c568831SAndroid Build Coastguard Worker     }
2492*7c568831SAndroid Build Coastguard Worker     if (ret == 0)
2493*7c568831SAndroid Build Coastguard Worker         return(0);
2494*7c568831SAndroid Build Coastguard Worker not_determinist:
2495*7c568831SAndroid Build Coastguard Worker     return(1);
2496*7c568831SAndroid Build Coastguard Worker }
2497*7c568831SAndroid Build Coastguard Worker 
2498*7c568831SAndroid Build Coastguard Worker /**
2499*7c568831SAndroid Build Coastguard Worker  * xmlFARecurseDeterminism:
2500*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
2501*7c568831SAndroid Build Coastguard Worker  *
2502*7c568831SAndroid Build Coastguard Worker  * Check whether the associated regexp is determinist,
2503*7c568831SAndroid Build Coastguard Worker  * should be called after xmlFAEliminateEpsilonTransitions()
2504*7c568831SAndroid Build Coastguard Worker  *
2505*7c568831SAndroid Build Coastguard Worker  */
2506*7c568831SAndroid Build Coastguard Worker static int
xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr state,int fromnr,int tonr,xmlRegAtomPtr atom)2507*7c568831SAndroid Build Coastguard Worker xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
2508*7c568831SAndroid Build Coastguard Worker 	                int fromnr, int tonr, xmlRegAtomPtr atom) {
2509*7c568831SAndroid Build Coastguard Worker     int ret = 1;
2510*7c568831SAndroid Build Coastguard Worker     int res;
2511*7c568831SAndroid Build Coastguard Worker     int transnr, nbTrans;
2512*7c568831SAndroid Build Coastguard Worker     xmlRegTransPtr t1;
2513*7c568831SAndroid Build Coastguard Worker     int deep = 1;
2514*7c568831SAndroid Build Coastguard Worker 
2515*7c568831SAndroid Build Coastguard Worker     if (state == NULL)
2516*7c568831SAndroid Build Coastguard Worker 	return(ret);
2517*7c568831SAndroid Build Coastguard Worker     if (state->markd == XML_REGEXP_MARK_VISITED)
2518*7c568831SAndroid Build Coastguard Worker 	return(ret);
2519*7c568831SAndroid Build Coastguard Worker 
2520*7c568831SAndroid Build Coastguard Worker     if (ctxt->flags & AM_AUTOMATA_RNG)
2521*7c568831SAndroid Build Coastguard Worker         deep = 0;
2522*7c568831SAndroid Build Coastguard Worker 
2523*7c568831SAndroid Build Coastguard Worker     /*
2524*7c568831SAndroid Build Coastguard Worker      * don't recurse on transitions potentially added in the course of
2525*7c568831SAndroid Build Coastguard Worker      * the elimination.
2526*7c568831SAndroid Build Coastguard Worker      */
2527*7c568831SAndroid Build Coastguard Worker     nbTrans = state->nbTrans;
2528*7c568831SAndroid Build Coastguard Worker     for (transnr = 0;transnr < nbTrans;transnr++) {
2529*7c568831SAndroid Build Coastguard Worker 	t1 = &(state->trans[transnr]);
2530*7c568831SAndroid Build Coastguard Worker 	/*
2531*7c568831SAndroid Build Coastguard Worker 	 * check transitions conflicting with the one looked at
2532*7c568831SAndroid Build Coastguard Worker 	 */
2533*7c568831SAndroid Build Coastguard Worker         if ((t1->to < 0) || (t1->to == fromnr))
2534*7c568831SAndroid Build Coastguard Worker             continue;
2535*7c568831SAndroid Build Coastguard Worker 	if (t1->atom == NULL) {
2536*7c568831SAndroid Build Coastguard Worker 	    state->markd = XML_REGEXP_MARK_VISITED;
2537*7c568831SAndroid Build Coastguard Worker 	    res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
2538*7c568831SAndroid Build Coastguard Worker 		                          fromnr, tonr, atom);
2539*7c568831SAndroid Build Coastguard Worker 	    if (res == 0) {
2540*7c568831SAndroid Build Coastguard Worker 	        ret = 0;
2541*7c568831SAndroid Build Coastguard Worker 		/* t1->nd = 1; */
2542*7c568831SAndroid Build Coastguard Worker 	    }
2543*7c568831SAndroid Build Coastguard Worker 	    continue;
2544*7c568831SAndroid Build Coastguard Worker 	}
2545*7c568831SAndroid Build Coastguard Worker 	if (xmlFACompareAtoms(t1->atom, atom, deep)) {
2546*7c568831SAndroid Build Coastguard Worker             /* Treat equal transitions as deterministic. */
2547*7c568831SAndroid Build Coastguard Worker             if ((t1->to != tonr) ||
2548*7c568831SAndroid Build Coastguard Worker                 (!xmlFAEqualAtoms(t1->atom, atom, deep)))
2549*7c568831SAndroid Build Coastguard Worker                 ret = 0;
2550*7c568831SAndroid Build Coastguard Worker 	    /* mark the transition as non-deterministic */
2551*7c568831SAndroid Build Coastguard Worker 	    t1->nd = 1;
2552*7c568831SAndroid Build Coastguard Worker 	}
2553*7c568831SAndroid Build Coastguard Worker     }
2554*7c568831SAndroid Build Coastguard Worker     return(ret);
2555*7c568831SAndroid Build Coastguard Worker }
2556*7c568831SAndroid Build Coastguard Worker 
2557*7c568831SAndroid Build Coastguard Worker /**
2558*7c568831SAndroid Build Coastguard Worker  * xmlFAFinishRecurseDeterminism:
2559*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
2560*7c568831SAndroid Build Coastguard Worker  *
2561*7c568831SAndroid Build Coastguard Worker  * Reset flags after checking determinism.
2562*7c568831SAndroid Build Coastguard Worker  */
2563*7c568831SAndroid Build Coastguard Worker static void
xmlFAFinishRecurseDeterminism(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr state)2564*7c568831SAndroid Build Coastguard Worker xmlFAFinishRecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
2565*7c568831SAndroid Build Coastguard Worker     int transnr, nbTrans;
2566*7c568831SAndroid Build Coastguard Worker 
2567*7c568831SAndroid Build Coastguard Worker     if (state == NULL)
2568*7c568831SAndroid Build Coastguard Worker 	return;
2569*7c568831SAndroid Build Coastguard Worker     if (state->markd != XML_REGEXP_MARK_VISITED)
2570*7c568831SAndroid Build Coastguard Worker 	return;
2571*7c568831SAndroid Build Coastguard Worker     state->markd = 0;
2572*7c568831SAndroid Build Coastguard Worker 
2573*7c568831SAndroid Build Coastguard Worker     nbTrans = state->nbTrans;
2574*7c568831SAndroid Build Coastguard Worker     for (transnr = 0; transnr < nbTrans; transnr++) {
2575*7c568831SAndroid Build Coastguard Worker 	xmlRegTransPtr t1 = &state->trans[transnr];
2576*7c568831SAndroid Build Coastguard Worker 	if ((t1->atom == NULL) && (t1->to >= 0))
2577*7c568831SAndroid Build Coastguard Worker 	    xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t1->to]);
2578*7c568831SAndroid Build Coastguard Worker     }
2579*7c568831SAndroid Build Coastguard Worker }
2580*7c568831SAndroid Build Coastguard Worker 
2581*7c568831SAndroid Build Coastguard Worker /**
2582*7c568831SAndroid Build Coastguard Worker  * xmlFAComputesDeterminism:
2583*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
2584*7c568831SAndroid Build Coastguard Worker  *
2585*7c568831SAndroid Build Coastguard Worker  * Check whether the associated regexp is determinist,
2586*7c568831SAndroid Build Coastguard Worker  * should be called after xmlFAEliminateEpsilonTransitions()
2587*7c568831SAndroid Build Coastguard Worker  *
2588*7c568831SAndroid Build Coastguard Worker  */
2589*7c568831SAndroid Build Coastguard Worker static int
xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt)2590*7c568831SAndroid Build Coastguard Worker xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
2591*7c568831SAndroid Build Coastguard Worker     int statenr, transnr;
2592*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr state;
2593*7c568831SAndroid Build Coastguard Worker     xmlRegTransPtr t1, t2, last;
2594*7c568831SAndroid Build Coastguard Worker     int i;
2595*7c568831SAndroid Build Coastguard Worker     int ret = 1;
2596*7c568831SAndroid Build Coastguard Worker     int deep = 1;
2597*7c568831SAndroid Build Coastguard Worker 
2598*7c568831SAndroid Build Coastguard Worker     if (ctxt->determinist != -1)
2599*7c568831SAndroid Build Coastguard Worker 	return(ctxt->determinist);
2600*7c568831SAndroid Build Coastguard Worker 
2601*7c568831SAndroid Build Coastguard Worker     if (ctxt->flags & AM_AUTOMATA_RNG)
2602*7c568831SAndroid Build Coastguard Worker         deep = 0;
2603*7c568831SAndroid Build Coastguard Worker 
2604*7c568831SAndroid Build Coastguard Worker     /*
2605*7c568831SAndroid Build Coastguard Worker      * First cleanup the automata removing cancelled transitions
2606*7c568831SAndroid Build Coastguard Worker      */
2607*7c568831SAndroid Build Coastguard Worker     for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
2608*7c568831SAndroid Build Coastguard Worker 	state = ctxt->states[statenr];
2609*7c568831SAndroid Build Coastguard Worker 	if (state == NULL)
2610*7c568831SAndroid Build Coastguard Worker 	    continue;
2611*7c568831SAndroid Build Coastguard Worker 	if (state->nbTrans < 2)
2612*7c568831SAndroid Build Coastguard Worker 	    continue;
2613*7c568831SAndroid Build Coastguard Worker 	for (transnr = 0;transnr < state->nbTrans;transnr++) {
2614*7c568831SAndroid Build Coastguard Worker 	    t1 = &(state->trans[transnr]);
2615*7c568831SAndroid Build Coastguard Worker 	    /*
2616*7c568831SAndroid Build Coastguard Worker 	     * Determinism checks in case of counted or all transitions
2617*7c568831SAndroid Build Coastguard Worker 	     * will have to be handled separately
2618*7c568831SAndroid Build Coastguard Worker 	     */
2619*7c568831SAndroid Build Coastguard Worker 	    if (t1->atom == NULL) {
2620*7c568831SAndroid Build Coastguard Worker 		/* t1->nd = 1; */
2621*7c568831SAndroid Build Coastguard Worker 		continue;
2622*7c568831SAndroid Build Coastguard Worker 	    }
2623*7c568831SAndroid Build Coastguard Worker 	    if (t1->to < 0) /* eliminated */
2624*7c568831SAndroid Build Coastguard Worker 		continue;
2625*7c568831SAndroid Build Coastguard Worker 	    for (i = 0;i < transnr;i++) {
2626*7c568831SAndroid Build Coastguard Worker 		t2 = &(state->trans[i]);
2627*7c568831SAndroid Build Coastguard Worker 		if (t2->to < 0) /* eliminated */
2628*7c568831SAndroid Build Coastguard Worker 		    continue;
2629*7c568831SAndroid Build Coastguard Worker 		if (t2->atom != NULL) {
2630*7c568831SAndroid Build Coastguard Worker 		    if (t1->to == t2->to) {
2631*7c568831SAndroid Build Coastguard Worker                         /*
2632*7c568831SAndroid Build Coastguard Worker                          * Here we use deep because we want to keep the
2633*7c568831SAndroid Build Coastguard Worker                          * transitions which indicate a conflict
2634*7c568831SAndroid Build Coastguard Worker                          */
2635*7c568831SAndroid Build Coastguard Worker 			if (xmlFAEqualAtoms(t1->atom, t2->atom, deep) &&
2636*7c568831SAndroid Build Coastguard Worker                             (t1->counter == t2->counter) &&
2637*7c568831SAndroid Build Coastguard Worker                             (t1->count == t2->count))
2638*7c568831SAndroid Build Coastguard Worker 			    t2->to = -1; /* eliminated */
2639*7c568831SAndroid Build Coastguard Worker 		    }
2640*7c568831SAndroid Build Coastguard Worker 		}
2641*7c568831SAndroid Build Coastguard Worker 	    }
2642*7c568831SAndroid Build Coastguard Worker 	}
2643*7c568831SAndroid Build Coastguard Worker     }
2644*7c568831SAndroid Build Coastguard Worker 
2645*7c568831SAndroid Build Coastguard Worker     /*
2646*7c568831SAndroid Build Coastguard Worker      * Check for all states that there aren't 2 transitions
2647*7c568831SAndroid Build Coastguard Worker      * with the same atom and a different target.
2648*7c568831SAndroid Build Coastguard Worker      */
2649*7c568831SAndroid Build Coastguard Worker     for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
2650*7c568831SAndroid Build Coastguard Worker 	state = ctxt->states[statenr];
2651*7c568831SAndroid Build Coastguard Worker 	if (state == NULL)
2652*7c568831SAndroid Build Coastguard Worker 	    continue;
2653*7c568831SAndroid Build Coastguard Worker 	if (state->nbTrans < 2)
2654*7c568831SAndroid Build Coastguard Worker 	    continue;
2655*7c568831SAndroid Build Coastguard Worker 	last = NULL;
2656*7c568831SAndroid Build Coastguard Worker 	for (transnr = 0;transnr < state->nbTrans;transnr++) {
2657*7c568831SAndroid Build Coastguard Worker 	    t1 = &(state->trans[transnr]);
2658*7c568831SAndroid Build Coastguard Worker 	    /*
2659*7c568831SAndroid Build Coastguard Worker 	     * Determinism checks in case of counted or all transitions
2660*7c568831SAndroid Build Coastguard Worker 	     * will have to be handled separately
2661*7c568831SAndroid Build Coastguard Worker 	     */
2662*7c568831SAndroid Build Coastguard Worker 	    if (t1->atom == NULL) {
2663*7c568831SAndroid Build Coastguard Worker 		continue;
2664*7c568831SAndroid Build Coastguard Worker 	    }
2665*7c568831SAndroid Build Coastguard Worker 	    if (t1->to < 0) /* eliminated */
2666*7c568831SAndroid Build Coastguard Worker 		continue;
2667*7c568831SAndroid Build Coastguard Worker 	    for (i = 0;i < transnr;i++) {
2668*7c568831SAndroid Build Coastguard Worker 		t2 = &(state->trans[i]);
2669*7c568831SAndroid Build Coastguard Worker 		if (t2->to < 0) /* eliminated */
2670*7c568831SAndroid Build Coastguard Worker 		    continue;
2671*7c568831SAndroid Build Coastguard Worker 		if (t2->atom != NULL) {
2672*7c568831SAndroid Build Coastguard Worker                     /*
2673*7c568831SAndroid Build Coastguard Worker                      * But here we don't use deep because we want to
2674*7c568831SAndroid Build Coastguard Worker                      * find transitions which indicate a conflict
2675*7c568831SAndroid Build Coastguard Worker                      */
2676*7c568831SAndroid Build Coastguard Worker 		    if (xmlFACompareAtoms(t1->atom, t2->atom, 1)) {
2677*7c568831SAndroid Build Coastguard Worker                         /*
2678*7c568831SAndroid Build Coastguard Worker                          * Treat equal counter transitions that couldn't be
2679*7c568831SAndroid Build Coastguard Worker                          * eliminated as deterministic.
2680*7c568831SAndroid Build Coastguard Worker                          */
2681*7c568831SAndroid Build Coastguard Worker                         if ((t1->to != t2->to) ||
2682*7c568831SAndroid Build Coastguard Worker                             (t1->counter == t2->counter) ||
2683*7c568831SAndroid Build Coastguard Worker                             (!xmlFAEqualAtoms(t1->atom, t2->atom, deep)))
2684*7c568831SAndroid Build Coastguard Worker                             ret = 0;
2685*7c568831SAndroid Build Coastguard Worker 			/* mark the transitions as non-deterministic ones */
2686*7c568831SAndroid Build Coastguard Worker 			t1->nd = 1;
2687*7c568831SAndroid Build Coastguard Worker 			t2->nd = 1;
2688*7c568831SAndroid Build Coastguard Worker 			last = t1;
2689*7c568831SAndroid Build Coastguard Worker 		    }
2690*7c568831SAndroid Build Coastguard Worker 		} else {
2691*7c568831SAndroid Build Coastguard Worker                     int res;
2692*7c568831SAndroid Build Coastguard Worker 
2693*7c568831SAndroid Build Coastguard Worker 		    /*
2694*7c568831SAndroid Build Coastguard Worker 		     * do the closure in case of remaining specific
2695*7c568831SAndroid Build Coastguard Worker 		     * epsilon transitions like choices or all
2696*7c568831SAndroid Build Coastguard Worker 		     */
2697*7c568831SAndroid Build Coastguard Worker 		    res = xmlFARecurseDeterminism(ctxt, ctxt->states[t2->to],
2698*7c568831SAndroid Build Coastguard Worker 						  statenr, t1->to, t1->atom);
2699*7c568831SAndroid Build Coastguard Worker                     xmlFAFinishRecurseDeterminism(ctxt, ctxt->states[t2->to]);
2700*7c568831SAndroid Build Coastguard Worker 		    /* don't shortcut the computation so all non deterministic
2701*7c568831SAndroid Build Coastguard Worker 		       transition get marked down
2702*7c568831SAndroid Build Coastguard Worker 		    if (ret == 0)
2703*7c568831SAndroid Build Coastguard Worker 			return(0);
2704*7c568831SAndroid Build Coastguard Worker 		     */
2705*7c568831SAndroid Build Coastguard Worker 		    if (res == 0) {
2706*7c568831SAndroid Build Coastguard Worker 			t1->nd = 1;
2707*7c568831SAndroid Build Coastguard Worker 			/* t2->nd = 1; */
2708*7c568831SAndroid Build Coastguard Worker 			last = t1;
2709*7c568831SAndroid Build Coastguard Worker                         ret = 0;
2710*7c568831SAndroid Build Coastguard Worker 		    }
2711*7c568831SAndroid Build Coastguard Worker 		}
2712*7c568831SAndroid Build Coastguard Worker 	    }
2713*7c568831SAndroid Build Coastguard Worker 	    /* don't shortcut the computation so all non deterministic
2714*7c568831SAndroid Build Coastguard Worker 	       transition get marked down
2715*7c568831SAndroid Build Coastguard Worker 	    if (ret == 0)
2716*7c568831SAndroid Build Coastguard Worker 		break; */
2717*7c568831SAndroid Build Coastguard Worker 	}
2718*7c568831SAndroid Build Coastguard Worker 
2719*7c568831SAndroid Build Coastguard Worker 	/*
2720*7c568831SAndroid Build Coastguard Worker 	 * mark specifically the last non-deterministic transition
2721*7c568831SAndroid Build Coastguard Worker 	 * from a state since there is no need to set-up rollback
2722*7c568831SAndroid Build Coastguard Worker 	 * from it
2723*7c568831SAndroid Build Coastguard Worker 	 */
2724*7c568831SAndroid Build Coastguard Worker 	if (last != NULL) {
2725*7c568831SAndroid Build Coastguard Worker 	    last->nd = 2;
2726*7c568831SAndroid Build Coastguard Worker 	}
2727*7c568831SAndroid Build Coastguard Worker 
2728*7c568831SAndroid Build Coastguard Worker 	/* don't shortcut the computation so all non deterministic
2729*7c568831SAndroid Build Coastguard Worker 	   transition get marked down
2730*7c568831SAndroid Build Coastguard Worker 	if (ret == 0)
2731*7c568831SAndroid Build Coastguard Worker 	    break; */
2732*7c568831SAndroid Build Coastguard Worker     }
2733*7c568831SAndroid Build Coastguard Worker 
2734*7c568831SAndroid Build Coastguard Worker     ctxt->determinist = ret;
2735*7c568831SAndroid Build Coastguard Worker     return(ret);
2736*7c568831SAndroid Build Coastguard Worker }
2737*7c568831SAndroid Build Coastguard Worker 
2738*7c568831SAndroid Build Coastguard Worker /************************************************************************
2739*7c568831SAndroid Build Coastguard Worker  *									*
2740*7c568831SAndroid Build Coastguard Worker  *	Routines to check input against transition atoms		*
2741*7c568831SAndroid Build Coastguard Worker  *									*
2742*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
2743*7c568831SAndroid Build Coastguard Worker 
2744*7c568831SAndroid Build Coastguard Worker static int
xmlRegCheckCharacterRange(xmlRegAtomType type,int codepoint,int neg,int start,int end,const xmlChar * blockName)2745*7c568831SAndroid Build Coastguard Worker xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint, int neg,
2746*7c568831SAndroid Build Coastguard Worker 	                  int start, int end, const xmlChar *blockName) {
2747*7c568831SAndroid Build Coastguard Worker     int ret = 0;
2748*7c568831SAndroid Build Coastguard Worker 
2749*7c568831SAndroid Build Coastguard Worker     switch (type) {
2750*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_STRING:
2751*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SUBREG:
2752*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_RANGES:
2753*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_EPSILON:
2754*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2755*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_ANYCHAR:
2756*7c568831SAndroid Build Coastguard Worker 	    ret = ((codepoint != '\n') && (codepoint != '\r'));
2757*7c568831SAndroid Build Coastguard Worker 	    break;
2758*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_CHARVAL:
2759*7c568831SAndroid Build Coastguard Worker 	    ret = ((codepoint >= start) && (codepoint <= end));
2760*7c568831SAndroid Build Coastguard Worker 	    break;
2761*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTSPACE:
2762*7c568831SAndroid Build Coastguard Worker 	    neg = !neg;
2763*7c568831SAndroid Build Coastguard Worker             /* Falls through. */
2764*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_ANYSPACE:
2765*7c568831SAndroid Build Coastguard Worker 	    ret = ((codepoint == '\n') || (codepoint == '\r') ||
2766*7c568831SAndroid Build Coastguard Worker 		   (codepoint == '\t') || (codepoint == ' '));
2767*7c568831SAndroid Build Coastguard Worker 	    break;
2768*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTINITNAME:
2769*7c568831SAndroid Build Coastguard Worker 	    neg = !neg;
2770*7c568831SAndroid Build Coastguard Worker             /* Falls through. */
2771*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_INITNAME:
2772*7c568831SAndroid Build Coastguard Worker 	    ret = (IS_LETTER(codepoint) ||
2773*7c568831SAndroid Build Coastguard Worker 		   (codepoint == '_') || (codepoint == ':'));
2774*7c568831SAndroid Build Coastguard Worker 	    break;
2775*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTNAMECHAR:
2776*7c568831SAndroid Build Coastguard Worker 	    neg = !neg;
2777*7c568831SAndroid Build Coastguard Worker             /* Falls through. */
2778*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NAMECHAR:
2779*7c568831SAndroid Build Coastguard Worker 	    ret = (IS_LETTER(codepoint) || IS_DIGIT(codepoint) ||
2780*7c568831SAndroid Build Coastguard Worker 		   (codepoint == '.') || (codepoint == '-') ||
2781*7c568831SAndroid Build Coastguard Worker 		   (codepoint == '_') || (codepoint == ':') ||
2782*7c568831SAndroid Build Coastguard Worker 		   IS_COMBINING(codepoint) || IS_EXTENDER(codepoint));
2783*7c568831SAndroid Build Coastguard Worker 	    break;
2784*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTDECIMAL:
2785*7c568831SAndroid Build Coastguard Worker 	    neg = !neg;
2786*7c568831SAndroid Build Coastguard Worker             /* Falls through. */
2787*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_DECIMAL:
2788*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatNd(codepoint);
2789*7c568831SAndroid Build Coastguard Worker 	    break;
2790*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_REALCHAR:
2791*7c568831SAndroid Build Coastguard Worker 	    neg = !neg;
2792*7c568831SAndroid Build Coastguard Worker             /* Falls through. */
2793*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTREALCHAR:
2794*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatP(codepoint);
2795*7c568831SAndroid Build Coastguard Worker 	    if (ret == 0)
2796*7c568831SAndroid Build Coastguard Worker 		ret = xmlUCSIsCatZ(codepoint);
2797*7c568831SAndroid Build Coastguard Worker 	    if (ret == 0)
2798*7c568831SAndroid Build Coastguard Worker 		ret = xmlUCSIsCatC(codepoint);
2799*7c568831SAndroid Build Coastguard Worker 	    break;
2800*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER:
2801*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatL(codepoint);
2802*7c568831SAndroid Build Coastguard Worker 	    break;
2803*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_UPPERCASE:
2804*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatLu(codepoint);
2805*7c568831SAndroid Build Coastguard Worker 	    break;
2806*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_LOWERCASE:
2807*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatLl(codepoint);
2808*7c568831SAndroid Build Coastguard Worker 	    break;
2809*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_TITLECASE:
2810*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatLt(codepoint);
2811*7c568831SAndroid Build Coastguard Worker 	    break;
2812*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_MODIFIER:
2813*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatLm(codepoint);
2814*7c568831SAndroid Build Coastguard Worker 	    break;
2815*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_OTHERS:
2816*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatLo(codepoint);
2817*7c568831SAndroid Build Coastguard Worker 	    break;
2818*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK:
2819*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatM(codepoint);
2820*7c568831SAndroid Build Coastguard Worker 	    break;
2821*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_NONSPACING:
2822*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatMn(codepoint);
2823*7c568831SAndroid Build Coastguard Worker 	    break;
2824*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_SPACECOMBINING:
2825*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatMc(codepoint);
2826*7c568831SAndroid Build Coastguard Worker 	    break;
2827*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_ENCLOSING:
2828*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatMe(codepoint);
2829*7c568831SAndroid Build Coastguard Worker 	    break;
2830*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER:
2831*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatN(codepoint);
2832*7c568831SAndroid Build Coastguard Worker 	    break;
2833*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_DECIMAL:
2834*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatNd(codepoint);
2835*7c568831SAndroid Build Coastguard Worker 	    break;
2836*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_LETTER:
2837*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatNl(codepoint);
2838*7c568831SAndroid Build Coastguard Worker 	    break;
2839*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_OTHERS:
2840*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatNo(codepoint);
2841*7c568831SAndroid Build Coastguard Worker 	    break;
2842*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT:
2843*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatP(codepoint);
2844*7c568831SAndroid Build Coastguard Worker 	    break;
2845*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_CONNECTOR:
2846*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatPc(codepoint);
2847*7c568831SAndroid Build Coastguard Worker 	    break;
2848*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_DASH:
2849*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatPd(codepoint);
2850*7c568831SAndroid Build Coastguard Worker 	    break;
2851*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_OPEN:
2852*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatPs(codepoint);
2853*7c568831SAndroid Build Coastguard Worker 	    break;
2854*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_CLOSE:
2855*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatPe(codepoint);
2856*7c568831SAndroid Build Coastguard Worker 	    break;
2857*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_INITQUOTE:
2858*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatPi(codepoint);
2859*7c568831SAndroid Build Coastguard Worker 	    break;
2860*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_FINQUOTE:
2861*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatPf(codepoint);
2862*7c568831SAndroid Build Coastguard Worker 	    break;
2863*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_OTHERS:
2864*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatPo(codepoint);
2865*7c568831SAndroid Build Coastguard Worker 	    break;
2866*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR:
2867*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatZ(codepoint);
2868*7c568831SAndroid Build Coastguard Worker 	    break;
2869*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_SPACE:
2870*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatZs(codepoint);
2871*7c568831SAndroid Build Coastguard Worker 	    break;
2872*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_LINE:
2873*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatZl(codepoint);
2874*7c568831SAndroid Build Coastguard Worker 	    break;
2875*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_PARA:
2876*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatZp(codepoint);
2877*7c568831SAndroid Build Coastguard Worker 	    break;
2878*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL:
2879*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatS(codepoint);
2880*7c568831SAndroid Build Coastguard Worker 	    break;
2881*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_MATH:
2882*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatSm(codepoint);
2883*7c568831SAndroid Build Coastguard Worker 	    break;
2884*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_CURRENCY:
2885*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatSc(codepoint);
2886*7c568831SAndroid Build Coastguard Worker 	    break;
2887*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_MODIFIER:
2888*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatSk(codepoint);
2889*7c568831SAndroid Build Coastguard Worker 	    break;
2890*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_OTHERS:
2891*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatSo(codepoint);
2892*7c568831SAndroid Build Coastguard Worker 	    break;
2893*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER:
2894*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatC(codepoint);
2895*7c568831SAndroid Build Coastguard Worker 	    break;
2896*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_CONTROL:
2897*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatCc(codepoint);
2898*7c568831SAndroid Build Coastguard Worker 	    break;
2899*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_FORMAT:
2900*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatCf(codepoint);
2901*7c568831SAndroid Build Coastguard Worker 	    break;
2902*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_PRIVATE:
2903*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsCatCo(codepoint);
2904*7c568831SAndroid Build Coastguard Worker 	    break;
2905*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_NA:
2906*7c568831SAndroid Build Coastguard Worker 	    /* ret = xmlUCSIsCatCn(codepoint); */
2907*7c568831SAndroid Build Coastguard Worker 	    /* Seems it doesn't exist anymore in recent Unicode releases */
2908*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
2909*7c568831SAndroid Build Coastguard Worker 	    break;
2910*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_BLOCK_NAME:
2911*7c568831SAndroid Build Coastguard Worker 	    ret = xmlUCSIsBlock(codepoint, (const char *) blockName);
2912*7c568831SAndroid Build Coastguard Worker 	    break;
2913*7c568831SAndroid Build Coastguard Worker     }
2914*7c568831SAndroid Build Coastguard Worker     if (neg)
2915*7c568831SAndroid Build Coastguard Worker 	return(!ret);
2916*7c568831SAndroid Build Coastguard Worker     return(ret);
2917*7c568831SAndroid Build Coastguard Worker }
2918*7c568831SAndroid Build Coastguard Worker 
2919*7c568831SAndroid Build Coastguard Worker static int
xmlRegCheckCharacter(xmlRegAtomPtr atom,int codepoint)2920*7c568831SAndroid Build Coastguard Worker xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint) {
2921*7c568831SAndroid Build Coastguard Worker     int i, ret = 0;
2922*7c568831SAndroid Build Coastguard Worker     xmlRegRangePtr range;
2923*7c568831SAndroid Build Coastguard Worker 
2924*7c568831SAndroid Build Coastguard Worker     if ((atom == NULL) || (!IS_CHAR(codepoint)))
2925*7c568831SAndroid Build Coastguard Worker 	return(-1);
2926*7c568831SAndroid Build Coastguard Worker 
2927*7c568831SAndroid Build Coastguard Worker     switch (atom->type) {
2928*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SUBREG:
2929*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_EPSILON:
2930*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2931*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_CHARVAL:
2932*7c568831SAndroid Build Coastguard Worker             return(codepoint == atom->codepoint);
2933*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_RANGES: {
2934*7c568831SAndroid Build Coastguard Worker 	    int accept = 0;
2935*7c568831SAndroid Build Coastguard Worker 
2936*7c568831SAndroid Build Coastguard Worker 	    for (i = 0;i < atom->nbRanges;i++) {
2937*7c568831SAndroid Build Coastguard Worker 		range = atom->ranges[i];
2938*7c568831SAndroid Build Coastguard Worker 		if (range->neg == 2) {
2939*7c568831SAndroid Build Coastguard Worker 		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
2940*7c568831SAndroid Build Coastguard Worker 						0, range->start, range->end,
2941*7c568831SAndroid Build Coastguard Worker 						range->blockName);
2942*7c568831SAndroid Build Coastguard Worker 		    if (ret != 0)
2943*7c568831SAndroid Build Coastguard Worker 			return(0); /* excluded char */
2944*7c568831SAndroid Build Coastguard Worker 		} else if (range->neg) {
2945*7c568831SAndroid Build Coastguard Worker 		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
2946*7c568831SAndroid Build Coastguard Worker 						0, range->start, range->end,
2947*7c568831SAndroid Build Coastguard Worker 						range->blockName);
2948*7c568831SAndroid Build Coastguard Worker 		    if (ret == 0)
2949*7c568831SAndroid Build Coastguard Worker 		        accept = 1;
2950*7c568831SAndroid Build Coastguard Worker 		    else
2951*7c568831SAndroid Build Coastguard Worker 		        return(0);
2952*7c568831SAndroid Build Coastguard Worker 		} else {
2953*7c568831SAndroid Build Coastguard Worker 		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
2954*7c568831SAndroid Build Coastguard Worker 						0, range->start, range->end,
2955*7c568831SAndroid Build Coastguard Worker 						range->blockName);
2956*7c568831SAndroid Build Coastguard Worker 		    if (ret != 0)
2957*7c568831SAndroid Build Coastguard Worker 			accept = 1; /* might still be excluded */
2958*7c568831SAndroid Build Coastguard Worker 		}
2959*7c568831SAndroid Build Coastguard Worker 	    }
2960*7c568831SAndroid Build Coastguard Worker 	    return(accept);
2961*7c568831SAndroid Build Coastguard Worker 	}
2962*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_STRING:
2963*7c568831SAndroid Build Coastguard Worker 	    return(-1);
2964*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_ANYCHAR:
2965*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_ANYSPACE:
2966*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTSPACE:
2967*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_INITNAME:
2968*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTINITNAME:
2969*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NAMECHAR:
2970*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTNAMECHAR:
2971*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_DECIMAL:
2972*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTDECIMAL:
2973*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_REALCHAR:
2974*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NOTREALCHAR:
2975*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER:
2976*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_UPPERCASE:
2977*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_LOWERCASE:
2978*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_TITLECASE:
2979*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_MODIFIER:
2980*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_LETTER_OTHERS:
2981*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK:
2982*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_NONSPACING:
2983*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_SPACECOMBINING:
2984*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_MARK_ENCLOSING:
2985*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER:
2986*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_DECIMAL:
2987*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_LETTER:
2988*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_NUMBER_OTHERS:
2989*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT:
2990*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_CONNECTOR:
2991*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_DASH:
2992*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_OPEN:
2993*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_CLOSE:
2994*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_INITQUOTE:
2995*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_FINQUOTE:
2996*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_PUNCT_OTHERS:
2997*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR:
2998*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_SPACE:
2999*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_LINE:
3000*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SEPAR_PARA:
3001*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL:
3002*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_MATH:
3003*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_CURRENCY:
3004*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_MODIFIER:
3005*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_SYMBOL_OTHERS:
3006*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER:
3007*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_CONTROL:
3008*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_FORMAT:
3009*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_PRIVATE:
3010*7c568831SAndroid Build Coastguard Worker         case XML_REGEXP_OTHER_NA:
3011*7c568831SAndroid Build Coastguard Worker 	case XML_REGEXP_BLOCK_NAME:
3012*7c568831SAndroid Build Coastguard Worker 	    ret = xmlRegCheckCharacterRange(atom->type, codepoint, 0, 0, 0,
3013*7c568831SAndroid Build Coastguard Worker 		                            (const xmlChar *)atom->valuep);
3014*7c568831SAndroid Build Coastguard Worker 	    if (atom->neg)
3015*7c568831SAndroid Build Coastguard Worker 		ret = !ret;
3016*7c568831SAndroid Build Coastguard Worker 	    break;
3017*7c568831SAndroid Build Coastguard Worker     }
3018*7c568831SAndroid Build Coastguard Worker     return(ret);
3019*7c568831SAndroid Build Coastguard Worker }
3020*7c568831SAndroid Build Coastguard Worker 
3021*7c568831SAndroid Build Coastguard Worker /************************************************************************
3022*7c568831SAndroid Build Coastguard Worker  *									*
3023*7c568831SAndroid Build Coastguard Worker  *	Saving and restoring state of an execution context		*
3024*7c568831SAndroid Build Coastguard Worker  *									*
3025*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
3026*7c568831SAndroid Build Coastguard Worker 
3027*7c568831SAndroid Build Coastguard Worker static void
xmlFARegExecSave(xmlRegExecCtxtPtr exec)3028*7c568831SAndroid Build Coastguard Worker xmlFARegExecSave(xmlRegExecCtxtPtr exec) {
3029*7c568831SAndroid Build Coastguard Worker #ifdef MAX_PUSH
3030*7c568831SAndroid Build Coastguard Worker     if (exec->nbPush > MAX_PUSH) {
3031*7c568831SAndroid Build Coastguard Worker         exec->status = XML_REGEXP_INTERNAL_LIMIT;
3032*7c568831SAndroid Build Coastguard Worker         return;
3033*7c568831SAndroid Build Coastguard Worker     }
3034*7c568831SAndroid Build Coastguard Worker     exec->nbPush++;
3035*7c568831SAndroid Build Coastguard Worker #endif
3036*7c568831SAndroid Build Coastguard Worker 
3037*7c568831SAndroid Build Coastguard Worker     if (exec->maxRollbacks == 0) {
3038*7c568831SAndroid Build Coastguard Worker 	exec->maxRollbacks = 4;
3039*7c568831SAndroid Build Coastguard Worker 	exec->rollbacks = (xmlRegExecRollback *) xmlMalloc(exec->maxRollbacks *
3040*7c568831SAndroid Build Coastguard Worker 		                             sizeof(xmlRegExecRollback));
3041*7c568831SAndroid Build Coastguard Worker 	if (exec->rollbacks == NULL) {
3042*7c568831SAndroid Build Coastguard Worker 	    exec->maxRollbacks = 0;
3043*7c568831SAndroid Build Coastguard Worker             exec->status = XML_REGEXP_OUT_OF_MEMORY;
3044*7c568831SAndroid Build Coastguard Worker 	    return;
3045*7c568831SAndroid Build Coastguard Worker 	}
3046*7c568831SAndroid Build Coastguard Worker 	memset(exec->rollbacks, 0,
3047*7c568831SAndroid Build Coastguard Worker 	       exec->maxRollbacks * sizeof(xmlRegExecRollback));
3048*7c568831SAndroid Build Coastguard Worker     } else if (exec->nbRollbacks >= exec->maxRollbacks) {
3049*7c568831SAndroid Build Coastguard Worker 	xmlRegExecRollback *tmp;
3050*7c568831SAndroid Build Coastguard Worker 	int len = exec->maxRollbacks;
3051*7c568831SAndroid Build Coastguard Worker 
3052*7c568831SAndroid Build Coastguard Worker 	exec->maxRollbacks *= 2;
3053*7c568831SAndroid Build Coastguard Worker 	tmp = (xmlRegExecRollback *) xmlRealloc(exec->rollbacks,
3054*7c568831SAndroid Build Coastguard Worker 			exec->maxRollbacks * sizeof(xmlRegExecRollback));
3055*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
3056*7c568831SAndroid Build Coastguard Worker 	    exec->maxRollbacks /= 2;
3057*7c568831SAndroid Build Coastguard Worker             exec->status = XML_REGEXP_OUT_OF_MEMORY;
3058*7c568831SAndroid Build Coastguard Worker 	    return;
3059*7c568831SAndroid Build Coastguard Worker 	}
3060*7c568831SAndroid Build Coastguard Worker 	exec->rollbacks = tmp;
3061*7c568831SAndroid Build Coastguard Worker 	tmp = &exec->rollbacks[len];
3062*7c568831SAndroid Build Coastguard Worker 	memset(tmp, 0, (exec->maxRollbacks - len) * sizeof(xmlRegExecRollback));
3063*7c568831SAndroid Build Coastguard Worker     }
3064*7c568831SAndroid Build Coastguard Worker     exec->rollbacks[exec->nbRollbacks].state = exec->state;
3065*7c568831SAndroid Build Coastguard Worker     exec->rollbacks[exec->nbRollbacks].index = exec->index;
3066*7c568831SAndroid Build Coastguard Worker     exec->rollbacks[exec->nbRollbacks].nextbranch = exec->transno + 1;
3067*7c568831SAndroid Build Coastguard Worker     if (exec->comp->nbCounters > 0) {
3068*7c568831SAndroid Build Coastguard Worker 	if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
3069*7c568831SAndroid Build Coastguard Worker 	    exec->rollbacks[exec->nbRollbacks].counts = (int *)
3070*7c568831SAndroid Build Coastguard Worker 		xmlMalloc(exec->comp->nbCounters * sizeof(int));
3071*7c568831SAndroid Build Coastguard Worker 	    if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
3072*7c568831SAndroid Build Coastguard Worker 		exec->status = XML_REGEXP_OUT_OF_MEMORY;
3073*7c568831SAndroid Build Coastguard Worker 		return;
3074*7c568831SAndroid Build Coastguard Worker 	    }
3075*7c568831SAndroid Build Coastguard Worker 	}
3076*7c568831SAndroid Build Coastguard Worker 	memcpy(exec->rollbacks[exec->nbRollbacks].counts, exec->counts,
3077*7c568831SAndroid Build Coastguard Worker 	       exec->comp->nbCounters * sizeof(int));
3078*7c568831SAndroid Build Coastguard Worker     }
3079*7c568831SAndroid Build Coastguard Worker     exec->nbRollbacks++;
3080*7c568831SAndroid Build Coastguard Worker }
3081*7c568831SAndroid Build Coastguard Worker 
3082*7c568831SAndroid Build Coastguard Worker static void
xmlFARegExecRollBack(xmlRegExecCtxtPtr exec)3083*7c568831SAndroid Build Coastguard Worker xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) {
3084*7c568831SAndroid Build Coastguard Worker     if (exec->status != XML_REGEXP_OK)
3085*7c568831SAndroid Build Coastguard Worker         return;
3086*7c568831SAndroid Build Coastguard Worker     if (exec->nbRollbacks <= 0) {
3087*7c568831SAndroid Build Coastguard Worker 	exec->status = XML_REGEXP_NOT_FOUND;
3088*7c568831SAndroid Build Coastguard Worker 	return;
3089*7c568831SAndroid Build Coastguard Worker     }
3090*7c568831SAndroid Build Coastguard Worker     exec->nbRollbacks--;
3091*7c568831SAndroid Build Coastguard Worker     exec->state = exec->rollbacks[exec->nbRollbacks].state;
3092*7c568831SAndroid Build Coastguard Worker     exec->index = exec->rollbacks[exec->nbRollbacks].index;
3093*7c568831SAndroid Build Coastguard Worker     exec->transno = exec->rollbacks[exec->nbRollbacks].nextbranch;
3094*7c568831SAndroid Build Coastguard Worker     if (exec->comp->nbCounters > 0) {
3095*7c568831SAndroid Build Coastguard Worker 	if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
3096*7c568831SAndroid Build Coastguard Worker 	    exec->status = XML_REGEXP_INTERNAL_ERROR;
3097*7c568831SAndroid Build Coastguard Worker 	    return;
3098*7c568831SAndroid Build Coastguard Worker 	}
3099*7c568831SAndroid Build Coastguard Worker 	if (exec->counts) {
3100*7c568831SAndroid Build Coastguard Worker 	    memcpy(exec->counts, exec->rollbacks[exec->nbRollbacks].counts,
3101*7c568831SAndroid Build Coastguard Worker 	       exec->comp->nbCounters * sizeof(int));
3102*7c568831SAndroid Build Coastguard Worker 	}
3103*7c568831SAndroid Build Coastguard Worker     }
3104*7c568831SAndroid Build Coastguard Worker }
3105*7c568831SAndroid Build Coastguard Worker 
3106*7c568831SAndroid Build Coastguard Worker /************************************************************************
3107*7c568831SAndroid Build Coastguard Worker  *									*
3108*7c568831SAndroid Build Coastguard Worker  *	Verifier, running an input against a compiled regexp		*
3109*7c568831SAndroid Build Coastguard Worker  *									*
3110*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
3111*7c568831SAndroid Build Coastguard Worker 
3112*7c568831SAndroid Build Coastguard Worker static int
xmlFARegExec(xmlRegexpPtr comp,const xmlChar * content)3113*7c568831SAndroid Build Coastguard Worker xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
3114*7c568831SAndroid Build Coastguard Worker     xmlRegExecCtxt execval;
3115*7c568831SAndroid Build Coastguard Worker     xmlRegExecCtxtPtr exec = &execval;
3116*7c568831SAndroid Build Coastguard Worker     int ret, codepoint = 0, len, deter;
3117*7c568831SAndroid Build Coastguard Worker 
3118*7c568831SAndroid Build Coastguard Worker     exec->inputString = content;
3119*7c568831SAndroid Build Coastguard Worker     exec->index = 0;
3120*7c568831SAndroid Build Coastguard Worker     exec->nbPush = 0;
3121*7c568831SAndroid Build Coastguard Worker     exec->determinist = 1;
3122*7c568831SAndroid Build Coastguard Worker     exec->maxRollbacks = 0;
3123*7c568831SAndroid Build Coastguard Worker     exec->nbRollbacks = 0;
3124*7c568831SAndroid Build Coastguard Worker     exec->rollbacks = NULL;
3125*7c568831SAndroid Build Coastguard Worker     exec->status = XML_REGEXP_OK;
3126*7c568831SAndroid Build Coastguard Worker     exec->comp = comp;
3127*7c568831SAndroid Build Coastguard Worker     exec->state = comp->states[0];
3128*7c568831SAndroid Build Coastguard Worker     exec->transno = 0;
3129*7c568831SAndroid Build Coastguard Worker     exec->transcount = 0;
3130*7c568831SAndroid Build Coastguard Worker     exec->inputStack = NULL;
3131*7c568831SAndroid Build Coastguard Worker     exec->inputStackMax = 0;
3132*7c568831SAndroid Build Coastguard Worker     if (comp->nbCounters > 0) {
3133*7c568831SAndroid Build Coastguard Worker 	exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int));
3134*7c568831SAndroid Build Coastguard Worker 	if (exec->counts == NULL) {
3135*7c568831SAndroid Build Coastguard Worker 	    return(XML_REGEXP_OUT_OF_MEMORY);
3136*7c568831SAndroid Build Coastguard Worker 	}
3137*7c568831SAndroid Build Coastguard Worker         memset(exec->counts, 0, comp->nbCounters * sizeof(int));
3138*7c568831SAndroid Build Coastguard Worker     } else
3139*7c568831SAndroid Build Coastguard Worker 	exec->counts = NULL;
3140*7c568831SAndroid Build Coastguard Worker     while ((exec->status == XML_REGEXP_OK) && (exec->state != NULL) &&
3141*7c568831SAndroid Build Coastguard Worker 	   ((exec->inputString[exec->index] != 0) ||
3142*7c568831SAndroid Build Coastguard Worker 	    ((exec->state != NULL) &&
3143*7c568831SAndroid Build Coastguard Worker 	     (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
3144*7c568831SAndroid Build Coastguard Worker 	xmlRegTransPtr trans;
3145*7c568831SAndroid Build Coastguard Worker 	xmlRegAtomPtr atom;
3146*7c568831SAndroid Build Coastguard Worker 
3147*7c568831SAndroid Build Coastguard Worker 	/*
3148*7c568831SAndroid Build Coastguard Worker 	 * If end of input on non-terminal state, rollback, however we may
3149*7c568831SAndroid Build Coastguard Worker 	 * still have epsilon like transition for counted transitions
3150*7c568831SAndroid Build Coastguard Worker 	 * on counters, in that case don't break too early.  Additionally,
3151*7c568831SAndroid Build Coastguard Worker 	 * if we are working on a range like "AB{0,2}", where B is not present,
3152*7c568831SAndroid Build Coastguard Worker 	 * we don't want to break.
3153*7c568831SAndroid Build Coastguard Worker 	 */
3154*7c568831SAndroid Build Coastguard Worker 	len = 1;
3155*7c568831SAndroid Build Coastguard Worker 	if ((exec->inputString[exec->index] == 0) && (exec->counts == NULL)) {
3156*7c568831SAndroid Build Coastguard Worker 	    /*
3157*7c568831SAndroid Build Coastguard Worker 	     * if there is a transition, we must check if
3158*7c568831SAndroid Build Coastguard Worker 	     *  atom allows minOccurs of 0
3159*7c568831SAndroid Build Coastguard Worker 	     */
3160*7c568831SAndroid Build Coastguard Worker 	    if (exec->transno < exec->state->nbTrans) {
3161*7c568831SAndroid Build Coastguard Worker 	        trans = &exec->state->trans[exec->transno];
3162*7c568831SAndroid Build Coastguard Worker 		if (trans->to >=0) {
3163*7c568831SAndroid Build Coastguard Worker 		    atom = trans->atom;
3164*7c568831SAndroid Build Coastguard Worker 		    if (!((atom->min == 0) && (atom->max > 0)))
3165*7c568831SAndroid Build Coastguard Worker 		        goto rollback;
3166*7c568831SAndroid Build Coastguard Worker 		}
3167*7c568831SAndroid Build Coastguard Worker 	    } else
3168*7c568831SAndroid Build Coastguard Worker 	        goto rollback;
3169*7c568831SAndroid Build Coastguard Worker 	}
3170*7c568831SAndroid Build Coastguard Worker 
3171*7c568831SAndroid Build Coastguard Worker 	exec->transcount = 0;
3172*7c568831SAndroid Build Coastguard Worker 	for (;exec->transno < exec->state->nbTrans;exec->transno++) {
3173*7c568831SAndroid Build Coastguard Worker 	    trans = &exec->state->trans[exec->transno];
3174*7c568831SAndroid Build Coastguard Worker 	    if (trans->to < 0)
3175*7c568831SAndroid Build Coastguard Worker 		continue;
3176*7c568831SAndroid Build Coastguard Worker 	    atom = trans->atom;
3177*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
3178*7c568831SAndroid Build Coastguard Worker 	    deter = 1;
3179*7c568831SAndroid Build Coastguard Worker 	    if (trans->count >= 0) {
3180*7c568831SAndroid Build Coastguard Worker 		int count;
3181*7c568831SAndroid Build Coastguard Worker 		xmlRegCounterPtr counter;
3182*7c568831SAndroid Build Coastguard Worker 
3183*7c568831SAndroid Build Coastguard Worker 		if (exec->counts == NULL) {
3184*7c568831SAndroid Build Coastguard Worker 		    exec->status = XML_REGEXP_INTERNAL_ERROR;
3185*7c568831SAndroid Build Coastguard Worker 		    goto error;
3186*7c568831SAndroid Build Coastguard Worker 		}
3187*7c568831SAndroid Build Coastguard Worker 		/*
3188*7c568831SAndroid Build Coastguard Worker 		 * A counted transition.
3189*7c568831SAndroid Build Coastguard Worker 		 */
3190*7c568831SAndroid Build Coastguard Worker 
3191*7c568831SAndroid Build Coastguard Worker 		count = exec->counts[trans->count];
3192*7c568831SAndroid Build Coastguard Worker 		counter = &exec->comp->counters[trans->count];
3193*7c568831SAndroid Build Coastguard Worker 		ret = ((count >= counter->min) && (count <= counter->max));
3194*7c568831SAndroid Build Coastguard Worker 		if ((ret) && (counter->min != counter->max))
3195*7c568831SAndroid Build Coastguard Worker 		    deter = 0;
3196*7c568831SAndroid Build Coastguard Worker 	    } else if (atom == NULL) {
3197*7c568831SAndroid Build Coastguard Worker 		exec->status = XML_REGEXP_INTERNAL_ERROR;
3198*7c568831SAndroid Build Coastguard Worker 		break;
3199*7c568831SAndroid Build Coastguard Worker 	    } else if (exec->inputString[exec->index] != 0) {
3200*7c568831SAndroid Build Coastguard Worker                 len = 4;
3201*7c568831SAndroid Build Coastguard Worker                 codepoint = xmlGetUTF8Char(&exec->inputString[exec->index],
3202*7c568831SAndroid Build Coastguard Worker                                            &len);
3203*7c568831SAndroid Build Coastguard Worker                 if (codepoint < 0) {
3204*7c568831SAndroid Build Coastguard Worker                     exec->status = XML_REGEXP_INVALID_UTF8;
3205*7c568831SAndroid Build Coastguard Worker                     goto error;
3206*7c568831SAndroid Build Coastguard Worker                 }
3207*7c568831SAndroid Build Coastguard Worker 		ret = xmlRegCheckCharacter(atom, codepoint);
3208*7c568831SAndroid Build Coastguard Worker 		if ((ret == 1) && (atom->min >= 0) && (atom->max > 0)) {
3209*7c568831SAndroid Build Coastguard Worker 		    xmlRegStatePtr to = comp->states[trans->to];
3210*7c568831SAndroid Build Coastguard Worker 
3211*7c568831SAndroid Build Coastguard Worker 		    /*
3212*7c568831SAndroid Build Coastguard Worker 		     * this is a multiple input sequence
3213*7c568831SAndroid Build Coastguard Worker 		     * If there is a counter associated increment it now.
3214*7c568831SAndroid Build Coastguard Worker 		     * do not increment if the counter is already over the
3215*7c568831SAndroid Build Coastguard Worker 		     * maximum limit in which case get to next transition
3216*7c568831SAndroid Build Coastguard Worker 		     */
3217*7c568831SAndroid Build Coastguard Worker 		    if (trans->counter >= 0) {
3218*7c568831SAndroid Build Coastguard Worker 			xmlRegCounterPtr counter;
3219*7c568831SAndroid Build Coastguard Worker 
3220*7c568831SAndroid Build Coastguard Worker 			if ((exec->counts == NULL) ||
3221*7c568831SAndroid Build Coastguard Worker 			    (exec->comp == NULL) ||
3222*7c568831SAndroid Build Coastguard Worker 			    (exec->comp->counters == NULL)) {
3223*7c568831SAndroid Build Coastguard Worker 			    exec->status = XML_REGEXP_INTERNAL_ERROR;
3224*7c568831SAndroid Build Coastguard Worker 			    goto error;
3225*7c568831SAndroid Build Coastguard Worker 			}
3226*7c568831SAndroid Build Coastguard Worker 			counter = &exec->comp->counters[trans->counter];
3227*7c568831SAndroid Build Coastguard Worker 			if (exec->counts[trans->counter] >= counter->max)
3228*7c568831SAndroid Build Coastguard Worker 			    continue; /* for loop on transitions */
3229*7c568831SAndroid Build Coastguard Worker                     }
3230*7c568831SAndroid Build Coastguard Worker                     /* Save before incrementing */
3231*7c568831SAndroid Build Coastguard Worker 		    if (exec->state->nbTrans > exec->transno + 1) {
3232*7c568831SAndroid Build Coastguard Worker 			xmlFARegExecSave(exec);
3233*7c568831SAndroid Build Coastguard Worker                         if (exec->status != XML_REGEXP_OK)
3234*7c568831SAndroid Build Coastguard Worker                             goto error;
3235*7c568831SAndroid Build Coastguard Worker 		    }
3236*7c568831SAndroid Build Coastguard Worker 		    if (trans->counter >= 0) {
3237*7c568831SAndroid Build Coastguard Worker 			exec->counts[trans->counter]++;
3238*7c568831SAndroid Build Coastguard Worker 		    }
3239*7c568831SAndroid Build Coastguard Worker 		    exec->transcount = 1;
3240*7c568831SAndroid Build Coastguard Worker 		    do {
3241*7c568831SAndroid Build Coastguard Worker 			/*
3242*7c568831SAndroid Build Coastguard Worker 			 * Try to progress as much as possible on the input
3243*7c568831SAndroid Build Coastguard Worker 			 */
3244*7c568831SAndroid Build Coastguard Worker 			if (exec->transcount == atom->max) {
3245*7c568831SAndroid Build Coastguard Worker 			    break;
3246*7c568831SAndroid Build Coastguard Worker 			}
3247*7c568831SAndroid Build Coastguard Worker 			exec->index += len;
3248*7c568831SAndroid Build Coastguard Worker 			/*
3249*7c568831SAndroid Build Coastguard Worker 			 * End of input: stop here
3250*7c568831SAndroid Build Coastguard Worker 			 */
3251*7c568831SAndroid Build Coastguard Worker 			if (exec->inputString[exec->index] == 0) {
3252*7c568831SAndroid Build Coastguard Worker 			    exec->index -= len;
3253*7c568831SAndroid Build Coastguard Worker 			    break;
3254*7c568831SAndroid Build Coastguard Worker 			}
3255*7c568831SAndroid Build Coastguard Worker 			if (exec->transcount >= atom->min) {
3256*7c568831SAndroid Build Coastguard Worker 			    int transno = exec->transno;
3257*7c568831SAndroid Build Coastguard Worker 			    xmlRegStatePtr state = exec->state;
3258*7c568831SAndroid Build Coastguard Worker 
3259*7c568831SAndroid Build Coastguard Worker 			    /*
3260*7c568831SAndroid Build Coastguard Worker 			     * The transition is acceptable save it
3261*7c568831SAndroid Build Coastguard Worker 			     */
3262*7c568831SAndroid Build Coastguard Worker 			    exec->transno = -1; /* trick */
3263*7c568831SAndroid Build Coastguard Worker 			    exec->state = to;
3264*7c568831SAndroid Build Coastguard Worker 			    xmlFARegExecSave(exec);
3265*7c568831SAndroid Build Coastguard Worker                             if (exec->status != XML_REGEXP_OK)
3266*7c568831SAndroid Build Coastguard Worker                                 goto error;
3267*7c568831SAndroid Build Coastguard Worker 			    exec->transno = transno;
3268*7c568831SAndroid Build Coastguard Worker 			    exec->state = state;
3269*7c568831SAndroid Build Coastguard Worker 			}
3270*7c568831SAndroid Build Coastguard Worker                         len = 4;
3271*7c568831SAndroid Build Coastguard Worker                         codepoint = xmlGetUTF8Char(
3272*7c568831SAndroid Build Coastguard Worker                                 &exec->inputString[exec->index], &len);
3273*7c568831SAndroid Build Coastguard Worker                         if (codepoint < 0) {
3274*7c568831SAndroid Build Coastguard Worker                             exec->status = XML_REGEXP_INVALID_UTF8;
3275*7c568831SAndroid Build Coastguard Worker                             goto error;
3276*7c568831SAndroid Build Coastguard Worker                         }
3277*7c568831SAndroid Build Coastguard Worker 			ret = xmlRegCheckCharacter(atom, codepoint);
3278*7c568831SAndroid Build Coastguard Worker 			exec->transcount++;
3279*7c568831SAndroid Build Coastguard Worker 		    } while (ret == 1);
3280*7c568831SAndroid Build Coastguard Worker 		    if (exec->transcount < atom->min)
3281*7c568831SAndroid Build Coastguard Worker 			ret = 0;
3282*7c568831SAndroid Build Coastguard Worker 
3283*7c568831SAndroid Build Coastguard Worker 		    /*
3284*7c568831SAndroid Build Coastguard Worker 		     * If the last check failed but one transition was found
3285*7c568831SAndroid Build Coastguard Worker 		     * possible, rollback
3286*7c568831SAndroid Build Coastguard Worker 		     */
3287*7c568831SAndroid Build Coastguard Worker 		    if (ret < 0)
3288*7c568831SAndroid Build Coastguard Worker 			ret = 0;
3289*7c568831SAndroid Build Coastguard Worker 		    if (ret == 0) {
3290*7c568831SAndroid Build Coastguard Worker 			goto rollback;
3291*7c568831SAndroid Build Coastguard Worker 		    }
3292*7c568831SAndroid Build Coastguard Worker 		    if (trans->counter >= 0) {
3293*7c568831SAndroid Build Coastguard Worker 			if (exec->counts == NULL) {
3294*7c568831SAndroid Build Coastguard Worker 			    exec->status = XML_REGEXP_INTERNAL_ERROR;
3295*7c568831SAndroid Build Coastguard Worker 			    goto error;
3296*7c568831SAndroid Build Coastguard Worker 			}
3297*7c568831SAndroid Build Coastguard Worker 			exec->counts[trans->counter]--;
3298*7c568831SAndroid Build Coastguard Worker 		    }
3299*7c568831SAndroid Build Coastguard Worker 		} else if ((ret == 0) && (atom->min == 0) && (atom->max > 0)) {
3300*7c568831SAndroid Build Coastguard Worker 		    /*
3301*7c568831SAndroid Build Coastguard Worker 		     * we don't match on the codepoint, but minOccurs of 0
3302*7c568831SAndroid Build Coastguard Worker 		     * says that's ok.  Setting len to 0 inhibits stepping
3303*7c568831SAndroid Build Coastguard Worker 		     * over the codepoint.
3304*7c568831SAndroid Build Coastguard Worker 		     */
3305*7c568831SAndroid Build Coastguard Worker 		    exec->transcount = 1;
3306*7c568831SAndroid Build Coastguard Worker 		    len = 0;
3307*7c568831SAndroid Build Coastguard Worker 		    ret = 1;
3308*7c568831SAndroid Build Coastguard Worker 		}
3309*7c568831SAndroid Build Coastguard Worker 	    } else if ((atom->min == 0) && (atom->max > 0)) {
3310*7c568831SAndroid Build Coastguard Worker 	        /* another spot to match when minOccurs is 0 */
3311*7c568831SAndroid Build Coastguard Worker 		exec->transcount = 1;
3312*7c568831SAndroid Build Coastguard Worker 		len = 0;
3313*7c568831SAndroid Build Coastguard Worker 		ret = 1;
3314*7c568831SAndroid Build Coastguard Worker 	    }
3315*7c568831SAndroid Build Coastguard Worker 	    if (ret == 1) {
3316*7c568831SAndroid Build Coastguard Worker 		if ((trans->nd == 1) ||
3317*7c568831SAndroid Build Coastguard Worker 		    ((trans->count >= 0) && (deter == 0) &&
3318*7c568831SAndroid Build Coastguard Worker 		     (exec->state->nbTrans > exec->transno + 1))) {
3319*7c568831SAndroid Build Coastguard Worker 		    xmlFARegExecSave(exec);
3320*7c568831SAndroid Build Coastguard Worker                     if (exec->status != XML_REGEXP_OK)
3321*7c568831SAndroid Build Coastguard Worker                         goto error;
3322*7c568831SAndroid Build Coastguard Worker 		}
3323*7c568831SAndroid Build Coastguard Worker 		if (trans->counter >= 0) {
3324*7c568831SAndroid Build Coastguard Worker 		    xmlRegCounterPtr counter;
3325*7c568831SAndroid Build Coastguard Worker 
3326*7c568831SAndroid Build Coastguard Worker                     /* make sure we don't go over the counter maximum value */
3327*7c568831SAndroid Build Coastguard Worker 		    if ((exec->counts == NULL) ||
3328*7c568831SAndroid Build Coastguard Worker 			(exec->comp == NULL) ||
3329*7c568831SAndroid Build Coastguard Worker 			(exec->comp->counters == NULL)) {
3330*7c568831SAndroid Build Coastguard Worker 			exec->status = XML_REGEXP_INTERNAL_ERROR;
3331*7c568831SAndroid Build Coastguard Worker 			goto error;
3332*7c568831SAndroid Build Coastguard Worker 		    }
3333*7c568831SAndroid Build Coastguard Worker 		    counter = &exec->comp->counters[trans->counter];
3334*7c568831SAndroid Build Coastguard Worker 		    if (exec->counts[trans->counter] >= counter->max)
3335*7c568831SAndroid Build Coastguard Worker 			continue; /* for loop on transitions */
3336*7c568831SAndroid Build Coastguard Worker 		    exec->counts[trans->counter]++;
3337*7c568831SAndroid Build Coastguard Worker 		}
3338*7c568831SAndroid Build Coastguard Worker 		if ((trans->count >= 0) &&
3339*7c568831SAndroid Build Coastguard Worker 		    (trans->count < REGEXP_ALL_COUNTER)) {
3340*7c568831SAndroid Build Coastguard Worker 		    if (exec->counts == NULL) {
3341*7c568831SAndroid Build Coastguard Worker 		        exec->status = XML_REGEXP_INTERNAL_ERROR;
3342*7c568831SAndroid Build Coastguard Worker 			goto error;
3343*7c568831SAndroid Build Coastguard Worker 		    }
3344*7c568831SAndroid Build Coastguard Worker 		    exec->counts[trans->count] = 0;
3345*7c568831SAndroid Build Coastguard Worker 		}
3346*7c568831SAndroid Build Coastguard Worker 		exec->state = comp->states[trans->to];
3347*7c568831SAndroid Build Coastguard Worker 		exec->transno = 0;
3348*7c568831SAndroid Build Coastguard Worker 		if (trans->atom != NULL) {
3349*7c568831SAndroid Build Coastguard Worker 		    exec->index += len;
3350*7c568831SAndroid Build Coastguard Worker 		}
3351*7c568831SAndroid Build Coastguard Worker 		goto progress;
3352*7c568831SAndroid Build Coastguard Worker 	    } else if (ret < 0) {
3353*7c568831SAndroid Build Coastguard Worker 		exec->status = XML_REGEXP_INTERNAL_ERROR;
3354*7c568831SAndroid Build Coastguard Worker 		break;
3355*7c568831SAndroid Build Coastguard Worker 	    }
3356*7c568831SAndroid Build Coastguard Worker 	}
3357*7c568831SAndroid Build Coastguard Worker 	if ((exec->transno != 0) || (exec->state->nbTrans == 0)) {
3358*7c568831SAndroid Build Coastguard Worker rollback:
3359*7c568831SAndroid Build Coastguard Worker 	    /*
3360*7c568831SAndroid Build Coastguard Worker 	     * Failed to find a way out
3361*7c568831SAndroid Build Coastguard Worker 	     */
3362*7c568831SAndroid Build Coastguard Worker 	    exec->determinist = 0;
3363*7c568831SAndroid Build Coastguard Worker 	    xmlFARegExecRollBack(exec);
3364*7c568831SAndroid Build Coastguard Worker 	}
3365*7c568831SAndroid Build Coastguard Worker progress:
3366*7c568831SAndroid Build Coastguard Worker 	continue;
3367*7c568831SAndroid Build Coastguard Worker     }
3368*7c568831SAndroid Build Coastguard Worker error:
3369*7c568831SAndroid Build Coastguard Worker     if (exec->rollbacks != NULL) {
3370*7c568831SAndroid Build Coastguard Worker 	if (exec->counts != NULL) {
3371*7c568831SAndroid Build Coastguard Worker 	    int i;
3372*7c568831SAndroid Build Coastguard Worker 
3373*7c568831SAndroid Build Coastguard Worker 	    for (i = 0;i < exec->maxRollbacks;i++)
3374*7c568831SAndroid Build Coastguard Worker 		if (exec->rollbacks[i].counts != NULL)
3375*7c568831SAndroid Build Coastguard Worker 		    xmlFree(exec->rollbacks[i].counts);
3376*7c568831SAndroid Build Coastguard Worker 	}
3377*7c568831SAndroid Build Coastguard Worker 	xmlFree(exec->rollbacks);
3378*7c568831SAndroid Build Coastguard Worker     }
3379*7c568831SAndroid Build Coastguard Worker     if (exec->state == NULL)
3380*7c568831SAndroid Build Coastguard Worker         return(XML_REGEXP_INTERNAL_ERROR);
3381*7c568831SAndroid Build Coastguard Worker     if (exec->counts != NULL)
3382*7c568831SAndroid Build Coastguard Worker 	xmlFree(exec->counts);
3383*7c568831SAndroid Build Coastguard Worker     if (exec->status == XML_REGEXP_OK)
3384*7c568831SAndroid Build Coastguard Worker 	return(1);
3385*7c568831SAndroid Build Coastguard Worker     if (exec->status == XML_REGEXP_NOT_FOUND)
3386*7c568831SAndroid Build Coastguard Worker 	return(0);
3387*7c568831SAndroid Build Coastguard Worker     return(exec->status);
3388*7c568831SAndroid Build Coastguard Worker }
3389*7c568831SAndroid Build Coastguard Worker 
3390*7c568831SAndroid Build Coastguard Worker /************************************************************************
3391*7c568831SAndroid Build Coastguard Worker  *									*
3392*7c568831SAndroid Build Coastguard Worker  *	Progressive interface to the verifier one atom at a time	*
3393*7c568831SAndroid Build Coastguard Worker  *									*
3394*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
3395*7c568831SAndroid Build Coastguard Worker 
3396*7c568831SAndroid Build Coastguard Worker /**
3397*7c568831SAndroid Build Coastguard Worker  * xmlRegNewExecCtxt:
3398*7c568831SAndroid Build Coastguard Worker  * @comp: a precompiled regular expression
3399*7c568831SAndroid Build Coastguard Worker  * @callback: a callback function used for handling progresses in the
3400*7c568831SAndroid Build Coastguard Worker  *            automata matching phase
3401*7c568831SAndroid Build Coastguard Worker  * @data: the context data associated to the callback in this context
3402*7c568831SAndroid Build Coastguard Worker  *
3403*7c568831SAndroid Build Coastguard Worker  * Build a context used for progressive evaluation of a regexp.
3404*7c568831SAndroid Build Coastguard Worker  *
3405*7c568831SAndroid Build Coastguard Worker  * Returns the new context
3406*7c568831SAndroid Build Coastguard Worker  */
3407*7c568831SAndroid Build Coastguard Worker xmlRegExecCtxtPtr
xmlRegNewExecCtxt(xmlRegexpPtr comp,xmlRegExecCallbacks callback,void * data)3408*7c568831SAndroid Build Coastguard Worker xmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) {
3409*7c568831SAndroid Build Coastguard Worker     xmlRegExecCtxtPtr exec;
3410*7c568831SAndroid Build Coastguard Worker 
3411*7c568831SAndroid Build Coastguard Worker     if (comp == NULL)
3412*7c568831SAndroid Build Coastguard Worker 	return(NULL);
3413*7c568831SAndroid Build Coastguard Worker     if ((comp->compact == NULL) && (comp->states == NULL))
3414*7c568831SAndroid Build Coastguard Worker         return(NULL);
3415*7c568831SAndroid Build Coastguard Worker     exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt));
3416*7c568831SAndroid Build Coastguard Worker     if (exec == NULL)
3417*7c568831SAndroid Build Coastguard Worker 	return(NULL);
3418*7c568831SAndroid Build Coastguard Worker     memset(exec, 0, sizeof(xmlRegExecCtxt));
3419*7c568831SAndroid Build Coastguard Worker     exec->inputString = NULL;
3420*7c568831SAndroid Build Coastguard Worker     exec->index = 0;
3421*7c568831SAndroid Build Coastguard Worker     exec->determinist = 1;
3422*7c568831SAndroid Build Coastguard Worker     exec->maxRollbacks = 0;
3423*7c568831SAndroid Build Coastguard Worker     exec->nbRollbacks = 0;
3424*7c568831SAndroid Build Coastguard Worker     exec->rollbacks = NULL;
3425*7c568831SAndroid Build Coastguard Worker     exec->status = XML_REGEXP_OK;
3426*7c568831SAndroid Build Coastguard Worker     exec->comp = comp;
3427*7c568831SAndroid Build Coastguard Worker     if (comp->compact == NULL)
3428*7c568831SAndroid Build Coastguard Worker 	exec->state = comp->states[0];
3429*7c568831SAndroid Build Coastguard Worker     exec->transno = 0;
3430*7c568831SAndroid Build Coastguard Worker     exec->transcount = 0;
3431*7c568831SAndroid Build Coastguard Worker     exec->callback = callback;
3432*7c568831SAndroid Build Coastguard Worker     exec->data = data;
3433*7c568831SAndroid Build Coastguard Worker     if (comp->nbCounters > 0) {
3434*7c568831SAndroid Build Coastguard Worker         /*
3435*7c568831SAndroid Build Coastguard Worker 	 * For error handling, exec->counts is allocated twice the size
3436*7c568831SAndroid Build Coastguard Worker 	 * the second half is used to store the data in case of rollback
3437*7c568831SAndroid Build Coastguard Worker 	 */
3438*7c568831SAndroid Build Coastguard Worker 	exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)
3439*7c568831SAndroid Build Coastguard Worker 	                                 * 2);
3440*7c568831SAndroid Build Coastguard Worker 	if (exec->counts == NULL) {
3441*7c568831SAndroid Build Coastguard Worker 	    xmlFree(exec);
3442*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
3443*7c568831SAndroid Build Coastguard Worker 	}
3444*7c568831SAndroid Build Coastguard Worker         memset(exec->counts, 0, comp->nbCounters * sizeof(int) * 2);
3445*7c568831SAndroid Build Coastguard Worker 	exec->errCounts = &exec->counts[comp->nbCounters];
3446*7c568831SAndroid Build Coastguard Worker     } else {
3447*7c568831SAndroid Build Coastguard Worker 	exec->counts = NULL;
3448*7c568831SAndroid Build Coastguard Worker 	exec->errCounts = NULL;
3449*7c568831SAndroid Build Coastguard Worker     }
3450*7c568831SAndroid Build Coastguard Worker     exec->inputStackMax = 0;
3451*7c568831SAndroid Build Coastguard Worker     exec->inputStackNr = 0;
3452*7c568831SAndroid Build Coastguard Worker     exec->inputStack = NULL;
3453*7c568831SAndroid Build Coastguard Worker     exec->errStateNo = -1;
3454*7c568831SAndroid Build Coastguard Worker     exec->errString = NULL;
3455*7c568831SAndroid Build Coastguard Worker     exec->nbPush = 0;
3456*7c568831SAndroid Build Coastguard Worker     return(exec);
3457*7c568831SAndroid Build Coastguard Worker }
3458*7c568831SAndroid Build Coastguard Worker 
3459*7c568831SAndroid Build Coastguard Worker /**
3460*7c568831SAndroid Build Coastguard Worker  * xmlRegFreeExecCtxt:
3461*7c568831SAndroid Build Coastguard Worker  * @exec: a regular expression evaluation context
3462*7c568831SAndroid Build Coastguard Worker  *
3463*7c568831SAndroid Build Coastguard Worker  * Free the structures associated to a regular expression evaluation context.
3464*7c568831SAndroid Build Coastguard Worker  */
3465*7c568831SAndroid Build Coastguard Worker void
xmlRegFreeExecCtxt(xmlRegExecCtxtPtr exec)3466*7c568831SAndroid Build Coastguard Worker xmlRegFreeExecCtxt(xmlRegExecCtxtPtr exec) {
3467*7c568831SAndroid Build Coastguard Worker     if (exec == NULL)
3468*7c568831SAndroid Build Coastguard Worker 	return;
3469*7c568831SAndroid Build Coastguard Worker 
3470*7c568831SAndroid Build Coastguard Worker     if (exec->rollbacks != NULL) {
3471*7c568831SAndroid Build Coastguard Worker 	if (exec->counts != NULL) {
3472*7c568831SAndroid Build Coastguard Worker 	    int i;
3473*7c568831SAndroid Build Coastguard Worker 
3474*7c568831SAndroid Build Coastguard Worker 	    for (i = 0;i < exec->maxRollbacks;i++)
3475*7c568831SAndroid Build Coastguard Worker 		if (exec->rollbacks[i].counts != NULL)
3476*7c568831SAndroid Build Coastguard Worker 		    xmlFree(exec->rollbacks[i].counts);
3477*7c568831SAndroid Build Coastguard Worker 	}
3478*7c568831SAndroid Build Coastguard Worker 	xmlFree(exec->rollbacks);
3479*7c568831SAndroid Build Coastguard Worker     }
3480*7c568831SAndroid Build Coastguard Worker     if (exec->counts != NULL)
3481*7c568831SAndroid Build Coastguard Worker 	xmlFree(exec->counts);
3482*7c568831SAndroid Build Coastguard Worker     if (exec->inputStack != NULL) {
3483*7c568831SAndroid Build Coastguard Worker 	int i;
3484*7c568831SAndroid Build Coastguard Worker 
3485*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < exec->inputStackNr;i++) {
3486*7c568831SAndroid Build Coastguard Worker 	    if (exec->inputStack[i].value != NULL)
3487*7c568831SAndroid Build Coastguard Worker 		xmlFree(exec->inputStack[i].value);
3488*7c568831SAndroid Build Coastguard Worker 	}
3489*7c568831SAndroid Build Coastguard Worker 	xmlFree(exec->inputStack);
3490*7c568831SAndroid Build Coastguard Worker     }
3491*7c568831SAndroid Build Coastguard Worker     if (exec->errString != NULL)
3492*7c568831SAndroid Build Coastguard Worker         xmlFree(exec->errString);
3493*7c568831SAndroid Build Coastguard Worker     xmlFree(exec);
3494*7c568831SAndroid Build Coastguard Worker }
3495*7c568831SAndroid Build Coastguard Worker 
3496*7c568831SAndroid Build Coastguard Worker static int
xmlRegExecSetErrString(xmlRegExecCtxtPtr exec,const xmlChar * value)3497*7c568831SAndroid Build Coastguard Worker xmlRegExecSetErrString(xmlRegExecCtxtPtr exec, const xmlChar *value) {
3498*7c568831SAndroid Build Coastguard Worker     if (exec->errString != NULL)
3499*7c568831SAndroid Build Coastguard Worker         xmlFree(exec->errString);
3500*7c568831SAndroid Build Coastguard Worker     if (value == NULL) {
3501*7c568831SAndroid Build Coastguard Worker         exec->errString = NULL;
3502*7c568831SAndroid Build Coastguard Worker     } else {
3503*7c568831SAndroid Build Coastguard Worker         exec->errString = xmlStrdup(value);
3504*7c568831SAndroid Build Coastguard Worker         if (exec->errString == NULL) {
3505*7c568831SAndroid Build Coastguard Worker             exec->status = XML_REGEXP_OUT_OF_MEMORY;
3506*7c568831SAndroid Build Coastguard Worker             return(-1);
3507*7c568831SAndroid Build Coastguard Worker         }
3508*7c568831SAndroid Build Coastguard Worker     }
3509*7c568831SAndroid Build Coastguard Worker     return(0);
3510*7c568831SAndroid Build Coastguard Worker }
3511*7c568831SAndroid Build Coastguard Worker 
3512*7c568831SAndroid Build Coastguard Worker static void
xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec,const xmlChar * value,void * data)3513*7c568831SAndroid Build Coastguard Worker xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value,
3514*7c568831SAndroid Build Coastguard Worker 	                    void *data) {
3515*7c568831SAndroid Build Coastguard Worker     if (exec->inputStackMax == 0) {
3516*7c568831SAndroid Build Coastguard Worker 	exec->inputStackMax = 4;
3517*7c568831SAndroid Build Coastguard Worker 	exec->inputStack = (xmlRegInputTokenPtr)
3518*7c568831SAndroid Build Coastguard Worker 	    xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken));
3519*7c568831SAndroid Build Coastguard Worker 	if (exec->inputStack == NULL) {
3520*7c568831SAndroid Build Coastguard Worker 	    exec->inputStackMax = 0;
3521*7c568831SAndroid Build Coastguard Worker             exec->status = XML_REGEXP_OUT_OF_MEMORY;
3522*7c568831SAndroid Build Coastguard Worker 	    return;
3523*7c568831SAndroid Build Coastguard Worker 	}
3524*7c568831SAndroid Build Coastguard Worker     } else if (exec->inputStackNr + 1 >= exec->inputStackMax) {
3525*7c568831SAndroid Build Coastguard Worker 	xmlRegInputTokenPtr tmp;
3526*7c568831SAndroid Build Coastguard Worker 
3527*7c568831SAndroid Build Coastguard Worker 	exec->inputStackMax *= 2;
3528*7c568831SAndroid Build Coastguard Worker 	tmp = (xmlRegInputTokenPtr) xmlRealloc(exec->inputStack,
3529*7c568831SAndroid Build Coastguard Worker 			exec->inputStackMax * sizeof(xmlRegInputToken));
3530*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
3531*7c568831SAndroid Build Coastguard Worker 	    exec->inputStackMax /= 2;
3532*7c568831SAndroid Build Coastguard Worker             exec->status = XML_REGEXP_OUT_OF_MEMORY;
3533*7c568831SAndroid Build Coastguard Worker 	    return;
3534*7c568831SAndroid Build Coastguard Worker 	}
3535*7c568831SAndroid Build Coastguard Worker 	exec->inputStack = tmp;
3536*7c568831SAndroid Build Coastguard Worker     }
3537*7c568831SAndroid Build Coastguard Worker     if (value == NULL) {
3538*7c568831SAndroid Build Coastguard Worker         exec->inputStack[exec->inputStackNr].value = NULL;
3539*7c568831SAndroid Build Coastguard Worker     } else {
3540*7c568831SAndroid Build Coastguard Worker         exec->inputStack[exec->inputStackNr].value = xmlStrdup(value);
3541*7c568831SAndroid Build Coastguard Worker         if (exec->inputStack[exec->inputStackNr].value == NULL) {
3542*7c568831SAndroid Build Coastguard Worker             exec->status = XML_REGEXP_OUT_OF_MEMORY;
3543*7c568831SAndroid Build Coastguard Worker             return;
3544*7c568831SAndroid Build Coastguard Worker         }
3545*7c568831SAndroid Build Coastguard Worker     }
3546*7c568831SAndroid Build Coastguard Worker     exec->inputStack[exec->inputStackNr].data = data;
3547*7c568831SAndroid Build Coastguard Worker     exec->inputStackNr++;
3548*7c568831SAndroid Build Coastguard Worker     exec->inputStack[exec->inputStackNr].value = NULL;
3549*7c568831SAndroid Build Coastguard Worker     exec->inputStack[exec->inputStackNr].data = NULL;
3550*7c568831SAndroid Build Coastguard Worker }
3551*7c568831SAndroid Build Coastguard Worker 
3552*7c568831SAndroid Build Coastguard Worker /**
3553*7c568831SAndroid Build Coastguard Worker  * xmlRegStrEqualWildcard:
3554*7c568831SAndroid Build Coastguard Worker  * @expStr:  the string to be evaluated
3555*7c568831SAndroid Build Coastguard Worker  * @valStr:  the validation string
3556*7c568831SAndroid Build Coastguard Worker  *
3557*7c568831SAndroid Build Coastguard Worker  * Checks if both strings are equal or have the same content. "*"
3558*7c568831SAndroid Build Coastguard Worker  * can be used as a wildcard in @valStr; "|" is used as a separator of
3559*7c568831SAndroid Build Coastguard Worker  * substrings in both @expStr and @valStr.
3560*7c568831SAndroid Build Coastguard Worker  *
3561*7c568831SAndroid Build Coastguard Worker  * Returns 1 if the comparison is satisfied and the number of substrings
3562*7c568831SAndroid Build Coastguard Worker  * is equal, 0 otherwise.
3563*7c568831SAndroid Build Coastguard Worker  */
3564*7c568831SAndroid Build Coastguard Worker 
3565*7c568831SAndroid Build Coastguard Worker static int
xmlRegStrEqualWildcard(const xmlChar * expStr,const xmlChar * valStr)3566*7c568831SAndroid Build Coastguard Worker xmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr) {
3567*7c568831SAndroid Build Coastguard Worker     if (expStr == valStr) return(1);
3568*7c568831SAndroid Build Coastguard Worker     if (expStr == NULL) return(0);
3569*7c568831SAndroid Build Coastguard Worker     if (valStr == NULL) return(0);
3570*7c568831SAndroid Build Coastguard Worker     do {
3571*7c568831SAndroid Build Coastguard Worker 	/*
3572*7c568831SAndroid Build Coastguard Worker 	* Eval if we have a wildcard for the current item.
3573*7c568831SAndroid Build Coastguard Worker 	*/
3574*7c568831SAndroid Build Coastguard Worker         if (*expStr != *valStr) {
3575*7c568831SAndroid Build Coastguard Worker 	    /* if one of them starts with a wildcard make valStr be it */
3576*7c568831SAndroid Build Coastguard Worker 	    if (*valStr == '*') {
3577*7c568831SAndroid Build Coastguard Worker 	        const xmlChar *tmp;
3578*7c568831SAndroid Build Coastguard Worker 
3579*7c568831SAndroid Build Coastguard Worker 		tmp = valStr;
3580*7c568831SAndroid Build Coastguard Worker 		valStr = expStr;
3581*7c568831SAndroid Build Coastguard Worker 		expStr = tmp;
3582*7c568831SAndroid Build Coastguard Worker 	    }
3583*7c568831SAndroid Build Coastguard Worker 	    if ((*valStr != 0) && (*expStr != 0) && (*expStr++ == '*')) {
3584*7c568831SAndroid Build Coastguard Worker 		do {
3585*7c568831SAndroid Build Coastguard Worker 		    if (*valStr == XML_REG_STRING_SEPARATOR)
3586*7c568831SAndroid Build Coastguard Worker 			break;
3587*7c568831SAndroid Build Coastguard Worker 		    valStr++;
3588*7c568831SAndroid Build Coastguard Worker 		} while (*valStr != 0);
3589*7c568831SAndroid Build Coastguard Worker 		continue;
3590*7c568831SAndroid Build Coastguard Worker 	    } else
3591*7c568831SAndroid Build Coastguard Worker 		return(0);
3592*7c568831SAndroid Build Coastguard Worker 	}
3593*7c568831SAndroid Build Coastguard Worker 	expStr++;
3594*7c568831SAndroid Build Coastguard Worker 	valStr++;
3595*7c568831SAndroid Build Coastguard Worker     } while (*valStr != 0);
3596*7c568831SAndroid Build Coastguard Worker     if (*expStr != 0)
3597*7c568831SAndroid Build Coastguard Worker 	return (0);
3598*7c568831SAndroid Build Coastguard Worker     else
3599*7c568831SAndroid Build Coastguard Worker 	return (1);
3600*7c568831SAndroid Build Coastguard Worker }
3601*7c568831SAndroid Build Coastguard Worker 
3602*7c568831SAndroid Build Coastguard Worker /**
3603*7c568831SAndroid Build Coastguard Worker  * xmlRegCompactPushString:
3604*7c568831SAndroid Build Coastguard Worker  * @exec: a regexp execution context
3605*7c568831SAndroid Build Coastguard Worker  * @comp:  the precompiled exec with a compact table
3606*7c568831SAndroid Build Coastguard Worker  * @value: a string token input
3607*7c568831SAndroid Build Coastguard Worker  * @data: data associated to the token to reuse in callbacks
3608*7c568831SAndroid Build Coastguard Worker  *
3609*7c568831SAndroid Build Coastguard Worker  * Push one input token in the execution context
3610*7c568831SAndroid Build Coastguard Worker  *
3611*7c568831SAndroid Build Coastguard Worker  * Returns: 1 if the regexp reached a final state, 0 if non-final, and
3612*7c568831SAndroid Build Coastguard Worker  *     a negative value in case of error.
3613*7c568831SAndroid Build Coastguard Worker  */
3614*7c568831SAndroid Build Coastguard Worker static int
xmlRegCompactPushString(xmlRegExecCtxtPtr exec,xmlRegexpPtr comp,const xmlChar * value,void * data)3615*7c568831SAndroid Build Coastguard Worker xmlRegCompactPushString(xmlRegExecCtxtPtr exec,
3616*7c568831SAndroid Build Coastguard Worker 	                xmlRegexpPtr comp,
3617*7c568831SAndroid Build Coastguard Worker 	                const xmlChar *value,
3618*7c568831SAndroid Build Coastguard Worker 	                void *data) {
3619*7c568831SAndroid Build Coastguard Worker     int state = exec->index;
3620*7c568831SAndroid Build Coastguard Worker     int i, target;
3621*7c568831SAndroid Build Coastguard Worker 
3622*7c568831SAndroid Build Coastguard Worker     if ((comp == NULL) || (comp->compact == NULL) || (comp->stringMap == NULL))
3623*7c568831SAndroid Build Coastguard Worker 	return(-1);
3624*7c568831SAndroid Build Coastguard Worker 
3625*7c568831SAndroid Build Coastguard Worker     if (value == NULL) {
3626*7c568831SAndroid Build Coastguard Worker 	/*
3627*7c568831SAndroid Build Coastguard Worker 	 * are we at a final state ?
3628*7c568831SAndroid Build Coastguard Worker 	 */
3629*7c568831SAndroid Build Coastguard Worker 	if (comp->compact[state * (comp->nbstrings + 1)] ==
3630*7c568831SAndroid Build Coastguard Worker             XML_REGEXP_FINAL_STATE)
3631*7c568831SAndroid Build Coastguard Worker 	    return(1);
3632*7c568831SAndroid Build Coastguard Worker 	return(0);
3633*7c568831SAndroid Build Coastguard Worker     }
3634*7c568831SAndroid Build Coastguard Worker 
3635*7c568831SAndroid Build Coastguard Worker     /*
3636*7c568831SAndroid Build Coastguard Worker      * Examine all outside transitions from current state
3637*7c568831SAndroid Build Coastguard Worker      */
3638*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < comp->nbstrings;i++) {
3639*7c568831SAndroid Build Coastguard Worker 	target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
3640*7c568831SAndroid Build Coastguard Worker 	if ((target > 0) && (target <= comp->nbstates)) {
3641*7c568831SAndroid Build Coastguard Worker 	    target--; /* to avoid 0 */
3642*7c568831SAndroid Build Coastguard Worker 	    if (xmlRegStrEqualWildcard(comp->stringMap[i], value)) {
3643*7c568831SAndroid Build Coastguard Worker 		exec->index = target;
3644*7c568831SAndroid Build Coastguard Worker 		if ((exec->callback != NULL) && (comp->transdata != NULL)) {
3645*7c568831SAndroid Build Coastguard Worker 		    exec->callback(exec->data, value,
3646*7c568831SAndroid Build Coastguard Worker 			  comp->transdata[state * comp->nbstrings + i], data);
3647*7c568831SAndroid Build Coastguard Worker 		}
3648*7c568831SAndroid Build Coastguard Worker 		if (comp->compact[target * (comp->nbstrings + 1)] ==
3649*7c568831SAndroid Build Coastguard Worker 		    XML_REGEXP_SINK_STATE)
3650*7c568831SAndroid Build Coastguard Worker 		    goto error;
3651*7c568831SAndroid Build Coastguard Worker 
3652*7c568831SAndroid Build Coastguard Worker 		if (comp->compact[target * (comp->nbstrings + 1)] ==
3653*7c568831SAndroid Build Coastguard Worker 		    XML_REGEXP_FINAL_STATE)
3654*7c568831SAndroid Build Coastguard Worker 		    return(1);
3655*7c568831SAndroid Build Coastguard Worker 		return(0);
3656*7c568831SAndroid Build Coastguard Worker 	    }
3657*7c568831SAndroid Build Coastguard Worker 	}
3658*7c568831SAndroid Build Coastguard Worker     }
3659*7c568831SAndroid Build Coastguard Worker     /*
3660*7c568831SAndroid Build Coastguard Worker      * Failed to find an exit transition out from current state for the
3661*7c568831SAndroid Build Coastguard Worker      * current token
3662*7c568831SAndroid Build Coastguard Worker      */
3663*7c568831SAndroid Build Coastguard Worker error:
3664*7c568831SAndroid Build Coastguard Worker     exec->errStateNo = state;
3665*7c568831SAndroid Build Coastguard Worker     exec->status = XML_REGEXP_NOT_FOUND;
3666*7c568831SAndroid Build Coastguard Worker     xmlRegExecSetErrString(exec, value);
3667*7c568831SAndroid Build Coastguard Worker     return(exec->status);
3668*7c568831SAndroid Build Coastguard Worker }
3669*7c568831SAndroid Build Coastguard Worker 
3670*7c568831SAndroid Build Coastguard Worker /**
3671*7c568831SAndroid Build Coastguard Worker  * xmlRegExecPushStringInternal:
3672*7c568831SAndroid Build Coastguard Worker  * @exec: a regexp execution context or NULL to indicate the end
3673*7c568831SAndroid Build Coastguard Worker  * @value: a string token input
3674*7c568831SAndroid Build Coastguard Worker  * @data: data associated to the token to reuse in callbacks
3675*7c568831SAndroid Build Coastguard Worker  * @compound: value was assembled from 2 strings
3676*7c568831SAndroid Build Coastguard Worker  *
3677*7c568831SAndroid Build Coastguard Worker  * Push one input token in the execution context
3678*7c568831SAndroid Build Coastguard Worker  *
3679*7c568831SAndroid Build Coastguard Worker  * Returns: 1 if the regexp reached a final state, 0 if non-final, and
3680*7c568831SAndroid Build Coastguard Worker  *     a negative value in case of error.
3681*7c568831SAndroid Build Coastguard Worker  */
3682*7c568831SAndroid Build Coastguard Worker static int
xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec,const xmlChar * value,void * data,int compound)3683*7c568831SAndroid Build Coastguard Worker xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
3684*7c568831SAndroid Build Coastguard Worker 	                     void *data, int compound) {
3685*7c568831SAndroid Build Coastguard Worker     xmlRegTransPtr trans;
3686*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
3687*7c568831SAndroid Build Coastguard Worker     int ret;
3688*7c568831SAndroid Build Coastguard Worker     int final = 0;
3689*7c568831SAndroid Build Coastguard Worker     int progress = 1;
3690*7c568831SAndroid Build Coastguard Worker 
3691*7c568831SAndroid Build Coastguard Worker     if (exec == NULL)
3692*7c568831SAndroid Build Coastguard Worker 	return(-1);
3693*7c568831SAndroid Build Coastguard Worker     if (exec->comp == NULL)
3694*7c568831SAndroid Build Coastguard Worker 	return(-1);
3695*7c568831SAndroid Build Coastguard Worker     if (exec->status != XML_REGEXP_OK)
3696*7c568831SAndroid Build Coastguard Worker 	return(exec->status);
3697*7c568831SAndroid Build Coastguard Worker 
3698*7c568831SAndroid Build Coastguard Worker     if (exec->comp->compact != NULL)
3699*7c568831SAndroid Build Coastguard Worker 	return(xmlRegCompactPushString(exec, exec->comp, value, data));
3700*7c568831SAndroid Build Coastguard Worker 
3701*7c568831SAndroid Build Coastguard Worker     if (value == NULL) {
3702*7c568831SAndroid Build Coastguard Worker         if (exec->state->type == XML_REGEXP_FINAL_STATE)
3703*7c568831SAndroid Build Coastguard Worker 	    return(1);
3704*7c568831SAndroid Build Coastguard Worker 	final = 1;
3705*7c568831SAndroid Build Coastguard Worker     }
3706*7c568831SAndroid Build Coastguard Worker 
3707*7c568831SAndroid Build Coastguard Worker     /*
3708*7c568831SAndroid Build Coastguard Worker      * If we have an active rollback stack push the new value there
3709*7c568831SAndroid Build Coastguard Worker      * and get back to where we were left
3710*7c568831SAndroid Build Coastguard Worker      */
3711*7c568831SAndroid Build Coastguard Worker     if ((value != NULL) && (exec->inputStackNr > 0)) {
3712*7c568831SAndroid Build Coastguard Worker 	xmlFARegExecSaveInputString(exec, value, data);
3713*7c568831SAndroid Build Coastguard Worker 	value = exec->inputStack[exec->index].value;
3714*7c568831SAndroid Build Coastguard Worker 	data = exec->inputStack[exec->index].data;
3715*7c568831SAndroid Build Coastguard Worker     }
3716*7c568831SAndroid Build Coastguard Worker 
3717*7c568831SAndroid Build Coastguard Worker     while ((exec->status == XML_REGEXP_OK) &&
3718*7c568831SAndroid Build Coastguard Worker 	   ((value != NULL) ||
3719*7c568831SAndroid Build Coastguard Worker 	    ((final == 1) &&
3720*7c568831SAndroid Build Coastguard Worker 	     (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
3721*7c568831SAndroid Build Coastguard Worker 
3722*7c568831SAndroid Build Coastguard Worker 	/*
3723*7c568831SAndroid Build Coastguard Worker 	 * End of input on non-terminal state, rollback, however we may
3724*7c568831SAndroid Build Coastguard Worker 	 * still have epsilon like transition for counted transitions
3725*7c568831SAndroid Build Coastguard Worker 	 * on counters, in that case don't break too early.
3726*7c568831SAndroid Build Coastguard Worker 	 */
3727*7c568831SAndroid Build Coastguard Worker 	if ((value == NULL) && (exec->counts == NULL))
3728*7c568831SAndroid Build Coastguard Worker 	    goto rollback;
3729*7c568831SAndroid Build Coastguard Worker 
3730*7c568831SAndroid Build Coastguard Worker 	exec->transcount = 0;
3731*7c568831SAndroid Build Coastguard Worker 	for (;exec->transno < exec->state->nbTrans;exec->transno++) {
3732*7c568831SAndroid Build Coastguard Worker 	    trans = &exec->state->trans[exec->transno];
3733*7c568831SAndroid Build Coastguard Worker 	    if (trans->to < 0)
3734*7c568831SAndroid Build Coastguard Worker 		continue;
3735*7c568831SAndroid Build Coastguard Worker 	    atom = trans->atom;
3736*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
3737*7c568831SAndroid Build Coastguard Worker 	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
3738*7c568831SAndroid Build Coastguard Worker 		int i;
3739*7c568831SAndroid Build Coastguard Worker 		int count;
3740*7c568831SAndroid Build Coastguard Worker 		xmlRegTransPtr t;
3741*7c568831SAndroid Build Coastguard Worker 		xmlRegCounterPtr counter;
3742*7c568831SAndroid Build Coastguard Worker 
3743*7c568831SAndroid Build Coastguard Worker 		ret = 0;
3744*7c568831SAndroid Build Coastguard Worker 
3745*7c568831SAndroid Build Coastguard Worker 		/*
3746*7c568831SAndroid Build Coastguard Worker 		 * Check all counted transitions from the current state
3747*7c568831SAndroid Build Coastguard Worker 		 */
3748*7c568831SAndroid Build Coastguard Worker 		if ((value == NULL) && (final)) {
3749*7c568831SAndroid Build Coastguard Worker 		    ret = 1;
3750*7c568831SAndroid Build Coastguard Worker 		} else if (value != NULL) {
3751*7c568831SAndroid Build Coastguard Worker 		    for (i = 0;i < exec->state->nbTrans;i++) {
3752*7c568831SAndroid Build Coastguard Worker 			t = &exec->state->trans[i];
3753*7c568831SAndroid Build Coastguard Worker 			if ((t->counter < 0) || (t == trans))
3754*7c568831SAndroid Build Coastguard Worker 			    continue;
3755*7c568831SAndroid Build Coastguard Worker 			counter = &exec->comp->counters[t->counter];
3756*7c568831SAndroid Build Coastguard Worker 			count = exec->counts[t->counter];
3757*7c568831SAndroid Build Coastguard Worker 			if ((count < counter->max) &&
3758*7c568831SAndroid Build Coastguard Worker 		            (t->atom != NULL) &&
3759*7c568831SAndroid Build Coastguard Worker 			    (xmlStrEqual(value, t->atom->valuep))) {
3760*7c568831SAndroid Build Coastguard Worker 			    ret = 0;
3761*7c568831SAndroid Build Coastguard Worker 			    break;
3762*7c568831SAndroid Build Coastguard Worker 			}
3763*7c568831SAndroid Build Coastguard Worker 			if ((count >= counter->min) &&
3764*7c568831SAndroid Build Coastguard Worker 			    (count < counter->max) &&
3765*7c568831SAndroid Build Coastguard Worker 			    (t->atom != NULL) &&
3766*7c568831SAndroid Build Coastguard Worker 			    (xmlStrEqual(value, t->atom->valuep))) {
3767*7c568831SAndroid Build Coastguard Worker 			    ret = 1;
3768*7c568831SAndroid Build Coastguard Worker 			    break;
3769*7c568831SAndroid Build Coastguard Worker 			}
3770*7c568831SAndroid Build Coastguard Worker 		    }
3771*7c568831SAndroid Build Coastguard Worker 		}
3772*7c568831SAndroid Build Coastguard Worker 	    } else if (trans->count == REGEXP_ALL_COUNTER) {
3773*7c568831SAndroid Build Coastguard Worker 		int i;
3774*7c568831SAndroid Build Coastguard Worker 		int count;
3775*7c568831SAndroid Build Coastguard Worker 		xmlRegTransPtr t;
3776*7c568831SAndroid Build Coastguard Worker 		xmlRegCounterPtr counter;
3777*7c568831SAndroid Build Coastguard Worker 
3778*7c568831SAndroid Build Coastguard Worker 		ret = 1;
3779*7c568831SAndroid Build Coastguard Worker 
3780*7c568831SAndroid Build Coastguard Worker 		/*
3781*7c568831SAndroid Build Coastguard Worker 		 * Check all counted transitions from the current state
3782*7c568831SAndroid Build Coastguard Worker 		 */
3783*7c568831SAndroid Build Coastguard Worker 		for (i = 0;i < exec->state->nbTrans;i++) {
3784*7c568831SAndroid Build Coastguard Worker                     t = &exec->state->trans[i];
3785*7c568831SAndroid Build Coastguard Worker 		    if ((t->counter < 0) || (t == trans))
3786*7c568831SAndroid Build Coastguard Worker 			continue;
3787*7c568831SAndroid Build Coastguard Worker                     counter = &exec->comp->counters[t->counter];
3788*7c568831SAndroid Build Coastguard Worker 		    count = exec->counts[t->counter];
3789*7c568831SAndroid Build Coastguard Worker 		    if ((count < counter->min) || (count > counter->max)) {
3790*7c568831SAndroid Build Coastguard Worker 			ret = 0;
3791*7c568831SAndroid Build Coastguard Worker 			break;
3792*7c568831SAndroid Build Coastguard Worker 		    }
3793*7c568831SAndroid Build Coastguard Worker 		}
3794*7c568831SAndroid Build Coastguard Worker 	    } else if (trans->count >= 0) {
3795*7c568831SAndroid Build Coastguard Worker 		int count;
3796*7c568831SAndroid Build Coastguard Worker 		xmlRegCounterPtr counter;
3797*7c568831SAndroid Build Coastguard Worker 
3798*7c568831SAndroid Build Coastguard Worker 		/*
3799*7c568831SAndroid Build Coastguard Worker 		 * A counted transition.
3800*7c568831SAndroid Build Coastguard Worker 		 */
3801*7c568831SAndroid Build Coastguard Worker 
3802*7c568831SAndroid Build Coastguard Worker 		count = exec->counts[trans->count];
3803*7c568831SAndroid Build Coastguard Worker 		counter = &exec->comp->counters[trans->count];
3804*7c568831SAndroid Build Coastguard Worker 		ret = ((count >= counter->min) && (count <= counter->max));
3805*7c568831SAndroid Build Coastguard Worker 	    } else if (atom == NULL) {
3806*7c568831SAndroid Build Coastguard Worker 		exec->status = XML_REGEXP_INTERNAL_ERROR;
3807*7c568831SAndroid Build Coastguard Worker 		break;
3808*7c568831SAndroid Build Coastguard Worker 	    } else if (value != NULL) {
3809*7c568831SAndroid Build Coastguard Worker 		ret = xmlRegStrEqualWildcard(atom->valuep, value);
3810*7c568831SAndroid Build Coastguard Worker 		if (atom->neg) {
3811*7c568831SAndroid Build Coastguard Worker 		    ret = !ret;
3812*7c568831SAndroid Build Coastguard Worker 		    if (!compound)
3813*7c568831SAndroid Build Coastguard Worker 		        ret = 0;
3814*7c568831SAndroid Build Coastguard Worker 		}
3815*7c568831SAndroid Build Coastguard Worker 		if ((ret == 1) && (trans->counter >= 0)) {
3816*7c568831SAndroid Build Coastguard Worker 		    xmlRegCounterPtr counter;
3817*7c568831SAndroid Build Coastguard Worker 		    int count;
3818*7c568831SAndroid Build Coastguard Worker 
3819*7c568831SAndroid Build Coastguard Worker 		    count = exec->counts[trans->counter];
3820*7c568831SAndroid Build Coastguard Worker 		    counter = &exec->comp->counters[trans->counter];
3821*7c568831SAndroid Build Coastguard Worker 		    if (count >= counter->max)
3822*7c568831SAndroid Build Coastguard Worker 			ret = 0;
3823*7c568831SAndroid Build Coastguard Worker 		}
3824*7c568831SAndroid Build Coastguard Worker 
3825*7c568831SAndroid Build Coastguard Worker 		if ((ret == 1) && (atom->min > 0) && (atom->max > 0)) {
3826*7c568831SAndroid Build Coastguard Worker 		    xmlRegStatePtr to = exec->comp->states[trans->to];
3827*7c568831SAndroid Build Coastguard Worker 
3828*7c568831SAndroid Build Coastguard Worker 		    /*
3829*7c568831SAndroid Build Coastguard Worker 		     * this is a multiple input sequence
3830*7c568831SAndroid Build Coastguard Worker 		     */
3831*7c568831SAndroid Build Coastguard Worker 		    if (exec->state->nbTrans > exec->transno + 1) {
3832*7c568831SAndroid Build Coastguard Worker 			if (exec->inputStackNr <= 0) {
3833*7c568831SAndroid Build Coastguard Worker 			    xmlFARegExecSaveInputString(exec, value, data);
3834*7c568831SAndroid Build Coastguard Worker 			}
3835*7c568831SAndroid Build Coastguard Worker 			xmlFARegExecSave(exec);
3836*7c568831SAndroid Build Coastguard Worker 		    }
3837*7c568831SAndroid Build Coastguard Worker 		    exec->transcount = 1;
3838*7c568831SAndroid Build Coastguard Worker 		    do {
3839*7c568831SAndroid Build Coastguard Worker 			/*
3840*7c568831SAndroid Build Coastguard Worker 			 * Try to progress as much as possible on the input
3841*7c568831SAndroid Build Coastguard Worker 			 */
3842*7c568831SAndroid Build Coastguard Worker 			if (exec->transcount == atom->max) {
3843*7c568831SAndroid Build Coastguard Worker 			    break;
3844*7c568831SAndroid Build Coastguard Worker 			}
3845*7c568831SAndroid Build Coastguard Worker 			exec->index++;
3846*7c568831SAndroid Build Coastguard Worker 			value = exec->inputStack[exec->index].value;
3847*7c568831SAndroid Build Coastguard Worker 			data = exec->inputStack[exec->index].data;
3848*7c568831SAndroid Build Coastguard Worker 
3849*7c568831SAndroid Build Coastguard Worker 			/*
3850*7c568831SAndroid Build Coastguard Worker 			 * End of input: stop here
3851*7c568831SAndroid Build Coastguard Worker 			 */
3852*7c568831SAndroid Build Coastguard Worker 			if (value == NULL) {
3853*7c568831SAndroid Build Coastguard Worker 			    exec->index --;
3854*7c568831SAndroid Build Coastguard Worker 			    break;
3855*7c568831SAndroid Build Coastguard Worker 			}
3856*7c568831SAndroid Build Coastguard Worker 			if (exec->transcount >= atom->min) {
3857*7c568831SAndroid Build Coastguard Worker 			    int transno = exec->transno;
3858*7c568831SAndroid Build Coastguard Worker 			    xmlRegStatePtr state = exec->state;
3859*7c568831SAndroid Build Coastguard Worker 
3860*7c568831SAndroid Build Coastguard Worker 			    /*
3861*7c568831SAndroid Build Coastguard Worker 			     * The transition is acceptable save it
3862*7c568831SAndroid Build Coastguard Worker 			     */
3863*7c568831SAndroid Build Coastguard Worker 			    exec->transno = -1; /* trick */
3864*7c568831SAndroid Build Coastguard Worker 			    exec->state = to;
3865*7c568831SAndroid Build Coastguard Worker 			    if (exec->inputStackNr <= 0) {
3866*7c568831SAndroid Build Coastguard Worker 				xmlFARegExecSaveInputString(exec, value, data);
3867*7c568831SAndroid Build Coastguard Worker 			    }
3868*7c568831SAndroid Build Coastguard Worker 			    xmlFARegExecSave(exec);
3869*7c568831SAndroid Build Coastguard Worker 			    exec->transno = transno;
3870*7c568831SAndroid Build Coastguard Worker 			    exec->state = state;
3871*7c568831SAndroid Build Coastguard Worker 			}
3872*7c568831SAndroid Build Coastguard Worker 			ret = xmlStrEqual(value, atom->valuep);
3873*7c568831SAndroid Build Coastguard Worker 			exec->transcount++;
3874*7c568831SAndroid Build Coastguard Worker 		    } while (ret == 1);
3875*7c568831SAndroid Build Coastguard Worker 		    if (exec->transcount < atom->min)
3876*7c568831SAndroid Build Coastguard Worker 			ret = 0;
3877*7c568831SAndroid Build Coastguard Worker 
3878*7c568831SAndroid Build Coastguard Worker 		    /*
3879*7c568831SAndroid Build Coastguard Worker 		     * If the last check failed but one transition was found
3880*7c568831SAndroid Build Coastguard Worker 		     * possible, rollback
3881*7c568831SAndroid Build Coastguard Worker 		     */
3882*7c568831SAndroid Build Coastguard Worker 		    if (ret < 0)
3883*7c568831SAndroid Build Coastguard Worker 			ret = 0;
3884*7c568831SAndroid Build Coastguard Worker 		    if (ret == 0) {
3885*7c568831SAndroid Build Coastguard Worker 			goto rollback;
3886*7c568831SAndroid Build Coastguard Worker 		    }
3887*7c568831SAndroid Build Coastguard Worker 		}
3888*7c568831SAndroid Build Coastguard Worker 	    }
3889*7c568831SAndroid Build Coastguard Worker 	    if (ret == 1) {
3890*7c568831SAndroid Build Coastguard Worker 		if ((exec->callback != NULL) && (atom != NULL) &&
3891*7c568831SAndroid Build Coastguard Worker 			(data != NULL)) {
3892*7c568831SAndroid Build Coastguard Worker 		    exec->callback(exec->data, atom->valuep,
3893*7c568831SAndroid Build Coastguard Worker 			           atom->data, data);
3894*7c568831SAndroid Build Coastguard Worker 		}
3895*7c568831SAndroid Build Coastguard Worker 		if (exec->state->nbTrans > exec->transno + 1) {
3896*7c568831SAndroid Build Coastguard Worker 		    if (exec->inputStackNr <= 0) {
3897*7c568831SAndroid Build Coastguard Worker 			xmlFARegExecSaveInputString(exec, value, data);
3898*7c568831SAndroid Build Coastguard Worker 		    }
3899*7c568831SAndroid Build Coastguard Worker 		    xmlFARegExecSave(exec);
3900*7c568831SAndroid Build Coastguard Worker 		}
3901*7c568831SAndroid Build Coastguard Worker 		if (trans->counter >= 0) {
3902*7c568831SAndroid Build Coastguard Worker 		    exec->counts[trans->counter]++;
3903*7c568831SAndroid Build Coastguard Worker 		}
3904*7c568831SAndroid Build Coastguard Worker 		if ((trans->count >= 0) &&
3905*7c568831SAndroid Build Coastguard Worker 		    (trans->count < REGEXP_ALL_COUNTER)) {
3906*7c568831SAndroid Build Coastguard Worker 		    exec->counts[trans->count] = 0;
3907*7c568831SAndroid Build Coastguard Worker 		}
3908*7c568831SAndroid Build Coastguard Worker                 if ((exec->comp->states[trans->to] != NULL) &&
3909*7c568831SAndroid Build Coastguard Worker 		    (exec->comp->states[trans->to]->type ==
3910*7c568831SAndroid Build Coastguard Worker 		     XML_REGEXP_SINK_STATE)) {
3911*7c568831SAndroid Build Coastguard Worker 		    /*
3912*7c568831SAndroid Build Coastguard Worker 		     * entering a sink state, save the current state as error
3913*7c568831SAndroid Build Coastguard Worker 		     * state.
3914*7c568831SAndroid Build Coastguard Worker 		     */
3915*7c568831SAndroid Build Coastguard Worker                     if (xmlRegExecSetErrString(exec, value) < 0)
3916*7c568831SAndroid Build Coastguard Worker                         break;
3917*7c568831SAndroid Build Coastguard Worker 		    exec->errState = exec->state;
3918*7c568831SAndroid Build Coastguard Worker 		    memcpy(exec->errCounts, exec->counts,
3919*7c568831SAndroid Build Coastguard Worker 			   exec->comp->nbCounters * sizeof(int));
3920*7c568831SAndroid Build Coastguard Worker 		}
3921*7c568831SAndroid Build Coastguard Worker 		exec->state = exec->comp->states[trans->to];
3922*7c568831SAndroid Build Coastguard Worker 		exec->transno = 0;
3923*7c568831SAndroid Build Coastguard Worker 		if (trans->atom != NULL) {
3924*7c568831SAndroid Build Coastguard Worker 		    if (exec->inputStack != NULL) {
3925*7c568831SAndroid Build Coastguard Worker 			exec->index++;
3926*7c568831SAndroid Build Coastguard Worker 			if (exec->index < exec->inputStackNr) {
3927*7c568831SAndroid Build Coastguard Worker 			    value = exec->inputStack[exec->index].value;
3928*7c568831SAndroid Build Coastguard Worker 			    data = exec->inputStack[exec->index].data;
3929*7c568831SAndroid Build Coastguard Worker 			} else {
3930*7c568831SAndroid Build Coastguard Worker 			    value = NULL;
3931*7c568831SAndroid Build Coastguard Worker 			    data = NULL;
3932*7c568831SAndroid Build Coastguard Worker 			}
3933*7c568831SAndroid Build Coastguard Worker 		    } else {
3934*7c568831SAndroid Build Coastguard Worker 			value = NULL;
3935*7c568831SAndroid Build Coastguard Worker 			data = NULL;
3936*7c568831SAndroid Build Coastguard Worker 		    }
3937*7c568831SAndroid Build Coastguard Worker 		}
3938*7c568831SAndroid Build Coastguard Worker 		goto progress;
3939*7c568831SAndroid Build Coastguard Worker 	    } else if (ret < 0) {
3940*7c568831SAndroid Build Coastguard Worker 		exec->status = XML_REGEXP_INTERNAL_ERROR;
3941*7c568831SAndroid Build Coastguard Worker 		break;
3942*7c568831SAndroid Build Coastguard Worker 	    }
3943*7c568831SAndroid Build Coastguard Worker 	}
3944*7c568831SAndroid Build Coastguard Worker 	if ((exec->transno != 0) || (exec->state->nbTrans == 0)) {
3945*7c568831SAndroid Build Coastguard Worker rollback:
3946*7c568831SAndroid Build Coastguard Worker             /*
3947*7c568831SAndroid Build Coastguard Worker 	     * if we didn't yet rollback on the current input
3948*7c568831SAndroid Build Coastguard Worker 	     * store the current state as the error state.
3949*7c568831SAndroid Build Coastguard Worker 	     */
3950*7c568831SAndroid Build Coastguard Worker 	    if ((progress) && (exec->state != NULL) &&
3951*7c568831SAndroid Build Coastguard Worker 	        (exec->state->type != XML_REGEXP_SINK_STATE)) {
3952*7c568831SAndroid Build Coastguard Worker 	        progress = 0;
3953*7c568831SAndroid Build Coastguard Worker                 if (xmlRegExecSetErrString(exec, value) < 0)
3954*7c568831SAndroid Build Coastguard Worker                     break;
3955*7c568831SAndroid Build Coastguard Worker 		exec->errState = exec->state;
3956*7c568831SAndroid Build Coastguard Worker                 if (exec->comp->nbCounters)
3957*7c568831SAndroid Build Coastguard Worker                     memcpy(exec->errCounts, exec->counts,
3958*7c568831SAndroid Build Coastguard Worker                            exec->comp->nbCounters * sizeof(int));
3959*7c568831SAndroid Build Coastguard Worker 	    }
3960*7c568831SAndroid Build Coastguard Worker 
3961*7c568831SAndroid Build Coastguard Worker 	    /*
3962*7c568831SAndroid Build Coastguard Worker 	     * Failed to find a way out
3963*7c568831SAndroid Build Coastguard Worker 	     */
3964*7c568831SAndroid Build Coastguard Worker 	    exec->determinist = 0;
3965*7c568831SAndroid Build Coastguard Worker 	    xmlFARegExecRollBack(exec);
3966*7c568831SAndroid Build Coastguard Worker 	    if ((exec->inputStack != NULL ) &&
3967*7c568831SAndroid Build Coastguard Worker                 (exec->status == XML_REGEXP_OK)) {
3968*7c568831SAndroid Build Coastguard Worker 		value = exec->inputStack[exec->index].value;
3969*7c568831SAndroid Build Coastguard Worker 		data = exec->inputStack[exec->index].data;
3970*7c568831SAndroid Build Coastguard Worker 	    }
3971*7c568831SAndroid Build Coastguard Worker 	}
3972*7c568831SAndroid Build Coastguard Worker 	continue;
3973*7c568831SAndroid Build Coastguard Worker progress:
3974*7c568831SAndroid Build Coastguard Worker         progress = 1;
3975*7c568831SAndroid Build Coastguard Worker     }
3976*7c568831SAndroid Build Coastguard Worker     if (exec->status == XML_REGEXP_OK) {
3977*7c568831SAndroid Build Coastguard Worker         return(exec->state->type == XML_REGEXP_FINAL_STATE);
3978*7c568831SAndroid Build Coastguard Worker     }
3979*7c568831SAndroid Build Coastguard Worker     return(exec->status);
3980*7c568831SAndroid Build Coastguard Worker }
3981*7c568831SAndroid Build Coastguard Worker 
3982*7c568831SAndroid Build Coastguard Worker /**
3983*7c568831SAndroid Build Coastguard Worker  * xmlRegExecPushString:
3984*7c568831SAndroid Build Coastguard Worker  * @exec: a regexp execution context or NULL to indicate the end
3985*7c568831SAndroid Build Coastguard Worker  * @value: a string token input
3986*7c568831SAndroid Build Coastguard Worker  * @data: data associated to the token to reuse in callbacks
3987*7c568831SAndroid Build Coastguard Worker  *
3988*7c568831SAndroid Build Coastguard Worker  * Push one input token in the execution context
3989*7c568831SAndroid Build Coastguard Worker  *
3990*7c568831SAndroid Build Coastguard Worker  * Returns: 1 if the regexp reached a final state, 0 if non-final, and
3991*7c568831SAndroid Build Coastguard Worker  *     a negative value in case of error.
3992*7c568831SAndroid Build Coastguard Worker  */
3993*7c568831SAndroid Build Coastguard Worker int
xmlRegExecPushString(xmlRegExecCtxtPtr exec,const xmlChar * value,void * data)3994*7c568831SAndroid Build Coastguard Worker xmlRegExecPushString(xmlRegExecCtxtPtr exec, const xmlChar *value,
3995*7c568831SAndroid Build Coastguard Worker 	             void *data) {
3996*7c568831SAndroid Build Coastguard Worker     return(xmlRegExecPushStringInternal(exec, value, data, 0));
3997*7c568831SAndroid Build Coastguard Worker }
3998*7c568831SAndroid Build Coastguard Worker 
3999*7c568831SAndroid Build Coastguard Worker /**
4000*7c568831SAndroid Build Coastguard Worker  * xmlRegExecPushString2:
4001*7c568831SAndroid Build Coastguard Worker  * @exec: a regexp execution context or NULL to indicate the end
4002*7c568831SAndroid Build Coastguard Worker  * @value: the first string token input
4003*7c568831SAndroid Build Coastguard Worker  * @value2: the second string token input
4004*7c568831SAndroid Build Coastguard Worker  * @data: data associated to the token to reuse in callbacks
4005*7c568831SAndroid Build Coastguard Worker  *
4006*7c568831SAndroid Build Coastguard Worker  * Push one input token in the execution context
4007*7c568831SAndroid Build Coastguard Worker  *
4008*7c568831SAndroid Build Coastguard Worker  * Returns: 1 if the regexp reached a final state, 0 if non-final, and
4009*7c568831SAndroid Build Coastguard Worker  *     a negative value in case of error.
4010*7c568831SAndroid Build Coastguard Worker  */
4011*7c568831SAndroid Build Coastguard Worker int
xmlRegExecPushString2(xmlRegExecCtxtPtr exec,const xmlChar * value,const xmlChar * value2,void * data)4012*7c568831SAndroid Build Coastguard Worker xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value,
4013*7c568831SAndroid Build Coastguard Worker                       const xmlChar *value2, void *data) {
4014*7c568831SAndroid Build Coastguard Worker     xmlChar buf[150];
4015*7c568831SAndroid Build Coastguard Worker     int lenn, lenp, ret;
4016*7c568831SAndroid Build Coastguard Worker     xmlChar *str;
4017*7c568831SAndroid Build Coastguard Worker 
4018*7c568831SAndroid Build Coastguard Worker     if (exec == NULL)
4019*7c568831SAndroid Build Coastguard Worker 	return(-1);
4020*7c568831SAndroid Build Coastguard Worker     if (exec->comp == NULL)
4021*7c568831SAndroid Build Coastguard Worker 	return(-1);
4022*7c568831SAndroid Build Coastguard Worker     if (exec->status != XML_REGEXP_OK)
4023*7c568831SAndroid Build Coastguard Worker 	return(exec->status);
4024*7c568831SAndroid Build Coastguard Worker 
4025*7c568831SAndroid Build Coastguard Worker     if (value2 == NULL)
4026*7c568831SAndroid Build Coastguard Worker         return(xmlRegExecPushString(exec, value, data));
4027*7c568831SAndroid Build Coastguard Worker 
4028*7c568831SAndroid Build Coastguard Worker     lenn = strlen((char *) value2);
4029*7c568831SAndroid Build Coastguard Worker     lenp = strlen((char *) value);
4030*7c568831SAndroid Build Coastguard Worker 
4031*7c568831SAndroid Build Coastguard Worker     if (150 < lenn + lenp + 2) {
4032*7c568831SAndroid Build Coastguard Worker 	str = xmlMalloc(lenn + lenp + 2);
4033*7c568831SAndroid Build Coastguard Worker 	if (str == NULL) {
4034*7c568831SAndroid Build Coastguard Worker 	    exec->status = XML_REGEXP_OUT_OF_MEMORY;
4035*7c568831SAndroid Build Coastguard Worker 	    return(-1);
4036*7c568831SAndroid Build Coastguard Worker 	}
4037*7c568831SAndroid Build Coastguard Worker     } else {
4038*7c568831SAndroid Build Coastguard Worker 	str = buf;
4039*7c568831SAndroid Build Coastguard Worker     }
4040*7c568831SAndroid Build Coastguard Worker     memcpy(&str[0], value, lenp);
4041*7c568831SAndroid Build Coastguard Worker     str[lenp] = XML_REG_STRING_SEPARATOR;
4042*7c568831SAndroid Build Coastguard Worker     memcpy(&str[lenp + 1], value2, lenn);
4043*7c568831SAndroid Build Coastguard Worker     str[lenn + lenp + 1] = 0;
4044*7c568831SAndroid Build Coastguard Worker 
4045*7c568831SAndroid Build Coastguard Worker     if (exec->comp->compact != NULL)
4046*7c568831SAndroid Build Coastguard Worker 	ret = xmlRegCompactPushString(exec, exec->comp, str, data);
4047*7c568831SAndroid Build Coastguard Worker     else
4048*7c568831SAndroid Build Coastguard Worker         ret = xmlRegExecPushStringInternal(exec, str, data, 1);
4049*7c568831SAndroid Build Coastguard Worker 
4050*7c568831SAndroid Build Coastguard Worker     if (str != buf)
4051*7c568831SAndroid Build Coastguard Worker         xmlFree(str);
4052*7c568831SAndroid Build Coastguard Worker     return(ret);
4053*7c568831SAndroid Build Coastguard Worker }
4054*7c568831SAndroid Build Coastguard Worker 
4055*7c568831SAndroid Build Coastguard Worker /**
4056*7c568831SAndroid Build Coastguard Worker  * xmlRegExecGetValues:
4057*7c568831SAndroid Build Coastguard Worker  * @exec: a regexp execution context
4058*7c568831SAndroid Build Coastguard Worker  * @err: error extraction or normal one
4059*7c568831SAndroid Build Coastguard Worker  * @nbval: pointer to the number of accepted values IN/OUT
4060*7c568831SAndroid Build Coastguard Worker  * @nbneg: return number of negative transitions
4061*7c568831SAndroid Build Coastguard Worker  * @values: pointer to the array of acceptable values
4062*7c568831SAndroid Build Coastguard Worker  * @terminal: return value if this was a terminal state
4063*7c568831SAndroid Build Coastguard Worker  *
4064*7c568831SAndroid Build Coastguard Worker  * Extract information from the regexp execution, internal routine to
4065*7c568831SAndroid Build Coastguard Worker  * implement xmlRegExecNextValues() and xmlRegExecErrInfo()
4066*7c568831SAndroid Build Coastguard Worker  *
4067*7c568831SAndroid Build Coastguard Worker  * Returns: 0 in case of success or -1 in case of error.
4068*7c568831SAndroid Build Coastguard Worker  */
4069*7c568831SAndroid Build Coastguard Worker static int
xmlRegExecGetValues(xmlRegExecCtxtPtr exec,int err,int * nbval,int * nbneg,xmlChar ** values,int * terminal)4070*7c568831SAndroid Build Coastguard Worker xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
4071*7c568831SAndroid Build Coastguard Worker                     int *nbval, int *nbneg,
4072*7c568831SAndroid Build Coastguard Worker 		    xmlChar **values, int *terminal) {
4073*7c568831SAndroid Build Coastguard Worker     int maxval;
4074*7c568831SAndroid Build Coastguard Worker     int nb = 0;
4075*7c568831SAndroid Build Coastguard Worker 
4076*7c568831SAndroid Build Coastguard Worker     if ((exec == NULL) || (nbval == NULL) || (nbneg == NULL) ||
4077*7c568831SAndroid Build Coastguard Worker         (values == NULL) || (*nbval <= 0))
4078*7c568831SAndroid Build Coastguard Worker         return(-1);
4079*7c568831SAndroid Build Coastguard Worker 
4080*7c568831SAndroid Build Coastguard Worker     maxval = *nbval;
4081*7c568831SAndroid Build Coastguard Worker     *nbval = 0;
4082*7c568831SAndroid Build Coastguard Worker     *nbneg = 0;
4083*7c568831SAndroid Build Coastguard Worker     if ((exec->comp != NULL) && (exec->comp->compact != NULL)) {
4084*7c568831SAndroid Build Coastguard Worker         xmlRegexpPtr comp;
4085*7c568831SAndroid Build Coastguard Worker 	int target, i, state;
4086*7c568831SAndroid Build Coastguard Worker 
4087*7c568831SAndroid Build Coastguard Worker         comp = exec->comp;
4088*7c568831SAndroid Build Coastguard Worker 
4089*7c568831SAndroid Build Coastguard Worker 	if (err) {
4090*7c568831SAndroid Build Coastguard Worker 	    if (exec->errStateNo == -1) return(-1);
4091*7c568831SAndroid Build Coastguard Worker 	    state = exec->errStateNo;
4092*7c568831SAndroid Build Coastguard Worker 	} else {
4093*7c568831SAndroid Build Coastguard Worker 	    state = exec->index;
4094*7c568831SAndroid Build Coastguard Worker 	}
4095*7c568831SAndroid Build Coastguard Worker 	if (terminal != NULL) {
4096*7c568831SAndroid Build Coastguard Worker 	    if (comp->compact[state * (comp->nbstrings + 1)] ==
4097*7c568831SAndroid Build Coastguard Worker 	        XML_REGEXP_FINAL_STATE)
4098*7c568831SAndroid Build Coastguard Worker 		*terminal = 1;
4099*7c568831SAndroid Build Coastguard Worker 	    else
4100*7c568831SAndroid Build Coastguard Worker 		*terminal = 0;
4101*7c568831SAndroid Build Coastguard Worker 	}
4102*7c568831SAndroid Build Coastguard Worker 	for (i = 0;(i < comp->nbstrings) && (nb < maxval);i++) {
4103*7c568831SAndroid Build Coastguard Worker 	    target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
4104*7c568831SAndroid Build Coastguard Worker 	    if ((target > 0) && (target <= comp->nbstates) &&
4105*7c568831SAndroid Build Coastguard Worker 	        (comp->compact[(target - 1) * (comp->nbstrings + 1)] !=
4106*7c568831SAndroid Build Coastguard Worker 		 XML_REGEXP_SINK_STATE)) {
4107*7c568831SAndroid Build Coastguard Worker 	        values[nb++] = comp->stringMap[i];
4108*7c568831SAndroid Build Coastguard Worker 		(*nbval)++;
4109*7c568831SAndroid Build Coastguard Worker 	    }
4110*7c568831SAndroid Build Coastguard Worker 	}
4111*7c568831SAndroid Build Coastguard Worker 	for (i = 0;(i < comp->nbstrings) && (nb < maxval);i++) {
4112*7c568831SAndroid Build Coastguard Worker 	    target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
4113*7c568831SAndroid Build Coastguard Worker 	    if ((target > 0) && (target <= comp->nbstates) &&
4114*7c568831SAndroid Build Coastguard Worker 	        (comp->compact[(target - 1) * (comp->nbstrings + 1)] ==
4115*7c568831SAndroid Build Coastguard Worker 		 XML_REGEXP_SINK_STATE)) {
4116*7c568831SAndroid Build Coastguard Worker 	        values[nb++] = comp->stringMap[i];
4117*7c568831SAndroid Build Coastguard Worker 		(*nbneg)++;
4118*7c568831SAndroid Build Coastguard Worker 	    }
4119*7c568831SAndroid Build Coastguard Worker 	}
4120*7c568831SAndroid Build Coastguard Worker     } else {
4121*7c568831SAndroid Build Coastguard Worker         int transno;
4122*7c568831SAndroid Build Coastguard Worker 	xmlRegTransPtr trans;
4123*7c568831SAndroid Build Coastguard Worker 	xmlRegAtomPtr atom;
4124*7c568831SAndroid Build Coastguard Worker 	xmlRegStatePtr state;
4125*7c568831SAndroid Build Coastguard Worker 
4126*7c568831SAndroid Build Coastguard Worker 	if (terminal != NULL) {
4127*7c568831SAndroid Build Coastguard Worker 	    if (exec->state->type == XML_REGEXP_FINAL_STATE)
4128*7c568831SAndroid Build Coastguard Worker 		*terminal = 1;
4129*7c568831SAndroid Build Coastguard Worker 	    else
4130*7c568831SAndroid Build Coastguard Worker 		*terminal = 0;
4131*7c568831SAndroid Build Coastguard Worker 	}
4132*7c568831SAndroid Build Coastguard Worker 
4133*7c568831SAndroid Build Coastguard Worker 	if (err) {
4134*7c568831SAndroid Build Coastguard Worker 	    if (exec->errState == NULL) return(-1);
4135*7c568831SAndroid Build Coastguard Worker 	    state = exec->errState;
4136*7c568831SAndroid Build Coastguard Worker 	} else {
4137*7c568831SAndroid Build Coastguard Worker 	    if (exec->state == NULL) return(-1);
4138*7c568831SAndroid Build Coastguard Worker 	    state = exec->state;
4139*7c568831SAndroid Build Coastguard Worker 	}
4140*7c568831SAndroid Build Coastguard Worker 	for (transno = 0;
4141*7c568831SAndroid Build Coastguard Worker 	     (transno < state->nbTrans) && (nb < maxval);
4142*7c568831SAndroid Build Coastguard Worker 	     transno++) {
4143*7c568831SAndroid Build Coastguard Worker 	    trans = &state->trans[transno];
4144*7c568831SAndroid Build Coastguard Worker 	    if (trans->to < 0)
4145*7c568831SAndroid Build Coastguard Worker 		continue;
4146*7c568831SAndroid Build Coastguard Worker 	    atom = trans->atom;
4147*7c568831SAndroid Build Coastguard Worker 	    if ((atom == NULL) || (atom->valuep == NULL))
4148*7c568831SAndroid Build Coastguard Worker 		continue;
4149*7c568831SAndroid Build Coastguard Worker 	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
4150*7c568831SAndroid Build Coastguard Worker 	        /* this should not be reached but ... */
4151*7c568831SAndroid Build Coastguard Worker 	    } else if (trans->count == REGEXP_ALL_COUNTER) {
4152*7c568831SAndroid Build Coastguard Worker 	        /* this should not be reached but ... */
4153*7c568831SAndroid Build Coastguard Worker 	    } else if (trans->counter >= 0) {
4154*7c568831SAndroid Build Coastguard Worker 		xmlRegCounterPtr counter = NULL;
4155*7c568831SAndroid Build Coastguard Worker 		int count;
4156*7c568831SAndroid Build Coastguard Worker 
4157*7c568831SAndroid Build Coastguard Worker 		if (err)
4158*7c568831SAndroid Build Coastguard Worker 		    count = exec->errCounts[trans->counter];
4159*7c568831SAndroid Build Coastguard Worker 		else
4160*7c568831SAndroid Build Coastguard Worker 		    count = exec->counts[trans->counter];
4161*7c568831SAndroid Build Coastguard Worker 		if (exec->comp != NULL)
4162*7c568831SAndroid Build Coastguard Worker 		    counter = &exec->comp->counters[trans->counter];
4163*7c568831SAndroid Build Coastguard Worker 		if ((counter == NULL) || (count < counter->max)) {
4164*7c568831SAndroid Build Coastguard Worker 		    if (atom->neg)
4165*7c568831SAndroid Build Coastguard Worker 			values[nb++] = (xmlChar *) atom->valuep2;
4166*7c568831SAndroid Build Coastguard Worker 		    else
4167*7c568831SAndroid Build Coastguard Worker 			values[nb++] = (xmlChar *) atom->valuep;
4168*7c568831SAndroid Build Coastguard Worker 		    (*nbval)++;
4169*7c568831SAndroid Build Coastguard Worker 		}
4170*7c568831SAndroid Build Coastguard Worker 	    } else {
4171*7c568831SAndroid Build Coastguard Worker                 if ((exec->comp != NULL) && (exec->comp->states[trans->to] != NULL) &&
4172*7c568831SAndroid Build Coastguard Worker 		    (exec->comp->states[trans->to]->type !=
4173*7c568831SAndroid Build Coastguard Worker 		     XML_REGEXP_SINK_STATE)) {
4174*7c568831SAndroid Build Coastguard Worker 		    if (atom->neg)
4175*7c568831SAndroid Build Coastguard Worker 			values[nb++] = (xmlChar *) atom->valuep2;
4176*7c568831SAndroid Build Coastguard Worker 		    else
4177*7c568831SAndroid Build Coastguard Worker 			values[nb++] = (xmlChar *) atom->valuep;
4178*7c568831SAndroid Build Coastguard Worker 		    (*nbval)++;
4179*7c568831SAndroid Build Coastguard Worker 		}
4180*7c568831SAndroid Build Coastguard Worker 	    }
4181*7c568831SAndroid Build Coastguard Worker 	}
4182*7c568831SAndroid Build Coastguard Worker 	for (transno = 0;
4183*7c568831SAndroid Build Coastguard Worker 	     (transno < state->nbTrans) && (nb < maxval);
4184*7c568831SAndroid Build Coastguard Worker 	     transno++) {
4185*7c568831SAndroid Build Coastguard Worker 	    trans = &state->trans[transno];
4186*7c568831SAndroid Build Coastguard Worker 	    if (trans->to < 0)
4187*7c568831SAndroid Build Coastguard Worker 		continue;
4188*7c568831SAndroid Build Coastguard Worker 	    atom = trans->atom;
4189*7c568831SAndroid Build Coastguard Worker 	    if ((atom == NULL) || (atom->valuep == NULL))
4190*7c568831SAndroid Build Coastguard Worker 		continue;
4191*7c568831SAndroid Build Coastguard Worker 	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
4192*7c568831SAndroid Build Coastguard Worker 	        continue;
4193*7c568831SAndroid Build Coastguard Worker 	    } else if (trans->count == REGEXP_ALL_COUNTER) {
4194*7c568831SAndroid Build Coastguard Worker 	        continue;
4195*7c568831SAndroid Build Coastguard Worker 	    } else if (trans->counter >= 0) {
4196*7c568831SAndroid Build Coastguard Worker 	        continue;
4197*7c568831SAndroid Build Coastguard Worker 	    } else {
4198*7c568831SAndroid Build Coastguard Worker                 if ((exec->comp->states[trans->to] != NULL) &&
4199*7c568831SAndroid Build Coastguard Worker 		    (exec->comp->states[trans->to]->type ==
4200*7c568831SAndroid Build Coastguard Worker 		     XML_REGEXP_SINK_STATE)) {
4201*7c568831SAndroid Build Coastguard Worker 		    if (atom->neg)
4202*7c568831SAndroid Build Coastguard Worker 			values[nb++] = (xmlChar *) atom->valuep2;
4203*7c568831SAndroid Build Coastguard Worker 		    else
4204*7c568831SAndroid Build Coastguard Worker 			values[nb++] = (xmlChar *) atom->valuep;
4205*7c568831SAndroid Build Coastguard Worker 		    (*nbneg)++;
4206*7c568831SAndroid Build Coastguard Worker 		}
4207*7c568831SAndroid Build Coastguard Worker 	    }
4208*7c568831SAndroid Build Coastguard Worker 	}
4209*7c568831SAndroid Build Coastguard Worker     }
4210*7c568831SAndroid Build Coastguard Worker     return(0);
4211*7c568831SAndroid Build Coastguard Worker }
4212*7c568831SAndroid Build Coastguard Worker 
4213*7c568831SAndroid Build Coastguard Worker /**
4214*7c568831SAndroid Build Coastguard Worker  * xmlRegExecNextValues:
4215*7c568831SAndroid Build Coastguard Worker  * @exec: a regexp execution context
4216*7c568831SAndroid Build Coastguard Worker  * @nbval: pointer to the number of accepted values IN/OUT
4217*7c568831SAndroid Build Coastguard Worker  * @nbneg: return number of negative transitions
4218*7c568831SAndroid Build Coastguard Worker  * @values: pointer to the array of acceptable values
4219*7c568831SAndroid Build Coastguard Worker  * @terminal: return value if this was a terminal state
4220*7c568831SAndroid Build Coastguard Worker  *
4221*7c568831SAndroid Build Coastguard Worker  * Extract information from the regexp execution,
4222*7c568831SAndroid Build Coastguard Worker  * the parameter @values must point to an array of @nbval string pointers
4223*7c568831SAndroid Build Coastguard Worker  * on return nbval will contain the number of possible strings in that
4224*7c568831SAndroid Build Coastguard Worker  * state and the @values array will be updated with them. The string values
4225*7c568831SAndroid Build Coastguard Worker  * returned will be freed with the @exec context and don't need to be
4226*7c568831SAndroid Build Coastguard Worker  * deallocated.
4227*7c568831SAndroid Build Coastguard Worker  *
4228*7c568831SAndroid Build Coastguard Worker  * Returns: 0 in case of success or -1 in case of error.
4229*7c568831SAndroid Build Coastguard Worker  */
4230*7c568831SAndroid Build Coastguard Worker int
xmlRegExecNextValues(xmlRegExecCtxtPtr exec,int * nbval,int * nbneg,xmlChar ** values,int * terminal)4231*7c568831SAndroid Build Coastguard Worker xmlRegExecNextValues(xmlRegExecCtxtPtr exec, int *nbval, int *nbneg,
4232*7c568831SAndroid Build Coastguard Worker                      xmlChar **values, int *terminal) {
4233*7c568831SAndroid Build Coastguard Worker     return(xmlRegExecGetValues(exec, 0, nbval, nbneg, values, terminal));
4234*7c568831SAndroid Build Coastguard Worker }
4235*7c568831SAndroid Build Coastguard Worker 
4236*7c568831SAndroid Build Coastguard Worker /**
4237*7c568831SAndroid Build Coastguard Worker  * xmlRegExecErrInfo:
4238*7c568831SAndroid Build Coastguard Worker  * @exec: a regexp execution context generating an error
4239*7c568831SAndroid Build Coastguard Worker  * @string: return value for the error string
4240*7c568831SAndroid Build Coastguard Worker  * @nbval: pointer to the number of accepted values IN/OUT
4241*7c568831SAndroid Build Coastguard Worker  * @nbneg: return number of negative transitions
4242*7c568831SAndroid Build Coastguard Worker  * @values: pointer to the array of acceptable values
4243*7c568831SAndroid Build Coastguard Worker  * @terminal: return value if this was a terminal state
4244*7c568831SAndroid Build Coastguard Worker  *
4245*7c568831SAndroid Build Coastguard Worker  * Extract error information from the regexp execution, the parameter
4246*7c568831SAndroid Build Coastguard Worker  * @string will be updated with the value pushed and not accepted,
4247*7c568831SAndroid Build Coastguard Worker  * the parameter @values must point to an array of @nbval string pointers
4248*7c568831SAndroid Build Coastguard Worker  * on return nbval will contain the number of possible strings in that
4249*7c568831SAndroid Build Coastguard Worker  * state and the @values array will be updated with them. The string values
4250*7c568831SAndroid Build Coastguard Worker  * returned will be freed with the @exec context and don't need to be
4251*7c568831SAndroid Build Coastguard Worker  * deallocated.
4252*7c568831SAndroid Build Coastguard Worker  *
4253*7c568831SAndroid Build Coastguard Worker  * Returns: 0 in case of success or -1 in case of error.
4254*7c568831SAndroid Build Coastguard Worker  */
4255*7c568831SAndroid Build Coastguard Worker int
xmlRegExecErrInfo(xmlRegExecCtxtPtr exec,const xmlChar ** string,int * nbval,int * nbneg,xmlChar ** values,int * terminal)4256*7c568831SAndroid Build Coastguard Worker xmlRegExecErrInfo(xmlRegExecCtxtPtr exec, const xmlChar **string,
4257*7c568831SAndroid Build Coastguard Worker                   int *nbval, int *nbneg, xmlChar **values, int *terminal) {
4258*7c568831SAndroid Build Coastguard Worker     if (exec == NULL)
4259*7c568831SAndroid Build Coastguard Worker         return(-1);
4260*7c568831SAndroid Build Coastguard Worker     if (string != NULL) {
4261*7c568831SAndroid Build Coastguard Worker         if (exec->status != XML_REGEXP_OK)
4262*7c568831SAndroid Build Coastguard Worker 	    *string = exec->errString;
4263*7c568831SAndroid Build Coastguard Worker 	else
4264*7c568831SAndroid Build Coastguard Worker 	    *string = NULL;
4265*7c568831SAndroid Build Coastguard Worker     }
4266*7c568831SAndroid Build Coastguard Worker     return(xmlRegExecGetValues(exec, 1, nbval, nbneg, values, terminal));
4267*7c568831SAndroid Build Coastguard Worker }
4268*7c568831SAndroid Build Coastguard Worker 
4269*7c568831SAndroid Build Coastguard Worker /************************************************************************
4270*7c568831SAndroid Build Coastguard Worker  *									*
4271*7c568831SAndroid Build Coastguard Worker  *	Parser for the Schemas Datatype Regular Expressions		*
4272*7c568831SAndroid Build Coastguard Worker  *	http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#regexs	*
4273*7c568831SAndroid Build Coastguard Worker  *									*
4274*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
4275*7c568831SAndroid Build Coastguard Worker 
4276*7c568831SAndroid Build Coastguard Worker /**
4277*7c568831SAndroid Build Coastguard Worker  * xmlFAIsChar:
4278*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4279*7c568831SAndroid Build Coastguard Worker  *
4280*7c568831SAndroid Build Coastguard Worker  * [10]   Char   ::=   [^.\?*+()|#x5B#x5D]
4281*7c568831SAndroid Build Coastguard Worker  */
4282*7c568831SAndroid Build Coastguard Worker static int
xmlFAIsChar(xmlRegParserCtxtPtr ctxt)4283*7c568831SAndroid Build Coastguard Worker xmlFAIsChar(xmlRegParserCtxtPtr ctxt) {
4284*7c568831SAndroid Build Coastguard Worker     int cur;
4285*7c568831SAndroid Build Coastguard Worker     int len;
4286*7c568831SAndroid Build Coastguard Worker 
4287*7c568831SAndroid Build Coastguard Worker     len = 4;
4288*7c568831SAndroid Build Coastguard Worker     cur = xmlGetUTF8Char(ctxt->cur, &len);
4289*7c568831SAndroid Build Coastguard Worker     if (cur < 0) {
4290*7c568831SAndroid Build Coastguard Worker         ERROR("Invalid UTF-8");
4291*7c568831SAndroid Build Coastguard Worker         return(0);
4292*7c568831SAndroid Build Coastguard Worker     }
4293*7c568831SAndroid Build Coastguard Worker     if ((cur == '.') || (cur == '\\') || (cur == '?') ||
4294*7c568831SAndroid Build Coastguard Worker 	(cur == '*') || (cur == '+') || (cur == '(') ||
4295*7c568831SAndroid Build Coastguard Worker 	(cur == ')') || (cur == '|') || (cur == 0x5B) ||
4296*7c568831SAndroid Build Coastguard Worker 	(cur == 0x5D) || (cur == 0))
4297*7c568831SAndroid Build Coastguard Worker 	return(-1);
4298*7c568831SAndroid Build Coastguard Worker     return(cur);
4299*7c568831SAndroid Build Coastguard Worker }
4300*7c568831SAndroid Build Coastguard Worker 
4301*7c568831SAndroid Build Coastguard Worker /**
4302*7c568831SAndroid Build Coastguard Worker  * xmlFAParseCharProp:
4303*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4304*7c568831SAndroid Build Coastguard Worker  *
4305*7c568831SAndroid Build Coastguard Worker  * [27]   charProp   ::=   IsCategory | IsBlock
4306*7c568831SAndroid Build Coastguard Worker  * [28]   IsCategory ::= Letters | Marks | Numbers | Punctuation |
4307*7c568831SAndroid Build Coastguard Worker  *                       Separators | Symbols | Others
4308*7c568831SAndroid Build Coastguard Worker  * [29]   Letters   ::=   'L' [ultmo]?
4309*7c568831SAndroid Build Coastguard Worker  * [30]   Marks   ::=   'M' [nce]?
4310*7c568831SAndroid Build Coastguard Worker  * [31]   Numbers   ::=   'N' [dlo]?
4311*7c568831SAndroid Build Coastguard Worker  * [32]   Punctuation   ::=   'P' [cdseifo]?
4312*7c568831SAndroid Build Coastguard Worker  * [33]   Separators   ::=   'Z' [slp]?
4313*7c568831SAndroid Build Coastguard Worker  * [34]   Symbols   ::=   'S' [mcko]?
4314*7c568831SAndroid Build Coastguard Worker  * [35]   Others   ::=   'C' [cfon]?
4315*7c568831SAndroid Build Coastguard Worker  * [36]   IsBlock   ::=   'Is' [a-zA-Z0-9#x2D]+
4316*7c568831SAndroid Build Coastguard Worker  */
4317*7c568831SAndroid Build Coastguard Worker static void
xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt)4318*7c568831SAndroid Build Coastguard Worker xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
4319*7c568831SAndroid Build Coastguard Worker     int cur;
4320*7c568831SAndroid Build Coastguard Worker     xmlRegAtomType type = (xmlRegAtomType) 0;
4321*7c568831SAndroid Build Coastguard Worker     xmlChar *blockName = NULL;
4322*7c568831SAndroid Build Coastguard Worker 
4323*7c568831SAndroid Build Coastguard Worker     cur = CUR;
4324*7c568831SAndroid Build Coastguard Worker     if (cur == 'L') {
4325*7c568831SAndroid Build Coastguard Worker 	NEXT;
4326*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4327*7c568831SAndroid Build Coastguard Worker 	if (cur == 'u') {
4328*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4329*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_LETTER_UPPERCASE;
4330*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'l') {
4331*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4332*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_LETTER_LOWERCASE;
4333*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 't') {
4334*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4335*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_LETTER_TITLECASE;
4336*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'm') {
4337*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4338*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_LETTER_MODIFIER;
4339*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'o') {
4340*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4341*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_LETTER_OTHERS;
4342*7c568831SAndroid Build Coastguard Worker 	} else {
4343*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_LETTER;
4344*7c568831SAndroid Build Coastguard Worker 	}
4345*7c568831SAndroid Build Coastguard Worker     } else if (cur == 'M') {
4346*7c568831SAndroid Build Coastguard Worker 	NEXT;
4347*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4348*7c568831SAndroid Build Coastguard Worker 	if (cur == 'n') {
4349*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4350*7c568831SAndroid Build Coastguard Worker 	    /* nonspacing */
4351*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_MARK_NONSPACING;
4352*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'c') {
4353*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4354*7c568831SAndroid Build Coastguard Worker 	    /* spacing combining */
4355*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_MARK_SPACECOMBINING;
4356*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'e') {
4357*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4358*7c568831SAndroid Build Coastguard Worker 	    /* enclosing */
4359*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_MARK_ENCLOSING;
4360*7c568831SAndroid Build Coastguard Worker 	} else {
4361*7c568831SAndroid Build Coastguard Worker 	    /* all marks */
4362*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_MARK;
4363*7c568831SAndroid Build Coastguard Worker 	}
4364*7c568831SAndroid Build Coastguard Worker     } else if (cur == 'N') {
4365*7c568831SAndroid Build Coastguard Worker 	NEXT;
4366*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4367*7c568831SAndroid Build Coastguard Worker 	if (cur == 'd') {
4368*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4369*7c568831SAndroid Build Coastguard Worker 	    /* digital */
4370*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_NUMBER_DECIMAL;
4371*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'l') {
4372*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4373*7c568831SAndroid Build Coastguard Worker 	    /* letter */
4374*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_NUMBER_LETTER;
4375*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'o') {
4376*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4377*7c568831SAndroid Build Coastguard Worker 	    /* other */
4378*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_NUMBER_OTHERS;
4379*7c568831SAndroid Build Coastguard Worker 	} else {
4380*7c568831SAndroid Build Coastguard Worker 	    /* all numbers */
4381*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_NUMBER;
4382*7c568831SAndroid Build Coastguard Worker 	}
4383*7c568831SAndroid Build Coastguard Worker     } else if (cur == 'P') {
4384*7c568831SAndroid Build Coastguard Worker 	NEXT;
4385*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4386*7c568831SAndroid Build Coastguard Worker 	if (cur == 'c') {
4387*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4388*7c568831SAndroid Build Coastguard Worker 	    /* connector */
4389*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_PUNCT_CONNECTOR;
4390*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'd') {
4391*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4392*7c568831SAndroid Build Coastguard Worker 	    /* dash */
4393*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_PUNCT_DASH;
4394*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 's') {
4395*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4396*7c568831SAndroid Build Coastguard Worker 	    /* open */
4397*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_PUNCT_OPEN;
4398*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'e') {
4399*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4400*7c568831SAndroid Build Coastguard Worker 	    /* close */
4401*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_PUNCT_CLOSE;
4402*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'i') {
4403*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4404*7c568831SAndroid Build Coastguard Worker 	    /* initial quote */
4405*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_PUNCT_INITQUOTE;
4406*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'f') {
4407*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4408*7c568831SAndroid Build Coastguard Worker 	    /* final quote */
4409*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_PUNCT_FINQUOTE;
4410*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'o') {
4411*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4412*7c568831SAndroid Build Coastguard Worker 	    /* other */
4413*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_PUNCT_OTHERS;
4414*7c568831SAndroid Build Coastguard Worker 	} else {
4415*7c568831SAndroid Build Coastguard Worker 	    /* all punctuation */
4416*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_PUNCT;
4417*7c568831SAndroid Build Coastguard Worker 	}
4418*7c568831SAndroid Build Coastguard Worker     } else if (cur == 'Z') {
4419*7c568831SAndroid Build Coastguard Worker 	NEXT;
4420*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4421*7c568831SAndroid Build Coastguard Worker 	if (cur == 's') {
4422*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4423*7c568831SAndroid Build Coastguard Worker 	    /* space */
4424*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SEPAR_SPACE;
4425*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'l') {
4426*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4427*7c568831SAndroid Build Coastguard Worker 	    /* line */
4428*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SEPAR_LINE;
4429*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'p') {
4430*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4431*7c568831SAndroid Build Coastguard Worker 	    /* paragraph */
4432*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SEPAR_PARA;
4433*7c568831SAndroid Build Coastguard Worker 	} else {
4434*7c568831SAndroid Build Coastguard Worker 	    /* all separators */
4435*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SEPAR;
4436*7c568831SAndroid Build Coastguard Worker 	}
4437*7c568831SAndroid Build Coastguard Worker     } else if (cur == 'S') {
4438*7c568831SAndroid Build Coastguard Worker 	NEXT;
4439*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4440*7c568831SAndroid Build Coastguard Worker 	if (cur == 'm') {
4441*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4442*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SYMBOL_MATH;
4443*7c568831SAndroid Build Coastguard Worker 	    /* math */
4444*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'c') {
4445*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4446*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SYMBOL_CURRENCY;
4447*7c568831SAndroid Build Coastguard Worker 	    /* currency */
4448*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'k') {
4449*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4450*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SYMBOL_MODIFIER;
4451*7c568831SAndroid Build Coastguard Worker 	    /* modifiers */
4452*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'o') {
4453*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4454*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SYMBOL_OTHERS;
4455*7c568831SAndroid Build Coastguard Worker 	    /* other */
4456*7c568831SAndroid Build Coastguard Worker 	} else {
4457*7c568831SAndroid Build Coastguard Worker 	    /* all symbols */
4458*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_SYMBOL;
4459*7c568831SAndroid Build Coastguard Worker 	}
4460*7c568831SAndroid Build Coastguard Worker     } else if (cur == 'C') {
4461*7c568831SAndroid Build Coastguard Worker 	NEXT;
4462*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4463*7c568831SAndroid Build Coastguard Worker 	if (cur == 'c') {
4464*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4465*7c568831SAndroid Build Coastguard Worker 	    /* control */
4466*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_OTHER_CONTROL;
4467*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'f') {
4468*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4469*7c568831SAndroid Build Coastguard Worker 	    /* format */
4470*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_OTHER_FORMAT;
4471*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'o') {
4472*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4473*7c568831SAndroid Build Coastguard Worker 	    /* private use */
4474*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_OTHER_PRIVATE;
4475*7c568831SAndroid Build Coastguard Worker 	} else if (cur == 'n') {
4476*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4477*7c568831SAndroid Build Coastguard Worker 	    /* not assigned */
4478*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_OTHER_NA;
4479*7c568831SAndroid Build Coastguard Worker 	} else {
4480*7c568831SAndroid Build Coastguard Worker 	    /* all others */
4481*7c568831SAndroid Build Coastguard Worker 	    type = XML_REGEXP_OTHER;
4482*7c568831SAndroid Build Coastguard Worker 	}
4483*7c568831SAndroid Build Coastguard Worker     } else if (cur == 'I') {
4484*7c568831SAndroid Build Coastguard Worker 	const xmlChar *start;
4485*7c568831SAndroid Build Coastguard Worker 	NEXT;
4486*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4487*7c568831SAndroid Build Coastguard Worker 	if (cur != 's') {
4488*7c568831SAndroid Build Coastguard Worker 	    ERROR("IsXXXX expected");
4489*7c568831SAndroid Build Coastguard Worker 	    return;
4490*7c568831SAndroid Build Coastguard Worker 	}
4491*7c568831SAndroid Build Coastguard Worker 	NEXT;
4492*7c568831SAndroid Build Coastguard Worker 	start = ctxt->cur;
4493*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4494*7c568831SAndroid Build Coastguard Worker 	if (((cur >= 'a') && (cur <= 'z')) ||
4495*7c568831SAndroid Build Coastguard Worker 	    ((cur >= 'A') && (cur <= 'Z')) ||
4496*7c568831SAndroid Build Coastguard Worker 	    ((cur >= '0') && (cur <= '9')) ||
4497*7c568831SAndroid Build Coastguard Worker 	    (cur == 0x2D)) {
4498*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4499*7c568831SAndroid Build Coastguard Worker 	    cur = CUR;
4500*7c568831SAndroid Build Coastguard Worker 	    while (((cur >= 'a') && (cur <= 'z')) ||
4501*7c568831SAndroid Build Coastguard Worker 		((cur >= 'A') && (cur <= 'Z')) ||
4502*7c568831SAndroid Build Coastguard Worker 		((cur >= '0') && (cur <= '9')) ||
4503*7c568831SAndroid Build Coastguard Worker 		(cur == 0x2D)) {
4504*7c568831SAndroid Build Coastguard Worker 		NEXT;
4505*7c568831SAndroid Build Coastguard Worker 		cur = CUR;
4506*7c568831SAndroid Build Coastguard Worker 	    }
4507*7c568831SAndroid Build Coastguard Worker 	}
4508*7c568831SAndroid Build Coastguard Worker 	type = XML_REGEXP_BLOCK_NAME;
4509*7c568831SAndroid Build Coastguard Worker 	blockName = xmlStrndup(start, ctxt->cur - start);
4510*7c568831SAndroid Build Coastguard Worker         if (blockName == NULL)
4511*7c568831SAndroid Build Coastguard Worker 	    xmlRegexpErrMemory(ctxt);
4512*7c568831SAndroid Build Coastguard Worker     } else {
4513*7c568831SAndroid Build Coastguard Worker 	ERROR("Unknown char property");
4514*7c568831SAndroid Build Coastguard Worker 	return;
4515*7c568831SAndroid Build Coastguard Worker     }
4516*7c568831SAndroid Build Coastguard Worker     if (ctxt->atom == NULL) {
4517*7c568831SAndroid Build Coastguard Worker 	ctxt->atom = xmlRegNewAtom(ctxt, type);
4518*7c568831SAndroid Build Coastguard Worker         if (ctxt->atom == NULL) {
4519*7c568831SAndroid Build Coastguard Worker             xmlFree(blockName);
4520*7c568831SAndroid Build Coastguard Worker             return;
4521*7c568831SAndroid Build Coastguard Worker         }
4522*7c568831SAndroid Build Coastguard Worker 	ctxt->atom->valuep = blockName;
4523*7c568831SAndroid Build Coastguard Worker     } else if (ctxt->atom->type == XML_REGEXP_RANGES) {
4524*7c568831SAndroid Build Coastguard Worker         if (xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
4525*7c568831SAndroid Build Coastguard Worker                                type, 0, 0, blockName) == NULL) {
4526*7c568831SAndroid Build Coastguard Worker             xmlFree(blockName);
4527*7c568831SAndroid Build Coastguard Worker         }
4528*7c568831SAndroid Build Coastguard Worker     }
4529*7c568831SAndroid Build Coastguard Worker }
4530*7c568831SAndroid Build Coastguard Worker 
parse_escaped_codeunit(xmlRegParserCtxtPtr ctxt)4531*7c568831SAndroid Build Coastguard Worker static int parse_escaped_codeunit(xmlRegParserCtxtPtr ctxt)
4532*7c568831SAndroid Build Coastguard Worker {
4533*7c568831SAndroid Build Coastguard Worker     int val = 0, i, cur;
4534*7c568831SAndroid Build Coastguard Worker     for (i = 0; i < 4; i++) {
4535*7c568831SAndroid Build Coastguard Worker 	NEXT;
4536*7c568831SAndroid Build Coastguard Worker 	val *= 16;
4537*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4538*7c568831SAndroid Build Coastguard Worker 	if (cur >= '0' && cur <= '9') {
4539*7c568831SAndroid Build Coastguard Worker 	    val += cur - '0';
4540*7c568831SAndroid Build Coastguard Worker 	} else if (cur >= 'A' && cur <= 'F') {
4541*7c568831SAndroid Build Coastguard Worker 	    val += cur - 'A' + 10;
4542*7c568831SAndroid Build Coastguard Worker 	} else if (cur >= 'a' && cur <= 'f') {
4543*7c568831SAndroid Build Coastguard Worker 	    val += cur - 'a' + 10;
4544*7c568831SAndroid Build Coastguard Worker 	} else {
4545*7c568831SAndroid Build Coastguard Worker 	    ERROR("Expecting hex digit");
4546*7c568831SAndroid Build Coastguard Worker 	    return -1;
4547*7c568831SAndroid Build Coastguard Worker 	}
4548*7c568831SAndroid Build Coastguard Worker     }
4549*7c568831SAndroid Build Coastguard Worker     return val;
4550*7c568831SAndroid Build Coastguard Worker }
4551*7c568831SAndroid Build Coastguard Worker 
parse_escaped_codepoint(xmlRegParserCtxtPtr ctxt)4552*7c568831SAndroid Build Coastguard Worker static int parse_escaped_codepoint(xmlRegParserCtxtPtr ctxt)
4553*7c568831SAndroid Build Coastguard Worker {
4554*7c568831SAndroid Build Coastguard Worker     int val = parse_escaped_codeunit(ctxt);
4555*7c568831SAndroid Build Coastguard Worker     if (0xD800 <= val && val <= 0xDBFF) {
4556*7c568831SAndroid Build Coastguard Worker 	NEXT;
4557*7c568831SAndroid Build Coastguard Worker 	if (CUR == '\\') {
4558*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4559*7c568831SAndroid Build Coastguard Worker 	    if (CUR == 'u') {
4560*7c568831SAndroid Build Coastguard Worker 		int low = parse_escaped_codeunit(ctxt);
4561*7c568831SAndroid Build Coastguard Worker 		if (0xDC00 <= low && low <= 0xDFFF) {
4562*7c568831SAndroid Build Coastguard Worker 		    return (val - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000;
4563*7c568831SAndroid Build Coastguard Worker 		}
4564*7c568831SAndroid Build Coastguard Worker 	    }
4565*7c568831SAndroid Build Coastguard Worker 	}
4566*7c568831SAndroid Build Coastguard Worker 	ERROR("Invalid low surrogate pair code unit");
4567*7c568831SAndroid Build Coastguard Worker 	val = -1;
4568*7c568831SAndroid Build Coastguard Worker     }
4569*7c568831SAndroid Build Coastguard Worker     return val;
4570*7c568831SAndroid Build Coastguard Worker }
4571*7c568831SAndroid Build Coastguard Worker 
4572*7c568831SAndroid Build Coastguard Worker /**
4573*7c568831SAndroid Build Coastguard Worker  * xmlFAParseCharClassEsc:
4574*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4575*7c568831SAndroid Build Coastguard Worker  *
4576*7c568831SAndroid Build Coastguard Worker  * [23] charClassEsc ::= ( SingleCharEsc | MultiCharEsc | catEsc | complEsc )
4577*7c568831SAndroid Build Coastguard Worker  * [24] SingleCharEsc ::= '\' [nrt\|.?*+(){}#x2D#x5B#x5D#x5E]
4578*7c568831SAndroid Build Coastguard Worker  * [25] catEsc   ::=   '\p{' charProp '}'
4579*7c568831SAndroid Build Coastguard Worker  * [26] complEsc ::=   '\P{' charProp '}'
4580*7c568831SAndroid Build Coastguard Worker  * [37] MultiCharEsc ::= '.' | ('\' [sSiIcCdDwW])
4581*7c568831SAndroid Build Coastguard Worker  */
4582*7c568831SAndroid Build Coastguard Worker static void
xmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt)4583*7c568831SAndroid Build Coastguard Worker xmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) {
4584*7c568831SAndroid Build Coastguard Worker     int cur;
4585*7c568831SAndroid Build Coastguard Worker 
4586*7c568831SAndroid Build Coastguard Worker     if (CUR == '.') {
4587*7c568831SAndroid Build Coastguard Worker 	if (ctxt->atom == NULL) {
4588*7c568831SAndroid Build Coastguard Worker 	    ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_ANYCHAR);
4589*7c568831SAndroid Build Coastguard Worker 	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
4590*7c568831SAndroid Build Coastguard Worker 	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
4591*7c568831SAndroid Build Coastguard Worker 			       XML_REGEXP_ANYCHAR, 0, 0, NULL);
4592*7c568831SAndroid Build Coastguard Worker 	}
4593*7c568831SAndroid Build Coastguard Worker 	NEXT;
4594*7c568831SAndroid Build Coastguard Worker 	return;
4595*7c568831SAndroid Build Coastguard Worker     }
4596*7c568831SAndroid Build Coastguard Worker     if (CUR != '\\') {
4597*7c568831SAndroid Build Coastguard Worker 	ERROR("Escaped sequence: expecting \\");
4598*7c568831SAndroid Build Coastguard Worker 	return;
4599*7c568831SAndroid Build Coastguard Worker     }
4600*7c568831SAndroid Build Coastguard Worker     NEXT;
4601*7c568831SAndroid Build Coastguard Worker     cur = CUR;
4602*7c568831SAndroid Build Coastguard Worker     if (cur == 'p') {
4603*7c568831SAndroid Build Coastguard Worker 	NEXT;
4604*7c568831SAndroid Build Coastguard Worker 	if (CUR != '{') {
4605*7c568831SAndroid Build Coastguard Worker 	    ERROR("Expecting '{'");
4606*7c568831SAndroid Build Coastguard Worker 	    return;
4607*7c568831SAndroid Build Coastguard Worker 	}
4608*7c568831SAndroid Build Coastguard Worker 	NEXT;
4609*7c568831SAndroid Build Coastguard Worker 	xmlFAParseCharProp(ctxt);
4610*7c568831SAndroid Build Coastguard Worker 	if (CUR != '}') {
4611*7c568831SAndroid Build Coastguard Worker 	    ERROR("Expecting '}'");
4612*7c568831SAndroid Build Coastguard Worker 	    return;
4613*7c568831SAndroid Build Coastguard Worker 	}
4614*7c568831SAndroid Build Coastguard Worker 	NEXT;
4615*7c568831SAndroid Build Coastguard Worker     } else if (cur == 'P') {
4616*7c568831SAndroid Build Coastguard Worker 	NEXT;
4617*7c568831SAndroid Build Coastguard Worker 	if (CUR != '{') {
4618*7c568831SAndroid Build Coastguard Worker 	    ERROR("Expecting '{'");
4619*7c568831SAndroid Build Coastguard Worker 	    return;
4620*7c568831SAndroid Build Coastguard Worker 	}
4621*7c568831SAndroid Build Coastguard Worker 	NEXT;
4622*7c568831SAndroid Build Coastguard Worker 	xmlFAParseCharProp(ctxt);
4623*7c568831SAndroid Build Coastguard Worker         if (ctxt->atom != NULL)
4624*7c568831SAndroid Build Coastguard Worker 	    ctxt->atom->neg = 1;
4625*7c568831SAndroid Build Coastguard Worker 	if (CUR != '}') {
4626*7c568831SAndroid Build Coastguard Worker 	    ERROR("Expecting '}'");
4627*7c568831SAndroid Build Coastguard Worker 	    return;
4628*7c568831SAndroid Build Coastguard Worker 	}
4629*7c568831SAndroid Build Coastguard Worker 	NEXT;
4630*7c568831SAndroid Build Coastguard Worker     } else if ((cur == 'n') || (cur == 'r') || (cur == 't') || (cur == '\\') ||
4631*7c568831SAndroid Build Coastguard Worker 	(cur == '|') || (cur == '.') || (cur == '?') || (cur == '*') ||
4632*7c568831SAndroid Build Coastguard Worker 	(cur == '+') || (cur == '(') || (cur == ')') || (cur == '{') ||
4633*7c568831SAndroid Build Coastguard Worker 	(cur == '}') || (cur == 0x2D) || (cur == 0x5B) || (cur == 0x5D) ||
4634*7c568831SAndroid Build Coastguard Worker 	(cur == 0x5E) ||
4635*7c568831SAndroid Build Coastguard Worker 
4636*7c568831SAndroid Build Coastguard Worker 	/* Non-standard escape sequences:
4637*7c568831SAndroid Build Coastguard Worker 	 *                  Java 1.8|.NET Core 3.1|MSXML 6 */
4638*7c568831SAndroid Build Coastguard Worker 	(cur == '!') ||     /*   +  |     +       |    +   */
4639*7c568831SAndroid Build Coastguard Worker 	(cur == '"') ||     /*   +  |     +       |    +   */
4640*7c568831SAndroid Build Coastguard Worker 	(cur == '#') ||     /*   +  |     +       |    +   */
4641*7c568831SAndroid Build Coastguard Worker 	(cur == '$') ||     /*   +  |     +       |    +   */
4642*7c568831SAndroid Build Coastguard Worker 	(cur == '%') ||     /*   +  |     +       |    +   */
4643*7c568831SAndroid Build Coastguard Worker 	(cur == ',') ||     /*   +  |     +       |    +   */
4644*7c568831SAndroid Build Coastguard Worker 	(cur == '/') ||     /*   +  |     +       |    +   */
4645*7c568831SAndroid Build Coastguard Worker 	(cur == ':') ||     /*   +  |     +       |    +   */
4646*7c568831SAndroid Build Coastguard Worker 	(cur == ';') ||     /*   +  |     +       |    +   */
4647*7c568831SAndroid Build Coastguard Worker 	(cur == '=') ||     /*   +  |     +       |    +   */
4648*7c568831SAndroid Build Coastguard Worker 	(cur == '>') ||     /*      |     +       |    +   */
4649*7c568831SAndroid Build Coastguard Worker 	(cur == '@') ||     /*   +  |     +       |    +   */
4650*7c568831SAndroid Build Coastguard Worker 	(cur == '`') ||     /*   +  |     +       |    +   */
4651*7c568831SAndroid Build Coastguard Worker 	(cur == '~') ||     /*   +  |     +       |    +   */
4652*7c568831SAndroid Build Coastguard Worker 	(cur == 'u')) {     /*      |     +       |    +   */
4653*7c568831SAndroid Build Coastguard Worker 	if (ctxt->atom == NULL) {
4654*7c568831SAndroid Build Coastguard Worker 	    ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL);
4655*7c568831SAndroid Build Coastguard Worker 	    if (ctxt->atom != NULL) {
4656*7c568831SAndroid Build Coastguard Worker 	        switch (cur) {
4657*7c568831SAndroid Build Coastguard Worker 		    case 'n':
4658*7c568831SAndroid Build Coastguard Worker 		        ctxt->atom->codepoint = '\n';
4659*7c568831SAndroid Build Coastguard Worker 			break;
4660*7c568831SAndroid Build Coastguard Worker 		    case 'r':
4661*7c568831SAndroid Build Coastguard Worker 		        ctxt->atom->codepoint = '\r';
4662*7c568831SAndroid Build Coastguard Worker 			break;
4663*7c568831SAndroid Build Coastguard Worker 		    case 't':
4664*7c568831SAndroid Build Coastguard Worker 		        ctxt->atom->codepoint = '\t';
4665*7c568831SAndroid Build Coastguard Worker 			break;
4666*7c568831SAndroid Build Coastguard Worker 		    case 'u':
4667*7c568831SAndroid Build Coastguard Worker 			cur = parse_escaped_codepoint(ctxt);
4668*7c568831SAndroid Build Coastguard Worker 			if (cur < 0) {
4669*7c568831SAndroid Build Coastguard Worker 			    return;
4670*7c568831SAndroid Build Coastguard Worker 			}
4671*7c568831SAndroid Build Coastguard Worker 			ctxt->atom->codepoint = cur;
4672*7c568831SAndroid Build Coastguard Worker 			break;
4673*7c568831SAndroid Build Coastguard Worker 		    default:
4674*7c568831SAndroid Build Coastguard Worker 			ctxt->atom->codepoint = cur;
4675*7c568831SAndroid Build Coastguard Worker 		}
4676*7c568831SAndroid Build Coastguard Worker 	    }
4677*7c568831SAndroid Build Coastguard Worker 	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
4678*7c568831SAndroid Build Coastguard Worker             switch (cur) {
4679*7c568831SAndroid Build Coastguard Worker                 case 'n':
4680*7c568831SAndroid Build Coastguard Worker                     cur = '\n';
4681*7c568831SAndroid Build Coastguard Worker                     break;
4682*7c568831SAndroid Build Coastguard Worker                 case 'r':
4683*7c568831SAndroid Build Coastguard Worker                     cur = '\r';
4684*7c568831SAndroid Build Coastguard Worker                     break;
4685*7c568831SAndroid Build Coastguard Worker                 case 't':
4686*7c568831SAndroid Build Coastguard Worker                     cur = '\t';
4687*7c568831SAndroid Build Coastguard Worker                     break;
4688*7c568831SAndroid Build Coastguard Worker             }
4689*7c568831SAndroid Build Coastguard Worker 	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
4690*7c568831SAndroid Build Coastguard Worker 			       XML_REGEXP_CHARVAL, cur, cur, NULL);
4691*7c568831SAndroid Build Coastguard Worker 	}
4692*7c568831SAndroid Build Coastguard Worker 	NEXT;
4693*7c568831SAndroid Build Coastguard Worker     } else if ((cur == 's') || (cur == 'S') || (cur == 'i') || (cur == 'I') ||
4694*7c568831SAndroid Build Coastguard Worker 	(cur == 'c') || (cur == 'C') || (cur == 'd') || (cur == 'D') ||
4695*7c568831SAndroid Build Coastguard Worker 	(cur == 'w') || (cur == 'W')) {
4696*7c568831SAndroid Build Coastguard Worker 	xmlRegAtomType type = XML_REGEXP_ANYSPACE;
4697*7c568831SAndroid Build Coastguard Worker 
4698*7c568831SAndroid Build Coastguard Worker 	switch (cur) {
4699*7c568831SAndroid Build Coastguard Worker 	    case 's':
4700*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_ANYSPACE;
4701*7c568831SAndroid Build Coastguard Worker 		break;
4702*7c568831SAndroid Build Coastguard Worker 	    case 'S':
4703*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_NOTSPACE;
4704*7c568831SAndroid Build Coastguard Worker 		break;
4705*7c568831SAndroid Build Coastguard Worker 	    case 'i':
4706*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_INITNAME;
4707*7c568831SAndroid Build Coastguard Worker 		break;
4708*7c568831SAndroid Build Coastguard Worker 	    case 'I':
4709*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_NOTINITNAME;
4710*7c568831SAndroid Build Coastguard Worker 		break;
4711*7c568831SAndroid Build Coastguard Worker 	    case 'c':
4712*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_NAMECHAR;
4713*7c568831SAndroid Build Coastguard Worker 		break;
4714*7c568831SAndroid Build Coastguard Worker 	    case 'C':
4715*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_NOTNAMECHAR;
4716*7c568831SAndroid Build Coastguard Worker 		break;
4717*7c568831SAndroid Build Coastguard Worker 	    case 'd':
4718*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_DECIMAL;
4719*7c568831SAndroid Build Coastguard Worker 		break;
4720*7c568831SAndroid Build Coastguard Worker 	    case 'D':
4721*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_NOTDECIMAL;
4722*7c568831SAndroid Build Coastguard Worker 		break;
4723*7c568831SAndroid Build Coastguard Worker 	    case 'w':
4724*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_REALCHAR;
4725*7c568831SAndroid Build Coastguard Worker 		break;
4726*7c568831SAndroid Build Coastguard Worker 	    case 'W':
4727*7c568831SAndroid Build Coastguard Worker 		type = XML_REGEXP_NOTREALCHAR;
4728*7c568831SAndroid Build Coastguard Worker 		break;
4729*7c568831SAndroid Build Coastguard Worker 	}
4730*7c568831SAndroid Build Coastguard Worker 	NEXT;
4731*7c568831SAndroid Build Coastguard Worker 	if (ctxt->atom == NULL) {
4732*7c568831SAndroid Build Coastguard Worker 	    ctxt->atom = xmlRegNewAtom(ctxt, type);
4733*7c568831SAndroid Build Coastguard Worker 	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
4734*7c568831SAndroid Build Coastguard Worker 	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
4735*7c568831SAndroid Build Coastguard Worker 			       type, 0, 0, NULL);
4736*7c568831SAndroid Build Coastguard Worker 	}
4737*7c568831SAndroid Build Coastguard Worker     } else {
4738*7c568831SAndroid Build Coastguard Worker 	ERROR("Wrong escape sequence, misuse of character '\\'");
4739*7c568831SAndroid Build Coastguard Worker     }
4740*7c568831SAndroid Build Coastguard Worker }
4741*7c568831SAndroid Build Coastguard Worker 
4742*7c568831SAndroid Build Coastguard Worker /**
4743*7c568831SAndroid Build Coastguard Worker  * xmlFAParseCharRange:
4744*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4745*7c568831SAndroid Build Coastguard Worker  *
4746*7c568831SAndroid Build Coastguard Worker  * [17]   charRange   ::=     seRange | XmlCharRef | XmlCharIncDash
4747*7c568831SAndroid Build Coastguard Worker  * [18]   seRange   ::=   charOrEsc '-' charOrEsc
4748*7c568831SAndroid Build Coastguard Worker  * [20]   charOrEsc   ::=   XmlChar | SingleCharEsc
4749*7c568831SAndroid Build Coastguard Worker  * [21]   XmlChar   ::=   [^\#x2D#x5B#x5D]
4750*7c568831SAndroid Build Coastguard Worker  * [22]   XmlCharIncDash   ::=   [^\#x5B#x5D]
4751*7c568831SAndroid Build Coastguard Worker  */
4752*7c568831SAndroid Build Coastguard Worker static void
xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt)4753*7c568831SAndroid Build Coastguard Worker xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) {
4754*7c568831SAndroid Build Coastguard Worker     int cur, len;
4755*7c568831SAndroid Build Coastguard Worker     int start = -1;
4756*7c568831SAndroid Build Coastguard Worker     int end = -1;
4757*7c568831SAndroid Build Coastguard Worker 
4758*7c568831SAndroid Build Coastguard Worker     if (CUR == '\0') {
4759*7c568831SAndroid Build Coastguard Worker         ERROR("Expecting ']'");
4760*7c568831SAndroid Build Coastguard Worker 	return;
4761*7c568831SAndroid Build Coastguard Worker     }
4762*7c568831SAndroid Build Coastguard Worker 
4763*7c568831SAndroid Build Coastguard Worker     cur = CUR;
4764*7c568831SAndroid Build Coastguard Worker     if (cur == '\\') {
4765*7c568831SAndroid Build Coastguard Worker 	NEXT;
4766*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4767*7c568831SAndroid Build Coastguard Worker 	switch (cur) {
4768*7c568831SAndroid Build Coastguard Worker 	    case 'n': start = 0xA; break;
4769*7c568831SAndroid Build Coastguard Worker 	    case 'r': start = 0xD; break;
4770*7c568831SAndroid Build Coastguard Worker 	    case 't': start = 0x9; break;
4771*7c568831SAndroid Build Coastguard Worker 	    case '\\': case '|': case '.': case '-': case '^': case '?':
4772*7c568831SAndroid Build Coastguard Worker 	    case '*': case '+': case '{': case '}': case '(': case ')':
4773*7c568831SAndroid Build Coastguard Worker 	    case '[': case ']':
4774*7c568831SAndroid Build Coastguard Worker 		start = cur; break;
4775*7c568831SAndroid Build Coastguard Worker 	    default:
4776*7c568831SAndroid Build Coastguard Worker 		ERROR("Invalid escape value");
4777*7c568831SAndroid Build Coastguard Worker 		return;
4778*7c568831SAndroid Build Coastguard Worker 	}
4779*7c568831SAndroid Build Coastguard Worker 	end = start;
4780*7c568831SAndroid Build Coastguard Worker         len = 1;
4781*7c568831SAndroid Build Coastguard Worker     } else if ((cur != 0x5B) && (cur != 0x5D)) {
4782*7c568831SAndroid Build Coastguard Worker         len = 4;
4783*7c568831SAndroid Build Coastguard Worker         end = start = xmlGetUTF8Char(ctxt->cur, &len);
4784*7c568831SAndroid Build Coastguard Worker         if (start < 0) {
4785*7c568831SAndroid Build Coastguard Worker             ERROR("Invalid UTF-8");
4786*7c568831SAndroid Build Coastguard Worker             return;
4787*7c568831SAndroid Build Coastguard Worker         }
4788*7c568831SAndroid Build Coastguard Worker     } else {
4789*7c568831SAndroid Build Coastguard Worker 	ERROR("Expecting a char range");
4790*7c568831SAndroid Build Coastguard Worker 	return;
4791*7c568831SAndroid Build Coastguard Worker     }
4792*7c568831SAndroid Build Coastguard Worker     /*
4793*7c568831SAndroid Build Coastguard Worker      * Since we are "inside" a range, we can assume ctxt->cur is past
4794*7c568831SAndroid Build Coastguard Worker      * the start of ctxt->string, and PREV should be safe
4795*7c568831SAndroid Build Coastguard Worker      */
4796*7c568831SAndroid Build Coastguard Worker     if ((start == '-') && (NXT(1) != ']') && (PREV != '[') && (PREV != '^')) {
4797*7c568831SAndroid Build Coastguard Worker 	NEXTL(len);
4798*7c568831SAndroid Build Coastguard Worker 	return;
4799*7c568831SAndroid Build Coastguard Worker     }
4800*7c568831SAndroid Build Coastguard Worker     NEXTL(len);
4801*7c568831SAndroid Build Coastguard Worker     cur = CUR;
4802*7c568831SAndroid Build Coastguard Worker     if ((cur != '-') || (NXT(1) == '[') || (NXT(1) == ']')) {
4803*7c568831SAndroid Build Coastguard Worker         xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
4804*7c568831SAndroid Build Coastguard Worker 		              XML_REGEXP_CHARVAL, start, end, NULL);
4805*7c568831SAndroid Build Coastguard Worker 	return;
4806*7c568831SAndroid Build Coastguard Worker     }
4807*7c568831SAndroid Build Coastguard Worker     NEXT;
4808*7c568831SAndroid Build Coastguard Worker     cur = CUR;
4809*7c568831SAndroid Build Coastguard Worker     if (cur == '\\') {
4810*7c568831SAndroid Build Coastguard Worker 	NEXT;
4811*7c568831SAndroid Build Coastguard Worker 	cur = CUR;
4812*7c568831SAndroid Build Coastguard Worker 	switch (cur) {
4813*7c568831SAndroid Build Coastguard Worker 	    case 'n': end = 0xA; break;
4814*7c568831SAndroid Build Coastguard Worker 	    case 'r': end = 0xD; break;
4815*7c568831SAndroid Build Coastguard Worker 	    case 't': end = 0x9; break;
4816*7c568831SAndroid Build Coastguard Worker 	    case '\\': case '|': case '.': case '-': case '^': case '?':
4817*7c568831SAndroid Build Coastguard Worker 	    case '*': case '+': case '{': case '}': case '(': case ')':
4818*7c568831SAndroid Build Coastguard Worker 	    case '[': case ']':
4819*7c568831SAndroid Build Coastguard Worker 		end = cur; break;
4820*7c568831SAndroid Build Coastguard Worker 	    default:
4821*7c568831SAndroid Build Coastguard Worker 		ERROR("Invalid escape value");
4822*7c568831SAndroid Build Coastguard Worker 		return;
4823*7c568831SAndroid Build Coastguard Worker 	}
4824*7c568831SAndroid Build Coastguard Worker         len = 1;
4825*7c568831SAndroid Build Coastguard Worker     } else if ((cur != '\0') && (cur != 0x5B) && (cur != 0x5D)) {
4826*7c568831SAndroid Build Coastguard Worker         len = 4;
4827*7c568831SAndroid Build Coastguard Worker         end = xmlGetUTF8Char(ctxt->cur, &len);
4828*7c568831SAndroid Build Coastguard Worker         if (end < 0) {
4829*7c568831SAndroid Build Coastguard Worker             ERROR("Invalid UTF-8");
4830*7c568831SAndroid Build Coastguard Worker             return;
4831*7c568831SAndroid Build Coastguard Worker         }
4832*7c568831SAndroid Build Coastguard Worker     } else {
4833*7c568831SAndroid Build Coastguard Worker 	ERROR("Expecting the end of a char range");
4834*7c568831SAndroid Build Coastguard Worker 	return;
4835*7c568831SAndroid Build Coastguard Worker     }
4836*7c568831SAndroid Build Coastguard Worker 
4837*7c568831SAndroid Build Coastguard Worker     /* TODO check that the values are acceptable character ranges for XML */
4838*7c568831SAndroid Build Coastguard Worker     if (end < start) {
4839*7c568831SAndroid Build Coastguard Worker 	ERROR("End of range is before start of range");
4840*7c568831SAndroid Build Coastguard Worker     } else {
4841*7c568831SAndroid Build Coastguard Worker         NEXTL(len);
4842*7c568831SAndroid Build Coastguard Worker         xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
4843*7c568831SAndroid Build Coastguard Worker 		           XML_REGEXP_CHARVAL, start, end, NULL);
4844*7c568831SAndroid Build Coastguard Worker     }
4845*7c568831SAndroid Build Coastguard Worker }
4846*7c568831SAndroid Build Coastguard Worker 
4847*7c568831SAndroid Build Coastguard Worker /**
4848*7c568831SAndroid Build Coastguard Worker  * xmlFAParsePosCharGroup:
4849*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4850*7c568831SAndroid Build Coastguard Worker  *
4851*7c568831SAndroid Build Coastguard Worker  * [14]   posCharGroup ::= ( charRange | charClassEsc  )+
4852*7c568831SAndroid Build Coastguard Worker  */
4853*7c568831SAndroid Build Coastguard Worker static void
xmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt)4854*7c568831SAndroid Build Coastguard Worker xmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) {
4855*7c568831SAndroid Build Coastguard Worker     do {
4856*7c568831SAndroid Build Coastguard Worker 	if (CUR == '\\') {
4857*7c568831SAndroid Build Coastguard Worker 	    xmlFAParseCharClassEsc(ctxt);
4858*7c568831SAndroid Build Coastguard Worker 	} else {
4859*7c568831SAndroid Build Coastguard Worker 	    xmlFAParseCharRange(ctxt);
4860*7c568831SAndroid Build Coastguard Worker 	}
4861*7c568831SAndroid Build Coastguard Worker     } while ((CUR != ']') && (CUR != '-') &&
4862*7c568831SAndroid Build Coastguard Worker              (CUR != 0) && (ctxt->error == 0));
4863*7c568831SAndroid Build Coastguard Worker }
4864*7c568831SAndroid Build Coastguard Worker 
4865*7c568831SAndroid Build Coastguard Worker /**
4866*7c568831SAndroid Build Coastguard Worker  * xmlFAParseCharGroup:
4867*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4868*7c568831SAndroid Build Coastguard Worker  *
4869*7c568831SAndroid Build Coastguard Worker  * [13]   charGroup    ::= posCharGroup | negCharGroup | charClassSub
4870*7c568831SAndroid Build Coastguard Worker  * [15]   negCharGroup ::= '^' posCharGroup
4871*7c568831SAndroid Build Coastguard Worker  * [16]   charClassSub ::= ( posCharGroup | negCharGroup ) '-' charClassExpr
4872*7c568831SAndroid Build Coastguard Worker  * [12]   charClassExpr ::= '[' charGroup ']'
4873*7c568831SAndroid Build Coastguard Worker  */
4874*7c568831SAndroid Build Coastguard Worker static void
xmlFAParseCharGroup(xmlRegParserCtxtPtr ctxt)4875*7c568831SAndroid Build Coastguard Worker xmlFAParseCharGroup(xmlRegParserCtxtPtr ctxt) {
4876*7c568831SAndroid Build Coastguard Worker     int neg = ctxt->neg;
4877*7c568831SAndroid Build Coastguard Worker 
4878*7c568831SAndroid Build Coastguard Worker     if (CUR == '^') {
4879*7c568831SAndroid Build Coastguard Worker 	NEXT;
4880*7c568831SAndroid Build Coastguard Worker 	ctxt->neg = !ctxt->neg;
4881*7c568831SAndroid Build Coastguard Worker 	xmlFAParsePosCharGroup(ctxt);
4882*7c568831SAndroid Build Coastguard Worker 	ctxt->neg = neg;
4883*7c568831SAndroid Build Coastguard Worker     }
4884*7c568831SAndroid Build Coastguard Worker     while ((CUR != ']') && (ctxt->error == 0)) {
4885*7c568831SAndroid Build Coastguard Worker 	if ((CUR == '-') && (NXT(1) == '[')) {
4886*7c568831SAndroid Build Coastguard Worker 	    NEXT;	/* eat the '-' */
4887*7c568831SAndroid Build Coastguard Worker 	    NEXT;	/* eat the '[' */
4888*7c568831SAndroid Build Coastguard Worker 	    ctxt->neg = 2;
4889*7c568831SAndroid Build Coastguard Worker 	    xmlFAParseCharGroup(ctxt);
4890*7c568831SAndroid Build Coastguard Worker 	    ctxt->neg = neg;
4891*7c568831SAndroid Build Coastguard Worker 	    if (CUR == ']') {
4892*7c568831SAndroid Build Coastguard Worker 		NEXT;
4893*7c568831SAndroid Build Coastguard Worker 	    } else {
4894*7c568831SAndroid Build Coastguard Worker 		ERROR("charClassExpr: ']' expected");
4895*7c568831SAndroid Build Coastguard Worker 	    }
4896*7c568831SAndroid Build Coastguard Worker 	    break;
4897*7c568831SAndroid Build Coastguard Worker 	} else {
4898*7c568831SAndroid Build Coastguard Worker 	    xmlFAParsePosCharGroup(ctxt);
4899*7c568831SAndroid Build Coastguard Worker 	}
4900*7c568831SAndroid Build Coastguard Worker     }
4901*7c568831SAndroid Build Coastguard Worker }
4902*7c568831SAndroid Build Coastguard Worker 
4903*7c568831SAndroid Build Coastguard Worker /**
4904*7c568831SAndroid Build Coastguard Worker  * xmlFAParseCharClass:
4905*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4906*7c568831SAndroid Build Coastguard Worker  *
4907*7c568831SAndroid Build Coastguard Worker  * [11]   charClass   ::=     charClassEsc | charClassExpr
4908*7c568831SAndroid Build Coastguard Worker  * [12]   charClassExpr   ::=   '[' charGroup ']'
4909*7c568831SAndroid Build Coastguard Worker  */
4910*7c568831SAndroid Build Coastguard Worker static void
xmlFAParseCharClass(xmlRegParserCtxtPtr ctxt)4911*7c568831SAndroid Build Coastguard Worker xmlFAParseCharClass(xmlRegParserCtxtPtr ctxt) {
4912*7c568831SAndroid Build Coastguard Worker     if (CUR == '[') {
4913*7c568831SAndroid Build Coastguard Worker 	NEXT;
4914*7c568831SAndroid Build Coastguard Worker 	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_RANGES);
4915*7c568831SAndroid Build Coastguard Worker 	if (ctxt->atom == NULL)
4916*7c568831SAndroid Build Coastguard Worker 	    return;
4917*7c568831SAndroid Build Coastguard Worker 	xmlFAParseCharGroup(ctxt);
4918*7c568831SAndroid Build Coastguard Worker 	if (CUR == ']') {
4919*7c568831SAndroid Build Coastguard Worker 	    NEXT;
4920*7c568831SAndroid Build Coastguard Worker 	} else {
4921*7c568831SAndroid Build Coastguard Worker 	    ERROR("xmlFAParseCharClass: ']' expected");
4922*7c568831SAndroid Build Coastguard Worker 	}
4923*7c568831SAndroid Build Coastguard Worker     } else {
4924*7c568831SAndroid Build Coastguard Worker 	xmlFAParseCharClassEsc(ctxt);
4925*7c568831SAndroid Build Coastguard Worker     }
4926*7c568831SAndroid Build Coastguard Worker }
4927*7c568831SAndroid Build Coastguard Worker 
4928*7c568831SAndroid Build Coastguard Worker /**
4929*7c568831SAndroid Build Coastguard Worker  * xmlFAParseQuantExact:
4930*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4931*7c568831SAndroid Build Coastguard Worker  *
4932*7c568831SAndroid Build Coastguard Worker  * [8]   QuantExact   ::=   [0-9]+
4933*7c568831SAndroid Build Coastguard Worker  *
4934*7c568831SAndroid Build Coastguard Worker  * Returns 0 if success or -1 in case of error
4935*7c568831SAndroid Build Coastguard Worker  */
4936*7c568831SAndroid Build Coastguard Worker static int
xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt)4937*7c568831SAndroid Build Coastguard Worker xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
4938*7c568831SAndroid Build Coastguard Worker     int ret = 0;
4939*7c568831SAndroid Build Coastguard Worker     int ok = 0;
4940*7c568831SAndroid Build Coastguard Worker     int overflow = 0;
4941*7c568831SAndroid Build Coastguard Worker 
4942*7c568831SAndroid Build Coastguard Worker     while ((CUR >= '0') && (CUR <= '9')) {
4943*7c568831SAndroid Build Coastguard Worker         if (ret > INT_MAX / 10) {
4944*7c568831SAndroid Build Coastguard Worker             overflow = 1;
4945*7c568831SAndroid Build Coastguard Worker         } else {
4946*7c568831SAndroid Build Coastguard Worker             int digit = CUR - '0';
4947*7c568831SAndroid Build Coastguard Worker 
4948*7c568831SAndroid Build Coastguard Worker             ret *= 10;
4949*7c568831SAndroid Build Coastguard Worker             if (ret > INT_MAX - digit)
4950*7c568831SAndroid Build Coastguard Worker                 overflow = 1;
4951*7c568831SAndroid Build Coastguard Worker             else
4952*7c568831SAndroid Build Coastguard Worker                 ret += digit;
4953*7c568831SAndroid Build Coastguard Worker         }
4954*7c568831SAndroid Build Coastguard Worker 	ok = 1;
4955*7c568831SAndroid Build Coastguard Worker 	NEXT;
4956*7c568831SAndroid Build Coastguard Worker     }
4957*7c568831SAndroid Build Coastguard Worker     if ((ok != 1) || (overflow == 1)) {
4958*7c568831SAndroid Build Coastguard Worker 	return(-1);
4959*7c568831SAndroid Build Coastguard Worker     }
4960*7c568831SAndroid Build Coastguard Worker     return(ret);
4961*7c568831SAndroid Build Coastguard Worker }
4962*7c568831SAndroid Build Coastguard Worker 
4963*7c568831SAndroid Build Coastguard Worker /**
4964*7c568831SAndroid Build Coastguard Worker  * xmlFAParseQuantifier:
4965*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
4966*7c568831SAndroid Build Coastguard Worker  *
4967*7c568831SAndroid Build Coastguard Worker  * [4]   quantifier   ::=   [?*+] | ( '{' quantity '}' )
4968*7c568831SAndroid Build Coastguard Worker  * [5]   quantity   ::=   quantRange | quantMin | QuantExact
4969*7c568831SAndroid Build Coastguard Worker  * [6]   quantRange   ::=   QuantExact ',' QuantExact
4970*7c568831SAndroid Build Coastguard Worker  * [7]   quantMin   ::=   QuantExact ','
4971*7c568831SAndroid Build Coastguard Worker  * [8]   QuantExact   ::=   [0-9]+
4972*7c568831SAndroid Build Coastguard Worker  */
4973*7c568831SAndroid Build Coastguard Worker static int
xmlFAParseQuantifier(xmlRegParserCtxtPtr ctxt)4974*7c568831SAndroid Build Coastguard Worker xmlFAParseQuantifier(xmlRegParserCtxtPtr ctxt) {
4975*7c568831SAndroid Build Coastguard Worker     int cur;
4976*7c568831SAndroid Build Coastguard Worker 
4977*7c568831SAndroid Build Coastguard Worker     cur = CUR;
4978*7c568831SAndroid Build Coastguard Worker     if ((cur == '?') || (cur == '*') || (cur == '+')) {
4979*7c568831SAndroid Build Coastguard Worker 	if (ctxt->atom != NULL) {
4980*7c568831SAndroid Build Coastguard Worker 	    if (cur == '?')
4981*7c568831SAndroid Build Coastguard Worker 		ctxt->atom->quant = XML_REGEXP_QUANT_OPT;
4982*7c568831SAndroid Build Coastguard Worker 	    else if (cur == '*')
4983*7c568831SAndroid Build Coastguard Worker 		ctxt->atom->quant = XML_REGEXP_QUANT_MULT;
4984*7c568831SAndroid Build Coastguard Worker 	    else if (cur == '+')
4985*7c568831SAndroid Build Coastguard Worker 		ctxt->atom->quant = XML_REGEXP_QUANT_PLUS;
4986*7c568831SAndroid Build Coastguard Worker 	}
4987*7c568831SAndroid Build Coastguard Worker 	NEXT;
4988*7c568831SAndroid Build Coastguard Worker 	return(1);
4989*7c568831SAndroid Build Coastguard Worker     }
4990*7c568831SAndroid Build Coastguard Worker     if (cur == '{') {
4991*7c568831SAndroid Build Coastguard Worker 	int min = 0, max = 0;
4992*7c568831SAndroid Build Coastguard Worker 
4993*7c568831SAndroid Build Coastguard Worker 	NEXT;
4994*7c568831SAndroid Build Coastguard Worker 	cur = xmlFAParseQuantExact(ctxt);
4995*7c568831SAndroid Build Coastguard Worker 	if (cur >= 0)
4996*7c568831SAndroid Build Coastguard Worker 	    min = cur;
4997*7c568831SAndroid Build Coastguard Worker         else {
4998*7c568831SAndroid Build Coastguard Worker             ERROR("Improper quantifier");
4999*7c568831SAndroid Build Coastguard Worker         }
5000*7c568831SAndroid Build Coastguard Worker 	if (CUR == ',') {
5001*7c568831SAndroid Build Coastguard Worker 	    NEXT;
5002*7c568831SAndroid Build Coastguard Worker 	    if (CUR == '}')
5003*7c568831SAndroid Build Coastguard Worker 	        max = INT_MAX;
5004*7c568831SAndroid Build Coastguard Worker 	    else {
5005*7c568831SAndroid Build Coastguard Worker 	        cur = xmlFAParseQuantExact(ctxt);
5006*7c568831SAndroid Build Coastguard Worker 	        if (cur >= 0)
5007*7c568831SAndroid Build Coastguard Worker 		    max = cur;
5008*7c568831SAndroid Build Coastguard Worker 		else {
5009*7c568831SAndroid Build Coastguard Worker 		    ERROR("Improper quantifier");
5010*7c568831SAndroid Build Coastguard Worker 		}
5011*7c568831SAndroid Build Coastguard Worker 	    }
5012*7c568831SAndroid Build Coastguard Worker 	}
5013*7c568831SAndroid Build Coastguard Worker 	if (CUR == '}') {
5014*7c568831SAndroid Build Coastguard Worker 	    NEXT;
5015*7c568831SAndroid Build Coastguard Worker 	} else {
5016*7c568831SAndroid Build Coastguard Worker 	    ERROR("Unterminated quantifier");
5017*7c568831SAndroid Build Coastguard Worker 	}
5018*7c568831SAndroid Build Coastguard Worker 	if (max == 0)
5019*7c568831SAndroid Build Coastguard Worker 	    max = min;
5020*7c568831SAndroid Build Coastguard Worker 	if (ctxt->atom != NULL) {
5021*7c568831SAndroid Build Coastguard Worker 	    ctxt->atom->quant = XML_REGEXP_QUANT_RANGE;
5022*7c568831SAndroid Build Coastguard Worker 	    ctxt->atom->min = min;
5023*7c568831SAndroid Build Coastguard Worker 	    ctxt->atom->max = max;
5024*7c568831SAndroid Build Coastguard Worker 	}
5025*7c568831SAndroid Build Coastguard Worker 	return(1);
5026*7c568831SAndroid Build Coastguard Worker     }
5027*7c568831SAndroid Build Coastguard Worker     return(0);
5028*7c568831SAndroid Build Coastguard Worker }
5029*7c568831SAndroid Build Coastguard Worker 
5030*7c568831SAndroid Build Coastguard Worker /**
5031*7c568831SAndroid Build Coastguard Worker  * xmlFAParseAtom:
5032*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
5033*7c568831SAndroid Build Coastguard Worker  *
5034*7c568831SAndroid Build Coastguard Worker  * [9]   atom   ::=   Char | charClass | ( '(' regExp ')' )
5035*7c568831SAndroid Build Coastguard Worker  */
5036*7c568831SAndroid Build Coastguard Worker static int
xmlFAParseAtom(xmlRegParserCtxtPtr ctxt)5037*7c568831SAndroid Build Coastguard Worker xmlFAParseAtom(xmlRegParserCtxtPtr ctxt) {
5038*7c568831SAndroid Build Coastguard Worker     int codepoint, len;
5039*7c568831SAndroid Build Coastguard Worker 
5040*7c568831SAndroid Build Coastguard Worker     codepoint = xmlFAIsChar(ctxt);
5041*7c568831SAndroid Build Coastguard Worker     if (codepoint > 0) {
5042*7c568831SAndroid Build Coastguard Worker 	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL);
5043*7c568831SAndroid Build Coastguard Worker 	if (ctxt->atom == NULL)
5044*7c568831SAndroid Build Coastguard Worker 	    return(-1);
5045*7c568831SAndroid Build Coastguard Worker         len = 4;
5046*7c568831SAndroid Build Coastguard Worker         codepoint = xmlGetUTF8Char(ctxt->cur, &len);
5047*7c568831SAndroid Build Coastguard Worker         if (codepoint < 0) {
5048*7c568831SAndroid Build Coastguard Worker             ERROR("Invalid UTF-8");
5049*7c568831SAndroid Build Coastguard Worker             return(-1);
5050*7c568831SAndroid Build Coastguard Worker         }
5051*7c568831SAndroid Build Coastguard Worker 	ctxt->atom->codepoint = codepoint;
5052*7c568831SAndroid Build Coastguard Worker 	NEXTL(len);
5053*7c568831SAndroid Build Coastguard Worker 	return(1);
5054*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '|') {
5055*7c568831SAndroid Build Coastguard Worker 	return(0);
5056*7c568831SAndroid Build Coastguard Worker     } else if (CUR == 0) {
5057*7c568831SAndroid Build Coastguard Worker 	return(0);
5058*7c568831SAndroid Build Coastguard Worker     } else if (CUR == ')') {
5059*7c568831SAndroid Build Coastguard Worker 	return(0);
5060*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '(') {
5061*7c568831SAndroid Build Coastguard Worker 	xmlRegStatePtr start, oldend, start0;
5062*7c568831SAndroid Build Coastguard Worker 
5063*7c568831SAndroid Build Coastguard Worker 	NEXT;
5064*7c568831SAndroid Build Coastguard Worker         if (ctxt->depth >= 50) {
5065*7c568831SAndroid Build Coastguard Worker 	    ERROR("xmlFAParseAtom: maximum nesting depth exceeded");
5066*7c568831SAndroid Build Coastguard Worker             return(-1);
5067*7c568831SAndroid Build Coastguard Worker         }
5068*7c568831SAndroid Build Coastguard Worker 	/*
5069*7c568831SAndroid Build Coastguard Worker 	 * this extra Epsilon transition is needed if we count with 0 allowed
5070*7c568831SAndroid Build Coastguard Worker 	 * unfortunately this can't be known at that point
5071*7c568831SAndroid Build Coastguard Worker 	 */
5072*7c568831SAndroid Build Coastguard Worker 	xmlFAGenerateEpsilonTransition(ctxt, ctxt->state, NULL);
5073*7c568831SAndroid Build Coastguard Worker 	start0 = ctxt->state;
5074*7c568831SAndroid Build Coastguard Worker 	xmlFAGenerateEpsilonTransition(ctxt, ctxt->state, NULL);
5075*7c568831SAndroid Build Coastguard Worker 	start = ctxt->state;
5076*7c568831SAndroid Build Coastguard Worker 	oldend = ctxt->end;
5077*7c568831SAndroid Build Coastguard Worker 	ctxt->end = NULL;
5078*7c568831SAndroid Build Coastguard Worker 	ctxt->atom = NULL;
5079*7c568831SAndroid Build Coastguard Worker         ctxt->depth++;
5080*7c568831SAndroid Build Coastguard Worker 	xmlFAParseRegExp(ctxt, 0);
5081*7c568831SAndroid Build Coastguard Worker         ctxt->depth--;
5082*7c568831SAndroid Build Coastguard Worker 	if (CUR == ')') {
5083*7c568831SAndroid Build Coastguard Worker 	    NEXT;
5084*7c568831SAndroid Build Coastguard Worker 	} else {
5085*7c568831SAndroid Build Coastguard Worker 	    ERROR("xmlFAParseAtom: expecting ')'");
5086*7c568831SAndroid Build Coastguard Worker 	}
5087*7c568831SAndroid Build Coastguard Worker 	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_SUBREG);
5088*7c568831SAndroid Build Coastguard Worker 	if (ctxt->atom == NULL)
5089*7c568831SAndroid Build Coastguard Worker 	    return(-1);
5090*7c568831SAndroid Build Coastguard Worker 	ctxt->atom->start = start;
5091*7c568831SAndroid Build Coastguard Worker 	ctxt->atom->start0 = start0;
5092*7c568831SAndroid Build Coastguard Worker 	ctxt->atom->stop = ctxt->state;
5093*7c568831SAndroid Build Coastguard Worker 	ctxt->end = oldend;
5094*7c568831SAndroid Build Coastguard Worker 	return(1);
5095*7c568831SAndroid Build Coastguard Worker     } else if ((CUR == '[') || (CUR == '\\') || (CUR == '.')) {
5096*7c568831SAndroid Build Coastguard Worker 	xmlFAParseCharClass(ctxt);
5097*7c568831SAndroid Build Coastguard Worker 	return(1);
5098*7c568831SAndroid Build Coastguard Worker     }
5099*7c568831SAndroid Build Coastguard Worker     return(0);
5100*7c568831SAndroid Build Coastguard Worker }
5101*7c568831SAndroid Build Coastguard Worker 
5102*7c568831SAndroid Build Coastguard Worker /**
5103*7c568831SAndroid Build Coastguard Worker  * xmlFAParsePiece:
5104*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
5105*7c568831SAndroid Build Coastguard Worker  *
5106*7c568831SAndroid Build Coastguard Worker  * [3]   piece   ::=   atom quantifier?
5107*7c568831SAndroid Build Coastguard Worker  */
5108*7c568831SAndroid Build Coastguard Worker static int
xmlFAParsePiece(xmlRegParserCtxtPtr ctxt)5109*7c568831SAndroid Build Coastguard Worker xmlFAParsePiece(xmlRegParserCtxtPtr ctxt) {
5110*7c568831SAndroid Build Coastguard Worker     int ret;
5111*7c568831SAndroid Build Coastguard Worker 
5112*7c568831SAndroid Build Coastguard Worker     ctxt->atom = NULL;
5113*7c568831SAndroid Build Coastguard Worker     ret = xmlFAParseAtom(ctxt);
5114*7c568831SAndroid Build Coastguard Worker     if (ret == 0)
5115*7c568831SAndroid Build Coastguard Worker 	return(0);
5116*7c568831SAndroid Build Coastguard Worker     if (ctxt->atom == NULL) {
5117*7c568831SAndroid Build Coastguard Worker 	ERROR("internal: no atom generated");
5118*7c568831SAndroid Build Coastguard Worker     }
5119*7c568831SAndroid Build Coastguard Worker     xmlFAParseQuantifier(ctxt);
5120*7c568831SAndroid Build Coastguard Worker     return(1);
5121*7c568831SAndroid Build Coastguard Worker }
5122*7c568831SAndroid Build Coastguard Worker 
5123*7c568831SAndroid Build Coastguard Worker /**
5124*7c568831SAndroid Build Coastguard Worker  * xmlFAParseBranch:
5125*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
5126*7c568831SAndroid Build Coastguard Worker  * @to: optional target to the end of the branch
5127*7c568831SAndroid Build Coastguard Worker  *
5128*7c568831SAndroid Build Coastguard Worker  * @to is used to optimize by removing duplicate path in automata
5129*7c568831SAndroid Build Coastguard Worker  * in expressions like (a|b)(c|d)
5130*7c568831SAndroid Build Coastguard Worker  *
5131*7c568831SAndroid Build Coastguard Worker  * [2]   branch   ::=   piece*
5132*7c568831SAndroid Build Coastguard Worker  */
5133*7c568831SAndroid Build Coastguard Worker static int
xmlFAParseBranch(xmlRegParserCtxtPtr ctxt,xmlRegStatePtr to)5134*7c568831SAndroid Build Coastguard Worker xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) {
5135*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr previous;
5136*7c568831SAndroid Build Coastguard Worker     int ret;
5137*7c568831SAndroid Build Coastguard Worker 
5138*7c568831SAndroid Build Coastguard Worker     previous = ctxt->state;
5139*7c568831SAndroid Build Coastguard Worker     ret = xmlFAParsePiece(ctxt);
5140*7c568831SAndroid Build Coastguard Worker     if (ret == 0) {
5141*7c568831SAndroid Build Coastguard Worker         /* Empty branch */
5142*7c568831SAndroid Build Coastguard Worker 	xmlFAGenerateEpsilonTransition(ctxt, previous, to);
5143*7c568831SAndroid Build Coastguard Worker     } else {
5144*7c568831SAndroid Build Coastguard Worker 	if (xmlFAGenerateTransitions(ctxt, previous,
5145*7c568831SAndroid Build Coastguard Worker 	        (CUR=='|' || CUR==')' || CUR==0) ? to : NULL,
5146*7c568831SAndroid Build Coastguard Worker                 ctxt->atom) < 0) {
5147*7c568831SAndroid Build Coastguard Worker             xmlRegFreeAtom(ctxt->atom);
5148*7c568831SAndroid Build Coastguard Worker             ctxt->atom = NULL;
5149*7c568831SAndroid Build Coastguard Worker 	    return(-1);
5150*7c568831SAndroid Build Coastguard Worker         }
5151*7c568831SAndroid Build Coastguard Worker 	previous = ctxt->state;
5152*7c568831SAndroid Build Coastguard Worker 	ctxt->atom = NULL;
5153*7c568831SAndroid Build Coastguard Worker     }
5154*7c568831SAndroid Build Coastguard Worker     while ((ret != 0) && (ctxt->error == 0)) {
5155*7c568831SAndroid Build Coastguard Worker 	ret = xmlFAParsePiece(ctxt);
5156*7c568831SAndroid Build Coastguard Worker 	if (ret != 0) {
5157*7c568831SAndroid Build Coastguard Worker 	    if (xmlFAGenerateTransitions(ctxt, previous,
5158*7c568831SAndroid Build Coastguard Worker 	            (CUR=='|' || CUR==')' || CUR==0) ? to : NULL,
5159*7c568831SAndroid Build Coastguard Worker                     ctxt->atom) < 0) {
5160*7c568831SAndroid Build Coastguard Worker                 xmlRegFreeAtom(ctxt->atom);
5161*7c568831SAndroid Build Coastguard Worker                 ctxt->atom = NULL;
5162*7c568831SAndroid Build Coastguard Worker                 return(-1);
5163*7c568831SAndroid Build Coastguard Worker             }
5164*7c568831SAndroid Build Coastguard Worker 	    previous = ctxt->state;
5165*7c568831SAndroid Build Coastguard Worker 	    ctxt->atom = NULL;
5166*7c568831SAndroid Build Coastguard Worker 	}
5167*7c568831SAndroid Build Coastguard Worker     }
5168*7c568831SAndroid Build Coastguard Worker     return(0);
5169*7c568831SAndroid Build Coastguard Worker }
5170*7c568831SAndroid Build Coastguard Worker 
5171*7c568831SAndroid Build Coastguard Worker /**
5172*7c568831SAndroid Build Coastguard Worker  * xmlFAParseRegExp:
5173*7c568831SAndroid Build Coastguard Worker  * @ctxt:  a regexp parser context
5174*7c568831SAndroid Build Coastguard Worker  * @top:  is this the top-level expression ?
5175*7c568831SAndroid Build Coastguard Worker  *
5176*7c568831SAndroid Build Coastguard Worker  * [1]   regExp   ::=     branch  ( '|' branch )*
5177*7c568831SAndroid Build Coastguard Worker  */
5178*7c568831SAndroid Build Coastguard Worker static void
xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt,int top)5179*7c568831SAndroid Build Coastguard Worker xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
5180*7c568831SAndroid Build Coastguard Worker     xmlRegStatePtr start, end;
5181*7c568831SAndroid Build Coastguard Worker 
5182*7c568831SAndroid Build Coastguard Worker     /* if not top start should have been generated by an epsilon trans */
5183*7c568831SAndroid Build Coastguard Worker     start = ctxt->state;
5184*7c568831SAndroid Build Coastguard Worker     ctxt->end = NULL;
5185*7c568831SAndroid Build Coastguard Worker     xmlFAParseBranch(ctxt, NULL);
5186*7c568831SAndroid Build Coastguard Worker     if (top) {
5187*7c568831SAndroid Build Coastguard Worker 	ctxt->state->type = XML_REGEXP_FINAL_STATE;
5188*7c568831SAndroid Build Coastguard Worker     }
5189*7c568831SAndroid Build Coastguard Worker     if (CUR != '|') {
5190*7c568831SAndroid Build Coastguard Worker 	ctxt->end = ctxt->state;
5191*7c568831SAndroid Build Coastguard Worker 	return;
5192*7c568831SAndroid Build Coastguard Worker     }
5193*7c568831SAndroid Build Coastguard Worker     end = ctxt->state;
5194*7c568831SAndroid Build Coastguard Worker     while ((CUR == '|') && (ctxt->error == 0)) {
5195*7c568831SAndroid Build Coastguard Worker 	NEXT;
5196*7c568831SAndroid Build Coastguard Worker 	ctxt->state = start;
5197*7c568831SAndroid Build Coastguard Worker 	ctxt->end = NULL;
5198*7c568831SAndroid Build Coastguard Worker 	xmlFAParseBranch(ctxt, end);
5199*7c568831SAndroid Build Coastguard Worker     }
5200*7c568831SAndroid Build Coastguard Worker     if (!top) {
5201*7c568831SAndroid Build Coastguard Worker 	ctxt->state = end;
5202*7c568831SAndroid Build Coastguard Worker 	ctxt->end = end;
5203*7c568831SAndroid Build Coastguard Worker     }
5204*7c568831SAndroid Build Coastguard Worker }
5205*7c568831SAndroid Build Coastguard Worker 
5206*7c568831SAndroid Build Coastguard Worker /************************************************************************
5207*7c568831SAndroid Build Coastguard Worker  *									*
5208*7c568831SAndroid Build Coastguard Worker  *			The basic API					*
5209*7c568831SAndroid Build Coastguard Worker  *									*
5210*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
5211*7c568831SAndroid Build Coastguard Worker 
5212*7c568831SAndroid Build Coastguard Worker /**
5213*7c568831SAndroid Build Coastguard Worker  * xmlRegexpPrint:
5214*7c568831SAndroid Build Coastguard Worker  * @output: the file for the output debug
5215*7c568831SAndroid Build Coastguard Worker  * @regexp: the compiled regexp
5216*7c568831SAndroid Build Coastguard Worker  *
5217*7c568831SAndroid Build Coastguard Worker  * Print the content of the compiled regular expression
5218*7c568831SAndroid Build Coastguard Worker  */
5219*7c568831SAndroid Build Coastguard Worker void
xmlRegexpPrint(FILE * output,xmlRegexpPtr regexp)5220*7c568831SAndroid Build Coastguard Worker xmlRegexpPrint(FILE *output, xmlRegexpPtr regexp) {
5221*7c568831SAndroid Build Coastguard Worker     int i;
5222*7c568831SAndroid Build Coastguard Worker 
5223*7c568831SAndroid Build Coastguard Worker     if (output == NULL)
5224*7c568831SAndroid Build Coastguard Worker         return;
5225*7c568831SAndroid Build Coastguard Worker     fprintf(output, " regexp: ");
5226*7c568831SAndroid Build Coastguard Worker     if (regexp == NULL) {
5227*7c568831SAndroid Build Coastguard Worker 	fprintf(output, "NULL\n");
5228*7c568831SAndroid Build Coastguard Worker 	return;
5229*7c568831SAndroid Build Coastguard Worker     }
5230*7c568831SAndroid Build Coastguard Worker     fprintf(output, "'%s' ", regexp->string);
5231*7c568831SAndroid Build Coastguard Worker     fprintf(output, "\n");
5232*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%d atoms:\n", regexp->nbAtoms);
5233*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < regexp->nbAtoms; i++) {
5234*7c568831SAndroid Build Coastguard Worker 	fprintf(output, " %02d ", i);
5235*7c568831SAndroid Build Coastguard Worker 	xmlRegPrintAtom(output, regexp->atoms[i]);
5236*7c568831SAndroid Build Coastguard Worker     }
5237*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%d states:", regexp->nbStates);
5238*7c568831SAndroid Build Coastguard Worker     fprintf(output, "\n");
5239*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < regexp->nbStates; i++) {
5240*7c568831SAndroid Build Coastguard Worker 	xmlRegPrintState(output, regexp->states[i]);
5241*7c568831SAndroid Build Coastguard Worker     }
5242*7c568831SAndroid Build Coastguard Worker     fprintf(output, "%d counters:\n", regexp->nbCounters);
5243*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < regexp->nbCounters; i++) {
5244*7c568831SAndroid Build Coastguard Worker 	fprintf(output, " %d: min %d max %d\n", i, regexp->counters[i].min,
5245*7c568831SAndroid Build Coastguard Worker 		                                regexp->counters[i].max);
5246*7c568831SAndroid Build Coastguard Worker     }
5247*7c568831SAndroid Build Coastguard Worker }
5248*7c568831SAndroid Build Coastguard Worker 
5249*7c568831SAndroid Build Coastguard Worker /**
5250*7c568831SAndroid Build Coastguard Worker  * xmlRegexpCompile:
5251*7c568831SAndroid Build Coastguard Worker  * @regexp:  a regular expression string
5252*7c568831SAndroid Build Coastguard Worker  *
5253*7c568831SAndroid Build Coastguard Worker  * Parses a regular expression conforming to XML Schemas Part 2 Datatype
5254*7c568831SAndroid Build Coastguard Worker  * Appendix F and builds an automata suitable for testing strings against
5255*7c568831SAndroid Build Coastguard Worker  * that regular expression
5256*7c568831SAndroid Build Coastguard Worker  *
5257*7c568831SAndroid Build Coastguard Worker  * Returns the compiled expression or NULL in case of error
5258*7c568831SAndroid Build Coastguard Worker  */
5259*7c568831SAndroid Build Coastguard Worker xmlRegexpPtr
xmlRegexpCompile(const xmlChar * regexp)5260*7c568831SAndroid Build Coastguard Worker xmlRegexpCompile(const xmlChar *regexp) {
5261*7c568831SAndroid Build Coastguard Worker     xmlRegexpPtr ret = NULL;
5262*7c568831SAndroid Build Coastguard Worker     xmlRegParserCtxtPtr ctxt;
5263*7c568831SAndroid Build Coastguard Worker 
5264*7c568831SAndroid Build Coastguard Worker     if (regexp == NULL)
5265*7c568831SAndroid Build Coastguard Worker         return(NULL);
5266*7c568831SAndroid Build Coastguard Worker 
5267*7c568831SAndroid Build Coastguard Worker     ctxt = xmlRegNewParserCtxt(regexp);
5268*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
5269*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5270*7c568831SAndroid Build Coastguard Worker 
5271*7c568831SAndroid Build Coastguard Worker     /* initialize the parser */
5272*7c568831SAndroid Build Coastguard Worker     ctxt->state = xmlRegStatePush(ctxt);
5273*7c568831SAndroid Build Coastguard Worker     if (ctxt->state == NULL)
5274*7c568831SAndroid Build Coastguard Worker         goto error;
5275*7c568831SAndroid Build Coastguard Worker     ctxt->start = ctxt->state;
5276*7c568831SAndroid Build Coastguard Worker     ctxt->end = NULL;
5277*7c568831SAndroid Build Coastguard Worker 
5278*7c568831SAndroid Build Coastguard Worker     /* parse the expression building an automata */
5279*7c568831SAndroid Build Coastguard Worker     xmlFAParseRegExp(ctxt, 1);
5280*7c568831SAndroid Build Coastguard Worker     if (CUR != 0) {
5281*7c568831SAndroid Build Coastguard Worker 	ERROR("xmlFAParseRegExp: extra characters");
5282*7c568831SAndroid Build Coastguard Worker     }
5283*7c568831SAndroid Build Coastguard Worker     if (ctxt->error != 0)
5284*7c568831SAndroid Build Coastguard Worker         goto error;
5285*7c568831SAndroid Build Coastguard Worker     ctxt->end = ctxt->state;
5286*7c568831SAndroid Build Coastguard Worker     ctxt->start->type = XML_REGEXP_START_STATE;
5287*7c568831SAndroid Build Coastguard Worker     ctxt->end->type = XML_REGEXP_FINAL_STATE;
5288*7c568831SAndroid Build Coastguard Worker 
5289*7c568831SAndroid Build Coastguard Worker     /* remove the Epsilon except for counted transitions */
5290*7c568831SAndroid Build Coastguard Worker     xmlFAEliminateEpsilonTransitions(ctxt);
5291*7c568831SAndroid Build Coastguard Worker 
5292*7c568831SAndroid Build Coastguard Worker 
5293*7c568831SAndroid Build Coastguard Worker     if (ctxt->error != 0)
5294*7c568831SAndroid Build Coastguard Worker         goto error;
5295*7c568831SAndroid Build Coastguard Worker     ret = xmlRegEpxFromParse(ctxt);
5296*7c568831SAndroid Build Coastguard Worker 
5297*7c568831SAndroid Build Coastguard Worker error:
5298*7c568831SAndroid Build Coastguard Worker     xmlRegFreeParserCtxt(ctxt);
5299*7c568831SAndroid Build Coastguard Worker     return(ret);
5300*7c568831SAndroid Build Coastguard Worker }
5301*7c568831SAndroid Build Coastguard Worker 
5302*7c568831SAndroid Build Coastguard Worker /**
5303*7c568831SAndroid Build Coastguard Worker  * xmlRegexpExec:
5304*7c568831SAndroid Build Coastguard Worker  * @comp:  the compiled regular expression
5305*7c568831SAndroid Build Coastguard Worker  * @content:  the value to check against the regular expression
5306*7c568831SAndroid Build Coastguard Worker  *
5307*7c568831SAndroid Build Coastguard Worker  * Check if the regular expression generates the value
5308*7c568831SAndroid Build Coastguard Worker  *
5309*7c568831SAndroid Build Coastguard Worker  * Returns 1 if it matches, 0 if not and a negative value in case of error
5310*7c568831SAndroid Build Coastguard Worker  */
5311*7c568831SAndroid Build Coastguard Worker int
xmlRegexpExec(xmlRegexpPtr comp,const xmlChar * content)5312*7c568831SAndroid Build Coastguard Worker xmlRegexpExec(xmlRegexpPtr comp, const xmlChar *content) {
5313*7c568831SAndroid Build Coastguard Worker     if ((comp == NULL) || (content == NULL))
5314*7c568831SAndroid Build Coastguard Worker 	return(-1);
5315*7c568831SAndroid Build Coastguard Worker     return(xmlFARegExec(comp, content));
5316*7c568831SAndroid Build Coastguard Worker }
5317*7c568831SAndroid Build Coastguard Worker 
5318*7c568831SAndroid Build Coastguard Worker /**
5319*7c568831SAndroid Build Coastguard Worker  * xmlRegexpIsDeterminist:
5320*7c568831SAndroid Build Coastguard Worker  * @comp:  the compiled regular expression
5321*7c568831SAndroid Build Coastguard Worker  *
5322*7c568831SAndroid Build Coastguard Worker  * Check if the regular expression is determinist
5323*7c568831SAndroid Build Coastguard Worker  *
5324*7c568831SAndroid Build Coastguard Worker  * Returns 1 if it yes, 0 if not and a negative value in case of error
5325*7c568831SAndroid Build Coastguard Worker  */
5326*7c568831SAndroid Build Coastguard Worker int
xmlRegexpIsDeterminist(xmlRegexpPtr comp)5327*7c568831SAndroid Build Coastguard Worker xmlRegexpIsDeterminist(xmlRegexpPtr comp) {
5328*7c568831SAndroid Build Coastguard Worker     xmlAutomataPtr am;
5329*7c568831SAndroid Build Coastguard Worker     int ret;
5330*7c568831SAndroid Build Coastguard Worker 
5331*7c568831SAndroid Build Coastguard Worker     if (comp == NULL)
5332*7c568831SAndroid Build Coastguard Worker 	return(-1);
5333*7c568831SAndroid Build Coastguard Worker     if (comp->determinist != -1)
5334*7c568831SAndroid Build Coastguard Worker 	return(comp->determinist);
5335*7c568831SAndroid Build Coastguard Worker 
5336*7c568831SAndroid Build Coastguard Worker     am = xmlNewAutomata();
5337*7c568831SAndroid Build Coastguard Worker     if (am == NULL)
5338*7c568831SAndroid Build Coastguard Worker         return(-1);
5339*7c568831SAndroid Build Coastguard Worker     if (am->states != NULL) {
5340*7c568831SAndroid Build Coastguard Worker 	int i;
5341*7c568831SAndroid Build Coastguard Worker 
5342*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < am->nbStates;i++)
5343*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeState(am->states[i]);
5344*7c568831SAndroid Build Coastguard Worker 	xmlFree(am->states);
5345*7c568831SAndroid Build Coastguard Worker     }
5346*7c568831SAndroid Build Coastguard Worker     am->nbAtoms = comp->nbAtoms;
5347*7c568831SAndroid Build Coastguard Worker     am->atoms = comp->atoms;
5348*7c568831SAndroid Build Coastguard Worker     am->nbStates = comp->nbStates;
5349*7c568831SAndroid Build Coastguard Worker     am->states = comp->states;
5350*7c568831SAndroid Build Coastguard Worker     am->determinist = -1;
5351*7c568831SAndroid Build Coastguard Worker     am->flags = comp->flags;
5352*7c568831SAndroid Build Coastguard Worker     ret = xmlFAComputesDeterminism(am);
5353*7c568831SAndroid Build Coastguard Worker     am->atoms = NULL;
5354*7c568831SAndroid Build Coastguard Worker     am->states = NULL;
5355*7c568831SAndroid Build Coastguard Worker     xmlFreeAutomata(am);
5356*7c568831SAndroid Build Coastguard Worker     comp->determinist = ret;
5357*7c568831SAndroid Build Coastguard Worker     return(ret);
5358*7c568831SAndroid Build Coastguard Worker }
5359*7c568831SAndroid Build Coastguard Worker 
5360*7c568831SAndroid Build Coastguard Worker /**
5361*7c568831SAndroid Build Coastguard Worker  * xmlRegFreeRegexp:
5362*7c568831SAndroid Build Coastguard Worker  * @regexp:  the regexp
5363*7c568831SAndroid Build Coastguard Worker  *
5364*7c568831SAndroid Build Coastguard Worker  * Free a regexp
5365*7c568831SAndroid Build Coastguard Worker  */
5366*7c568831SAndroid Build Coastguard Worker void
xmlRegFreeRegexp(xmlRegexpPtr regexp)5367*7c568831SAndroid Build Coastguard Worker xmlRegFreeRegexp(xmlRegexpPtr regexp) {
5368*7c568831SAndroid Build Coastguard Worker     int i;
5369*7c568831SAndroid Build Coastguard Worker     if (regexp == NULL)
5370*7c568831SAndroid Build Coastguard Worker 	return;
5371*7c568831SAndroid Build Coastguard Worker 
5372*7c568831SAndroid Build Coastguard Worker     if (regexp->string != NULL)
5373*7c568831SAndroid Build Coastguard Worker 	xmlFree(regexp->string);
5374*7c568831SAndroid Build Coastguard Worker     if (regexp->states != NULL) {
5375*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < regexp->nbStates;i++)
5376*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeState(regexp->states[i]);
5377*7c568831SAndroid Build Coastguard Worker 	xmlFree(regexp->states);
5378*7c568831SAndroid Build Coastguard Worker     }
5379*7c568831SAndroid Build Coastguard Worker     if (regexp->atoms != NULL) {
5380*7c568831SAndroid Build Coastguard Worker 	for (i = 0;i < regexp->nbAtoms;i++)
5381*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeAtom(regexp->atoms[i]);
5382*7c568831SAndroid Build Coastguard Worker 	xmlFree(regexp->atoms);
5383*7c568831SAndroid Build Coastguard Worker     }
5384*7c568831SAndroid Build Coastguard Worker     if (regexp->counters != NULL)
5385*7c568831SAndroid Build Coastguard Worker 	xmlFree(regexp->counters);
5386*7c568831SAndroid Build Coastguard Worker     if (regexp->compact != NULL)
5387*7c568831SAndroid Build Coastguard Worker 	xmlFree(regexp->compact);
5388*7c568831SAndroid Build Coastguard Worker     if (regexp->transdata != NULL)
5389*7c568831SAndroid Build Coastguard Worker 	xmlFree(regexp->transdata);
5390*7c568831SAndroid Build Coastguard Worker     if (regexp->stringMap != NULL) {
5391*7c568831SAndroid Build Coastguard Worker 	for (i = 0; i < regexp->nbstrings;i++)
5392*7c568831SAndroid Build Coastguard Worker 	    xmlFree(regexp->stringMap[i]);
5393*7c568831SAndroid Build Coastguard Worker 	xmlFree(regexp->stringMap);
5394*7c568831SAndroid Build Coastguard Worker     }
5395*7c568831SAndroid Build Coastguard Worker 
5396*7c568831SAndroid Build Coastguard Worker     xmlFree(regexp);
5397*7c568831SAndroid Build Coastguard Worker }
5398*7c568831SAndroid Build Coastguard Worker 
5399*7c568831SAndroid Build Coastguard Worker /************************************************************************
5400*7c568831SAndroid Build Coastguard Worker  *									*
5401*7c568831SAndroid Build Coastguard Worker  *			The Automata interface				*
5402*7c568831SAndroid Build Coastguard Worker  *									*
5403*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
5404*7c568831SAndroid Build Coastguard Worker 
5405*7c568831SAndroid Build Coastguard Worker /**
5406*7c568831SAndroid Build Coastguard Worker  * xmlNewAutomata:
5407*7c568831SAndroid Build Coastguard Worker  *
5408*7c568831SAndroid Build Coastguard Worker  * Create a new automata
5409*7c568831SAndroid Build Coastguard Worker  *
5410*7c568831SAndroid Build Coastguard Worker  * Returns the new object or NULL in case of failure
5411*7c568831SAndroid Build Coastguard Worker  */
5412*7c568831SAndroid Build Coastguard Worker xmlAutomataPtr
xmlNewAutomata(void)5413*7c568831SAndroid Build Coastguard Worker xmlNewAutomata(void) {
5414*7c568831SAndroid Build Coastguard Worker     xmlAutomataPtr ctxt;
5415*7c568831SAndroid Build Coastguard Worker 
5416*7c568831SAndroid Build Coastguard Worker     ctxt = xmlRegNewParserCtxt(NULL);
5417*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
5418*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5419*7c568831SAndroid Build Coastguard Worker 
5420*7c568831SAndroid Build Coastguard Worker     /* initialize the parser */
5421*7c568831SAndroid Build Coastguard Worker     ctxt->state = xmlRegStatePush(ctxt);
5422*7c568831SAndroid Build Coastguard Worker     if (ctxt->state == NULL) {
5423*7c568831SAndroid Build Coastguard Worker 	xmlFreeAutomata(ctxt);
5424*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5425*7c568831SAndroid Build Coastguard Worker     }
5426*7c568831SAndroid Build Coastguard Worker     ctxt->start = ctxt->state;
5427*7c568831SAndroid Build Coastguard Worker     ctxt->end = NULL;
5428*7c568831SAndroid Build Coastguard Worker 
5429*7c568831SAndroid Build Coastguard Worker     ctxt->start->type = XML_REGEXP_START_STATE;
5430*7c568831SAndroid Build Coastguard Worker     ctxt->flags = 0;
5431*7c568831SAndroid Build Coastguard Worker 
5432*7c568831SAndroid Build Coastguard Worker     return(ctxt);
5433*7c568831SAndroid Build Coastguard Worker }
5434*7c568831SAndroid Build Coastguard Worker 
5435*7c568831SAndroid Build Coastguard Worker /**
5436*7c568831SAndroid Build Coastguard Worker  * xmlFreeAutomata:
5437*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5438*7c568831SAndroid Build Coastguard Worker  *
5439*7c568831SAndroid Build Coastguard Worker  * Free an automata
5440*7c568831SAndroid Build Coastguard Worker  */
5441*7c568831SAndroid Build Coastguard Worker void
xmlFreeAutomata(xmlAutomataPtr am)5442*7c568831SAndroid Build Coastguard Worker xmlFreeAutomata(xmlAutomataPtr am) {
5443*7c568831SAndroid Build Coastguard Worker     if (am == NULL)
5444*7c568831SAndroid Build Coastguard Worker 	return;
5445*7c568831SAndroid Build Coastguard Worker     xmlRegFreeParserCtxt(am);
5446*7c568831SAndroid Build Coastguard Worker }
5447*7c568831SAndroid Build Coastguard Worker 
5448*7c568831SAndroid Build Coastguard Worker /**
5449*7c568831SAndroid Build Coastguard Worker  * xmlAutomataSetFlags:
5450*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5451*7c568831SAndroid Build Coastguard Worker  * @flags:  a set of internal flags
5452*7c568831SAndroid Build Coastguard Worker  *
5453*7c568831SAndroid Build Coastguard Worker  * Set some flags on the automata
5454*7c568831SAndroid Build Coastguard Worker  */
5455*7c568831SAndroid Build Coastguard Worker void
xmlAutomataSetFlags(xmlAutomataPtr am,int flags)5456*7c568831SAndroid Build Coastguard Worker xmlAutomataSetFlags(xmlAutomataPtr am, int flags) {
5457*7c568831SAndroid Build Coastguard Worker     if (am == NULL)
5458*7c568831SAndroid Build Coastguard Worker 	return;
5459*7c568831SAndroid Build Coastguard Worker     am->flags |= flags;
5460*7c568831SAndroid Build Coastguard Worker }
5461*7c568831SAndroid Build Coastguard Worker 
5462*7c568831SAndroid Build Coastguard Worker /**
5463*7c568831SAndroid Build Coastguard Worker  * xmlAutomataGetInitState:
5464*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5465*7c568831SAndroid Build Coastguard Worker  *
5466*7c568831SAndroid Build Coastguard Worker  * Initial state lookup
5467*7c568831SAndroid Build Coastguard Worker  *
5468*7c568831SAndroid Build Coastguard Worker  * Returns the initial state of the automata
5469*7c568831SAndroid Build Coastguard Worker  */
5470*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataGetInitState(xmlAutomataPtr am)5471*7c568831SAndroid Build Coastguard Worker xmlAutomataGetInitState(xmlAutomataPtr am) {
5472*7c568831SAndroid Build Coastguard Worker     if (am == NULL)
5473*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5474*7c568831SAndroid Build Coastguard Worker     return(am->start);
5475*7c568831SAndroid Build Coastguard Worker }
5476*7c568831SAndroid Build Coastguard Worker 
5477*7c568831SAndroid Build Coastguard Worker /**
5478*7c568831SAndroid Build Coastguard Worker  * xmlAutomataSetFinalState:
5479*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5480*7c568831SAndroid Build Coastguard Worker  * @state: a state in this automata
5481*7c568831SAndroid Build Coastguard Worker  *
5482*7c568831SAndroid Build Coastguard Worker  * Makes that state a final state
5483*7c568831SAndroid Build Coastguard Worker  *
5484*7c568831SAndroid Build Coastguard Worker  * Returns 0 or -1 in case of error
5485*7c568831SAndroid Build Coastguard Worker  */
5486*7c568831SAndroid Build Coastguard Worker int
xmlAutomataSetFinalState(xmlAutomataPtr am,xmlAutomataStatePtr state)5487*7c568831SAndroid Build Coastguard Worker xmlAutomataSetFinalState(xmlAutomataPtr am, xmlAutomataStatePtr state) {
5488*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (state == NULL))
5489*7c568831SAndroid Build Coastguard Worker 	return(-1);
5490*7c568831SAndroid Build Coastguard Worker     state->type = XML_REGEXP_FINAL_STATE;
5491*7c568831SAndroid Build Coastguard Worker     return(0);
5492*7c568831SAndroid Build Coastguard Worker }
5493*7c568831SAndroid Build Coastguard Worker 
5494*7c568831SAndroid Build Coastguard Worker /**
5495*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewTransition:
5496*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5497*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
5498*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
5499*7c568831SAndroid Build Coastguard Worker  * @token: the input string associated to that transition
5500*7c568831SAndroid Build Coastguard Worker  * @data: data passed to the callback function if the transition is activated
5501*7c568831SAndroid Build Coastguard Worker  *
5502*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
5503*7c568831SAndroid Build Coastguard Worker  * and then adds a transition from the @from state to the target state
5504*7c568831SAndroid Build Coastguard Worker  * activated by the value of @token
5505*7c568831SAndroid Build Coastguard Worker  *
5506*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
5507*7c568831SAndroid Build Coastguard Worker  */
5508*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewTransition(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,const xmlChar * token,void * data)5509*7c568831SAndroid Build Coastguard Worker xmlAutomataNewTransition(xmlAutomataPtr am, xmlAutomataStatePtr from,
5510*7c568831SAndroid Build Coastguard Worker 			 xmlAutomataStatePtr to, const xmlChar *token,
5511*7c568831SAndroid Build Coastguard Worker 			 void *data) {
5512*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
5513*7c568831SAndroid Build Coastguard Worker 
5514*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (token == NULL))
5515*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5516*7c568831SAndroid Build Coastguard Worker     atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5517*7c568831SAndroid Build Coastguard Worker     if (atom == NULL)
5518*7c568831SAndroid Build Coastguard Worker         return(NULL);
5519*7c568831SAndroid Build Coastguard Worker     atom->data = data;
5520*7c568831SAndroid Build Coastguard Worker     atom->valuep = xmlStrdup(token);
5521*7c568831SAndroid Build Coastguard Worker     if (atom->valuep == NULL) {
5522*7c568831SAndroid Build Coastguard Worker         xmlRegFreeAtom(atom);
5523*7c568831SAndroid Build Coastguard Worker         xmlRegexpErrMemory(am);
5524*7c568831SAndroid Build Coastguard Worker         return(NULL);
5525*7c568831SAndroid Build Coastguard Worker     }
5526*7c568831SAndroid Build Coastguard Worker 
5527*7c568831SAndroid Build Coastguard Worker     if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
5528*7c568831SAndroid Build Coastguard Worker         xmlRegFreeAtom(atom);
5529*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5530*7c568831SAndroid Build Coastguard Worker     }
5531*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
5532*7c568831SAndroid Build Coastguard Worker 	return(am->state);
5533*7c568831SAndroid Build Coastguard Worker     return(to);
5534*7c568831SAndroid Build Coastguard Worker }
5535*7c568831SAndroid Build Coastguard Worker 
5536*7c568831SAndroid Build Coastguard Worker /**
5537*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewTransition2:
5538*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5539*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
5540*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
5541*7c568831SAndroid Build Coastguard Worker  * @token: the first input string associated to that transition
5542*7c568831SAndroid Build Coastguard Worker  * @token2: the second input string associated to that transition
5543*7c568831SAndroid Build Coastguard Worker  * @data: data passed to the callback function if the transition is activated
5544*7c568831SAndroid Build Coastguard Worker  *
5545*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
5546*7c568831SAndroid Build Coastguard Worker  * and then adds a transition from the @from state to the target state
5547*7c568831SAndroid Build Coastguard Worker  * activated by the value of @token
5548*7c568831SAndroid Build Coastguard Worker  *
5549*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
5550*7c568831SAndroid Build Coastguard Worker  */
5551*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewTransition2(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,const xmlChar * token,const xmlChar * token2,void * data)5552*7c568831SAndroid Build Coastguard Worker xmlAutomataNewTransition2(xmlAutomataPtr am, xmlAutomataStatePtr from,
5553*7c568831SAndroid Build Coastguard Worker 			  xmlAutomataStatePtr to, const xmlChar *token,
5554*7c568831SAndroid Build Coastguard Worker 			  const xmlChar *token2, void *data) {
5555*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
5556*7c568831SAndroid Build Coastguard Worker 
5557*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (token == NULL))
5558*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5559*7c568831SAndroid Build Coastguard Worker     atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5560*7c568831SAndroid Build Coastguard Worker     if (atom == NULL)
5561*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5562*7c568831SAndroid Build Coastguard Worker     atom->data = data;
5563*7c568831SAndroid Build Coastguard Worker     if ((token2 == NULL) || (*token2 == 0)) {
5564*7c568831SAndroid Build Coastguard Worker 	atom->valuep = xmlStrdup(token);
5565*7c568831SAndroid Build Coastguard Worker     } else {
5566*7c568831SAndroid Build Coastguard Worker 	int lenn, lenp;
5567*7c568831SAndroid Build Coastguard Worker 	xmlChar *str;
5568*7c568831SAndroid Build Coastguard Worker 
5569*7c568831SAndroid Build Coastguard Worker 	lenn = strlen((char *) token2);
5570*7c568831SAndroid Build Coastguard Worker 	lenp = strlen((char *) token);
5571*7c568831SAndroid Build Coastguard Worker 
5572*7c568831SAndroid Build Coastguard Worker 	str = xmlMalloc(lenn + lenp + 2);
5573*7c568831SAndroid Build Coastguard Worker 	if (str == NULL) {
5574*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeAtom(atom);
5575*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
5576*7c568831SAndroid Build Coastguard Worker 	}
5577*7c568831SAndroid Build Coastguard Worker 	memcpy(&str[0], token, lenp);
5578*7c568831SAndroid Build Coastguard Worker 	str[lenp] = '|';
5579*7c568831SAndroid Build Coastguard Worker 	memcpy(&str[lenp + 1], token2, lenn);
5580*7c568831SAndroid Build Coastguard Worker 	str[lenn + lenp + 1] = 0;
5581*7c568831SAndroid Build Coastguard Worker 
5582*7c568831SAndroid Build Coastguard Worker 	atom->valuep = str;
5583*7c568831SAndroid Build Coastguard Worker     }
5584*7c568831SAndroid Build Coastguard Worker 
5585*7c568831SAndroid Build Coastguard Worker     if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
5586*7c568831SAndroid Build Coastguard Worker         xmlRegFreeAtom(atom);
5587*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5588*7c568831SAndroid Build Coastguard Worker     }
5589*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
5590*7c568831SAndroid Build Coastguard Worker 	return(am->state);
5591*7c568831SAndroid Build Coastguard Worker     return(to);
5592*7c568831SAndroid Build Coastguard Worker }
5593*7c568831SAndroid Build Coastguard Worker 
5594*7c568831SAndroid Build Coastguard Worker /**
5595*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewNegTrans:
5596*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5597*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
5598*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
5599*7c568831SAndroid Build Coastguard Worker  * @token: the first input string associated to that transition
5600*7c568831SAndroid Build Coastguard Worker  * @token2: the second input string associated to that transition
5601*7c568831SAndroid Build Coastguard Worker  * @data: data passed to the callback function if the transition is activated
5602*7c568831SAndroid Build Coastguard Worker  *
5603*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
5604*7c568831SAndroid Build Coastguard Worker  * and then adds a transition from the @from state to the target state
5605*7c568831SAndroid Build Coastguard Worker  * activated by any value except (@token,@token2)
5606*7c568831SAndroid Build Coastguard Worker  * Note that if @token2 is not NULL, then (X, NULL) won't match to follow
5607*7c568831SAndroid Build Coastguard Worker  # the semantic of XSD ##other
5608*7c568831SAndroid Build Coastguard Worker  *
5609*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
5610*7c568831SAndroid Build Coastguard Worker  */
5611*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewNegTrans(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,const xmlChar * token,const xmlChar * token2,void * data)5612*7c568831SAndroid Build Coastguard Worker xmlAutomataNewNegTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
5613*7c568831SAndroid Build Coastguard Worker 		       xmlAutomataStatePtr to, const xmlChar *token,
5614*7c568831SAndroid Build Coastguard Worker 		       const xmlChar *token2, void *data) {
5615*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
5616*7c568831SAndroid Build Coastguard Worker     xmlChar err_msg[200];
5617*7c568831SAndroid Build Coastguard Worker 
5618*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (token == NULL))
5619*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5620*7c568831SAndroid Build Coastguard Worker     atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5621*7c568831SAndroid Build Coastguard Worker     if (atom == NULL)
5622*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5623*7c568831SAndroid Build Coastguard Worker     atom->data = data;
5624*7c568831SAndroid Build Coastguard Worker     atom->neg = 1;
5625*7c568831SAndroid Build Coastguard Worker     if ((token2 == NULL) || (*token2 == 0)) {
5626*7c568831SAndroid Build Coastguard Worker 	atom->valuep = xmlStrdup(token);
5627*7c568831SAndroid Build Coastguard Worker     } else {
5628*7c568831SAndroid Build Coastguard Worker 	int lenn, lenp;
5629*7c568831SAndroid Build Coastguard Worker 	xmlChar *str;
5630*7c568831SAndroid Build Coastguard Worker 
5631*7c568831SAndroid Build Coastguard Worker 	lenn = strlen((char *) token2);
5632*7c568831SAndroid Build Coastguard Worker 	lenp = strlen((char *) token);
5633*7c568831SAndroid Build Coastguard Worker 
5634*7c568831SAndroid Build Coastguard Worker 	str = xmlMalloc(lenn + lenp + 2);
5635*7c568831SAndroid Build Coastguard Worker 	if (str == NULL) {
5636*7c568831SAndroid Build Coastguard Worker 	    xmlRegFreeAtom(atom);
5637*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
5638*7c568831SAndroid Build Coastguard Worker 	}
5639*7c568831SAndroid Build Coastguard Worker 	memcpy(&str[0], token, lenp);
5640*7c568831SAndroid Build Coastguard Worker 	str[lenp] = '|';
5641*7c568831SAndroid Build Coastguard Worker 	memcpy(&str[lenp + 1], token2, lenn);
5642*7c568831SAndroid Build Coastguard Worker 	str[lenn + lenp + 1] = 0;
5643*7c568831SAndroid Build Coastguard Worker 
5644*7c568831SAndroid Build Coastguard Worker 	atom->valuep = str;
5645*7c568831SAndroid Build Coastguard Worker     }
5646*7c568831SAndroid Build Coastguard Worker     snprintf((char *) err_msg, 199, "not %s", (const char *) atom->valuep);
5647*7c568831SAndroid Build Coastguard Worker     err_msg[199] = 0;
5648*7c568831SAndroid Build Coastguard Worker     atom->valuep2 = xmlStrdup(err_msg);
5649*7c568831SAndroid Build Coastguard Worker 
5650*7c568831SAndroid Build Coastguard Worker     if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
5651*7c568831SAndroid Build Coastguard Worker         xmlRegFreeAtom(atom);
5652*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5653*7c568831SAndroid Build Coastguard Worker     }
5654*7c568831SAndroid Build Coastguard Worker     am->negs++;
5655*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
5656*7c568831SAndroid Build Coastguard Worker 	return(am->state);
5657*7c568831SAndroid Build Coastguard Worker     return(to);
5658*7c568831SAndroid Build Coastguard Worker }
5659*7c568831SAndroid Build Coastguard Worker 
5660*7c568831SAndroid Build Coastguard Worker /**
5661*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewCountTrans2:
5662*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5663*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
5664*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
5665*7c568831SAndroid Build Coastguard Worker  * @token: the input string associated to that transition
5666*7c568831SAndroid Build Coastguard Worker  * @token2: the second input string associated to that transition
5667*7c568831SAndroid Build Coastguard Worker  * @min:  the minimum successive occurrences of token
5668*7c568831SAndroid Build Coastguard Worker  * @max:  the maximum successive occurrences of token
5669*7c568831SAndroid Build Coastguard Worker  * @data:  data associated to the transition
5670*7c568831SAndroid Build Coastguard Worker  *
5671*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
5672*7c568831SAndroid Build Coastguard Worker  * and then adds a transition from the @from state to the target state
5673*7c568831SAndroid Build Coastguard Worker  * activated by a succession of input of value @token and @token2 and
5674*7c568831SAndroid Build Coastguard Worker  * whose number is between @min and @max
5675*7c568831SAndroid Build Coastguard Worker  *
5676*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
5677*7c568831SAndroid Build Coastguard Worker  */
5678*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewCountTrans2(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,const xmlChar * token,const xmlChar * token2,int min,int max,void * data)5679*7c568831SAndroid Build Coastguard Worker xmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
5680*7c568831SAndroid Build Coastguard Worker 			 xmlAutomataStatePtr to, const xmlChar *token,
5681*7c568831SAndroid Build Coastguard Worker 			 const xmlChar *token2,
5682*7c568831SAndroid Build Coastguard Worker 			 int min, int max, void *data) {
5683*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
5684*7c568831SAndroid Build Coastguard Worker     int counter;
5685*7c568831SAndroid Build Coastguard Worker 
5686*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (token == NULL))
5687*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5688*7c568831SAndroid Build Coastguard Worker     if (min < 0)
5689*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5690*7c568831SAndroid Build Coastguard Worker     if ((max < min) || (max < 1))
5691*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5692*7c568831SAndroid Build Coastguard Worker     atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5693*7c568831SAndroid Build Coastguard Worker     if (atom == NULL)
5694*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5695*7c568831SAndroid Build Coastguard Worker     if ((token2 == NULL) || (*token2 == 0)) {
5696*7c568831SAndroid Build Coastguard Worker 	atom->valuep = xmlStrdup(token);
5697*7c568831SAndroid Build Coastguard Worker         if (atom->valuep == NULL)
5698*7c568831SAndroid Build Coastguard Worker             goto error;
5699*7c568831SAndroid Build Coastguard Worker     } else {
5700*7c568831SAndroid Build Coastguard Worker 	int lenn, lenp;
5701*7c568831SAndroid Build Coastguard Worker 	xmlChar *str;
5702*7c568831SAndroid Build Coastguard Worker 
5703*7c568831SAndroid Build Coastguard Worker 	lenn = strlen((char *) token2);
5704*7c568831SAndroid Build Coastguard Worker 	lenp = strlen((char *) token);
5705*7c568831SAndroid Build Coastguard Worker 
5706*7c568831SAndroid Build Coastguard Worker 	str = xmlMalloc(lenn + lenp + 2);
5707*7c568831SAndroid Build Coastguard Worker 	if (str == NULL)
5708*7c568831SAndroid Build Coastguard Worker 	    goto error;
5709*7c568831SAndroid Build Coastguard Worker 	memcpy(&str[0], token, lenp);
5710*7c568831SAndroid Build Coastguard Worker 	str[lenp] = '|';
5711*7c568831SAndroid Build Coastguard Worker 	memcpy(&str[lenp + 1], token2, lenn);
5712*7c568831SAndroid Build Coastguard Worker 	str[lenn + lenp + 1] = 0;
5713*7c568831SAndroid Build Coastguard Worker 
5714*7c568831SAndroid Build Coastguard Worker 	atom->valuep = str;
5715*7c568831SAndroid Build Coastguard Worker     }
5716*7c568831SAndroid Build Coastguard Worker     atom->data = data;
5717*7c568831SAndroid Build Coastguard Worker     if (min == 0)
5718*7c568831SAndroid Build Coastguard Worker 	atom->min = 1;
5719*7c568831SAndroid Build Coastguard Worker     else
5720*7c568831SAndroid Build Coastguard Worker 	atom->min = min;
5721*7c568831SAndroid Build Coastguard Worker     atom->max = max;
5722*7c568831SAndroid Build Coastguard Worker 
5723*7c568831SAndroid Build Coastguard Worker     /*
5724*7c568831SAndroid Build Coastguard Worker      * associate a counter to the transition.
5725*7c568831SAndroid Build Coastguard Worker      */
5726*7c568831SAndroid Build Coastguard Worker     counter = xmlRegGetCounter(am);
5727*7c568831SAndroid Build Coastguard Worker     if (counter < 0)
5728*7c568831SAndroid Build Coastguard Worker         goto error;
5729*7c568831SAndroid Build Coastguard Worker     am->counters[counter].min = min;
5730*7c568831SAndroid Build Coastguard Worker     am->counters[counter].max = max;
5731*7c568831SAndroid Build Coastguard Worker 
5732*7c568831SAndroid Build Coastguard Worker     /* xmlFAGenerateTransitions(am, from, to, atom); */
5733*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
5734*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(am);
5735*7c568831SAndroid Build Coastguard Worker         if (to == NULL)
5736*7c568831SAndroid Build Coastguard Worker             goto error;
5737*7c568831SAndroid Build Coastguard Worker     }
5738*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
5739*7c568831SAndroid Build Coastguard Worker     if (xmlRegAtomPush(am, atom) < 0)
5740*7c568831SAndroid Build Coastguard Worker         goto error;
5741*7c568831SAndroid Build Coastguard Worker     am->state = to;
5742*7c568831SAndroid Build Coastguard Worker 
5743*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
5744*7c568831SAndroid Build Coastguard Worker 	to = am->state;
5745*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
5746*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5747*7c568831SAndroid Build Coastguard Worker     if (min == 0)
5748*7c568831SAndroid Build Coastguard Worker 	xmlFAGenerateEpsilonTransition(am, from, to);
5749*7c568831SAndroid Build Coastguard Worker     return(to);
5750*7c568831SAndroid Build Coastguard Worker 
5751*7c568831SAndroid Build Coastguard Worker error:
5752*7c568831SAndroid Build Coastguard Worker     xmlRegFreeAtom(atom);
5753*7c568831SAndroid Build Coastguard Worker     return(NULL);
5754*7c568831SAndroid Build Coastguard Worker }
5755*7c568831SAndroid Build Coastguard Worker 
5756*7c568831SAndroid Build Coastguard Worker /**
5757*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewCountTrans:
5758*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5759*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
5760*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
5761*7c568831SAndroid Build Coastguard Worker  * @token: the input string associated to that transition
5762*7c568831SAndroid Build Coastguard Worker  * @min:  the minimum successive occurrences of token
5763*7c568831SAndroid Build Coastguard Worker  * @max:  the maximum successive occurrences of token
5764*7c568831SAndroid Build Coastguard Worker  * @data:  data associated to the transition
5765*7c568831SAndroid Build Coastguard Worker  *
5766*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
5767*7c568831SAndroid Build Coastguard Worker  * and then adds a transition from the @from state to the target state
5768*7c568831SAndroid Build Coastguard Worker  * activated by a succession of input of value @token and whose number
5769*7c568831SAndroid Build Coastguard Worker  * is between @min and @max
5770*7c568831SAndroid Build Coastguard Worker  *
5771*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
5772*7c568831SAndroid Build Coastguard Worker  */
5773*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewCountTrans(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,const xmlChar * token,int min,int max,void * data)5774*7c568831SAndroid Build Coastguard Worker xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
5775*7c568831SAndroid Build Coastguard Worker 			 xmlAutomataStatePtr to, const xmlChar *token,
5776*7c568831SAndroid Build Coastguard Worker 			 int min, int max, void *data) {
5777*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
5778*7c568831SAndroid Build Coastguard Worker     int counter;
5779*7c568831SAndroid Build Coastguard Worker 
5780*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (token == NULL))
5781*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5782*7c568831SAndroid Build Coastguard Worker     if (min < 0)
5783*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5784*7c568831SAndroid Build Coastguard Worker     if ((max < min) || (max < 1))
5785*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5786*7c568831SAndroid Build Coastguard Worker     atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5787*7c568831SAndroid Build Coastguard Worker     if (atom == NULL)
5788*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5789*7c568831SAndroid Build Coastguard Worker     atom->valuep = xmlStrdup(token);
5790*7c568831SAndroid Build Coastguard Worker     if (atom->valuep == NULL)
5791*7c568831SAndroid Build Coastguard Worker         goto error;
5792*7c568831SAndroid Build Coastguard Worker     atom->data = data;
5793*7c568831SAndroid Build Coastguard Worker     if (min == 0)
5794*7c568831SAndroid Build Coastguard Worker 	atom->min = 1;
5795*7c568831SAndroid Build Coastguard Worker     else
5796*7c568831SAndroid Build Coastguard Worker 	atom->min = min;
5797*7c568831SAndroid Build Coastguard Worker     atom->max = max;
5798*7c568831SAndroid Build Coastguard Worker 
5799*7c568831SAndroid Build Coastguard Worker     /*
5800*7c568831SAndroid Build Coastguard Worker      * associate a counter to the transition.
5801*7c568831SAndroid Build Coastguard Worker      */
5802*7c568831SAndroid Build Coastguard Worker     counter = xmlRegGetCounter(am);
5803*7c568831SAndroid Build Coastguard Worker     if (counter < 0)
5804*7c568831SAndroid Build Coastguard Worker         goto error;
5805*7c568831SAndroid Build Coastguard Worker     am->counters[counter].min = min;
5806*7c568831SAndroid Build Coastguard Worker     am->counters[counter].max = max;
5807*7c568831SAndroid Build Coastguard Worker 
5808*7c568831SAndroid Build Coastguard Worker     /* xmlFAGenerateTransitions(am, from, to, atom); */
5809*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
5810*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(am);
5811*7c568831SAndroid Build Coastguard Worker         if (to == NULL)
5812*7c568831SAndroid Build Coastguard Worker             goto error;
5813*7c568831SAndroid Build Coastguard Worker     }
5814*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
5815*7c568831SAndroid Build Coastguard Worker     if (xmlRegAtomPush(am, atom) < 0)
5816*7c568831SAndroid Build Coastguard Worker         goto error;
5817*7c568831SAndroid Build Coastguard Worker     am->state = to;
5818*7c568831SAndroid Build Coastguard Worker 
5819*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
5820*7c568831SAndroid Build Coastguard Worker 	to = am->state;
5821*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
5822*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5823*7c568831SAndroid Build Coastguard Worker     if (min == 0)
5824*7c568831SAndroid Build Coastguard Worker 	xmlFAGenerateEpsilonTransition(am, from, to);
5825*7c568831SAndroid Build Coastguard Worker     return(to);
5826*7c568831SAndroid Build Coastguard Worker 
5827*7c568831SAndroid Build Coastguard Worker error:
5828*7c568831SAndroid Build Coastguard Worker     xmlRegFreeAtom(atom);
5829*7c568831SAndroid Build Coastguard Worker     return(NULL);
5830*7c568831SAndroid Build Coastguard Worker }
5831*7c568831SAndroid Build Coastguard Worker 
5832*7c568831SAndroid Build Coastguard Worker /**
5833*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewOnceTrans2:
5834*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5835*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
5836*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
5837*7c568831SAndroid Build Coastguard Worker  * @token: the input string associated to that transition
5838*7c568831SAndroid Build Coastguard Worker  * @token2: the second input string associated to that transition
5839*7c568831SAndroid Build Coastguard Worker  * @min:  the minimum successive occurrences of token
5840*7c568831SAndroid Build Coastguard Worker  * @max:  the maximum successive occurrences of token
5841*7c568831SAndroid Build Coastguard Worker  * @data:  data associated to the transition
5842*7c568831SAndroid Build Coastguard Worker  *
5843*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
5844*7c568831SAndroid Build Coastguard Worker  * and then adds a transition from the @from state to the target state
5845*7c568831SAndroid Build Coastguard Worker  * activated by a succession of input of value @token and @token2 and whose
5846*7c568831SAndroid Build Coastguard Worker  * number is between @min and @max, moreover that transition can only be
5847*7c568831SAndroid Build Coastguard Worker  * crossed once.
5848*7c568831SAndroid Build Coastguard Worker  *
5849*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
5850*7c568831SAndroid Build Coastguard Worker  */
5851*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewOnceTrans2(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,const xmlChar * token,const xmlChar * token2,int min,int max,void * data)5852*7c568831SAndroid Build Coastguard Worker xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
5853*7c568831SAndroid Build Coastguard Worker 			 xmlAutomataStatePtr to, const xmlChar *token,
5854*7c568831SAndroid Build Coastguard Worker 			 const xmlChar *token2,
5855*7c568831SAndroid Build Coastguard Worker 			 int min, int max, void *data) {
5856*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
5857*7c568831SAndroid Build Coastguard Worker     int counter;
5858*7c568831SAndroid Build Coastguard Worker 
5859*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (token == NULL))
5860*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5861*7c568831SAndroid Build Coastguard Worker     if (min < 1)
5862*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5863*7c568831SAndroid Build Coastguard Worker     if (max < min)
5864*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5865*7c568831SAndroid Build Coastguard Worker     atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5866*7c568831SAndroid Build Coastguard Worker     if (atom == NULL)
5867*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5868*7c568831SAndroid Build Coastguard Worker     if ((token2 == NULL) || (*token2 == 0)) {
5869*7c568831SAndroid Build Coastguard Worker 	atom->valuep = xmlStrdup(token);
5870*7c568831SAndroid Build Coastguard Worker         if (atom->valuep == NULL)
5871*7c568831SAndroid Build Coastguard Worker             goto error;
5872*7c568831SAndroid Build Coastguard Worker     } else {
5873*7c568831SAndroid Build Coastguard Worker 	int lenn, lenp;
5874*7c568831SAndroid Build Coastguard Worker 	xmlChar *str;
5875*7c568831SAndroid Build Coastguard Worker 
5876*7c568831SAndroid Build Coastguard Worker 	lenn = strlen((char *) token2);
5877*7c568831SAndroid Build Coastguard Worker 	lenp = strlen((char *) token);
5878*7c568831SAndroid Build Coastguard Worker 
5879*7c568831SAndroid Build Coastguard Worker 	str = xmlMalloc(lenn + lenp + 2);
5880*7c568831SAndroid Build Coastguard Worker 	if (str == NULL)
5881*7c568831SAndroid Build Coastguard Worker 	    goto error;
5882*7c568831SAndroid Build Coastguard Worker 	memcpy(&str[0], token, lenp);
5883*7c568831SAndroid Build Coastguard Worker 	str[lenp] = '|';
5884*7c568831SAndroid Build Coastguard Worker 	memcpy(&str[lenp + 1], token2, lenn);
5885*7c568831SAndroid Build Coastguard Worker 	str[lenn + lenp + 1] = 0;
5886*7c568831SAndroid Build Coastguard Worker 
5887*7c568831SAndroid Build Coastguard Worker 	atom->valuep = str;
5888*7c568831SAndroid Build Coastguard Worker     }
5889*7c568831SAndroid Build Coastguard Worker     atom->data = data;
5890*7c568831SAndroid Build Coastguard Worker     atom->quant = XML_REGEXP_QUANT_ONCEONLY;
5891*7c568831SAndroid Build Coastguard Worker     atom->min = min;
5892*7c568831SAndroid Build Coastguard Worker     atom->max = max;
5893*7c568831SAndroid Build Coastguard Worker     /*
5894*7c568831SAndroid Build Coastguard Worker      * associate a counter to the transition.
5895*7c568831SAndroid Build Coastguard Worker      */
5896*7c568831SAndroid Build Coastguard Worker     counter = xmlRegGetCounter(am);
5897*7c568831SAndroid Build Coastguard Worker     if (counter < 0)
5898*7c568831SAndroid Build Coastguard Worker         goto error;
5899*7c568831SAndroid Build Coastguard Worker     am->counters[counter].min = 1;
5900*7c568831SAndroid Build Coastguard Worker     am->counters[counter].max = 1;
5901*7c568831SAndroid Build Coastguard Worker 
5902*7c568831SAndroid Build Coastguard Worker     /* xmlFAGenerateTransitions(am, from, to, atom); */
5903*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
5904*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(am);
5905*7c568831SAndroid Build Coastguard Worker         if (to == NULL)
5906*7c568831SAndroid Build Coastguard Worker             goto error;
5907*7c568831SAndroid Build Coastguard Worker     }
5908*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
5909*7c568831SAndroid Build Coastguard Worker     if (xmlRegAtomPush(am, atom) < 0)
5910*7c568831SAndroid Build Coastguard Worker         goto error;
5911*7c568831SAndroid Build Coastguard Worker     am->state = to;
5912*7c568831SAndroid Build Coastguard Worker     return(to);
5913*7c568831SAndroid Build Coastguard Worker 
5914*7c568831SAndroid Build Coastguard Worker error:
5915*7c568831SAndroid Build Coastguard Worker     xmlRegFreeAtom(atom);
5916*7c568831SAndroid Build Coastguard Worker     return(NULL);
5917*7c568831SAndroid Build Coastguard Worker }
5918*7c568831SAndroid Build Coastguard Worker 
5919*7c568831SAndroid Build Coastguard Worker 
5920*7c568831SAndroid Build Coastguard Worker 
5921*7c568831SAndroid Build Coastguard Worker /**
5922*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewOnceTrans:
5923*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5924*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
5925*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
5926*7c568831SAndroid Build Coastguard Worker  * @token: the input string associated to that transition
5927*7c568831SAndroid Build Coastguard Worker  * @min:  the minimum successive occurrences of token
5928*7c568831SAndroid Build Coastguard Worker  * @max:  the maximum successive occurrences of token
5929*7c568831SAndroid Build Coastguard Worker  * @data:  data associated to the transition
5930*7c568831SAndroid Build Coastguard Worker  *
5931*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
5932*7c568831SAndroid Build Coastguard Worker  * and then adds a transition from the @from state to the target state
5933*7c568831SAndroid Build Coastguard Worker  * activated by a succession of input of value @token and whose number
5934*7c568831SAndroid Build Coastguard Worker  * is between @min and @max, moreover that transition can only be crossed
5935*7c568831SAndroid Build Coastguard Worker  * once.
5936*7c568831SAndroid Build Coastguard Worker  *
5937*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
5938*7c568831SAndroid Build Coastguard Worker  */
5939*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewOnceTrans(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,const xmlChar * token,int min,int max,void * data)5940*7c568831SAndroid Build Coastguard Worker xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
5941*7c568831SAndroid Build Coastguard Worker 			 xmlAutomataStatePtr to, const xmlChar *token,
5942*7c568831SAndroid Build Coastguard Worker 			 int min, int max, void *data) {
5943*7c568831SAndroid Build Coastguard Worker     xmlRegAtomPtr atom;
5944*7c568831SAndroid Build Coastguard Worker     int counter;
5945*7c568831SAndroid Build Coastguard Worker 
5946*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (token == NULL))
5947*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5948*7c568831SAndroid Build Coastguard Worker     if (min < 1)
5949*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5950*7c568831SAndroid Build Coastguard Worker     if (max < min)
5951*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5952*7c568831SAndroid Build Coastguard Worker     atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5953*7c568831SAndroid Build Coastguard Worker     if (atom == NULL)
5954*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5955*7c568831SAndroid Build Coastguard Worker     atom->valuep = xmlStrdup(token);
5956*7c568831SAndroid Build Coastguard Worker     atom->data = data;
5957*7c568831SAndroid Build Coastguard Worker     atom->quant = XML_REGEXP_QUANT_ONCEONLY;
5958*7c568831SAndroid Build Coastguard Worker     atom->min = min;
5959*7c568831SAndroid Build Coastguard Worker     atom->max = max;
5960*7c568831SAndroid Build Coastguard Worker     /*
5961*7c568831SAndroid Build Coastguard Worker      * associate a counter to the transition.
5962*7c568831SAndroid Build Coastguard Worker      */
5963*7c568831SAndroid Build Coastguard Worker     counter = xmlRegGetCounter(am);
5964*7c568831SAndroid Build Coastguard Worker     if (counter < 0)
5965*7c568831SAndroid Build Coastguard Worker         goto error;
5966*7c568831SAndroid Build Coastguard Worker     am->counters[counter].min = 1;
5967*7c568831SAndroid Build Coastguard Worker     am->counters[counter].max = 1;
5968*7c568831SAndroid Build Coastguard Worker 
5969*7c568831SAndroid Build Coastguard Worker     /* xmlFAGenerateTransitions(am, from, to, atom); */
5970*7c568831SAndroid Build Coastguard Worker     if (to == NULL) {
5971*7c568831SAndroid Build Coastguard Worker 	to = xmlRegStatePush(am);
5972*7c568831SAndroid Build Coastguard Worker         if (to == NULL)
5973*7c568831SAndroid Build Coastguard Worker             goto error;
5974*7c568831SAndroid Build Coastguard Worker     }
5975*7c568831SAndroid Build Coastguard Worker     xmlRegStateAddTrans(am, from, atom, to, counter, -1);
5976*7c568831SAndroid Build Coastguard Worker     if (xmlRegAtomPush(am, atom) < 0)
5977*7c568831SAndroid Build Coastguard Worker         goto error;
5978*7c568831SAndroid Build Coastguard Worker     am->state = to;
5979*7c568831SAndroid Build Coastguard Worker     return(to);
5980*7c568831SAndroid Build Coastguard Worker 
5981*7c568831SAndroid Build Coastguard Worker error:
5982*7c568831SAndroid Build Coastguard Worker     xmlRegFreeAtom(atom);
5983*7c568831SAndroid Build Coastguard Worker     return(NULL);
5984*7c568831SAndroid Build Coastguard Worker }
5985*7c568831SAndroid Build Coastguard Worker 
5986*7c568831SAndroid Build Coastguard Worker /**
5987*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewState:
5988*7c568831SAndroid Build Coastguard Worker  * @am: an automata
5989*7c568831SAndroid Build Coastguard Worker  *
5990*7c568831SAndroid Build Coastguard Worker  * Create a new disconnected state in the automata
5991*7c568831SAndroid Build Coastguard Worker  *
5992*7c568831SAndroid Build Coastguard Worker  * Returns the new state or NULL in case of error
5993*7c568831SAndroid Build Coastguard Worker  */
5994*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewState(xmlAutomataPtr am)5995*7c568831SAndroid Build Coastguard Worker xmlAutomataNewState(xmlAutomataPtr am) {
5996*7c568831SAndroid Build Coastguard Worker     if (am == NULL)
5997*7c568831SAndroid Build Coastguard Worker 	return(NULL);
5998*7c568831SAndroid Build Coastguard Worker     return(xmlRegStatePush(am));
5999*7c568831SAndroid Build Coastguard Worker }
6000*7c568831SAndroid Build Coastguard Worker 
6001*7c568831SAndroid Build Coastguard Worker /**
6002*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewEpsilon:
6003*7c568831SAndroid Build Coastguard Worker  * @am: an automata
6004*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
6005*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
6006*7c568831SAndroid Build Coastguard Worker  *
6007*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
6008*7c568831SAndroid Build Coastguard Worker  * and then adds an epsilon transition from the @from state to the
6009*7c568831SAndroid Build Coastguard Worker  * target state
6010*7c568831SAndroid Build Coastguard Worker  *
6011*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
6012*7c568831SAndroid Build Coastguard Worker  */
6013*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewEpsilon(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to)6014*7c568831SAndroid Build Coastguard Worker xmlAutomataNewEpsilon(xmlAutomataPtr am, xmlAutomataStatePtr from,
6015*7c568831SAndroid Build Coastguard Worker 		      xmlAutomataStatePtr to) {
6016*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL))
6017*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6018*7c568831SAndroid Build Coastguard Worker     xmlFAGenerateEpsilonTransition(am, from, to);
6019*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
6020*7c568831SAndroid Build Coastguard Worker 	return(am->state);
6021*7c568831SAndroid Build Coastguard Worker     return(to);
6022*7c568831SAndroid Build Coastguard Worker }
6023*7c568831SAndroid Build Coastguard Worker 
6024*7c568831SAndroid Build Coastguard Worker /**
6025*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewAllTrans:
6026*7c568831SAndroid Build Coastguard Worker  * @am: an automata
6027*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
6028*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
6029*7c568831SAndroid Build Coastguard Worker  * @lax: allow to transition if not all all transitions have been activated
6030*7c568831SAndroid Build Coastguard Worker  *
6031*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
6032*7c568831SAndroid Build Coastguard Worker  * and then adds a an ALL transition from the @from state to the
6033*7c568831SAndroid Build Coastguard Worker  * target state. That transition is an epsilon transition allowed only when
6034*7c568831SAndroid Build Coastguard Worker  * all transitions from the @from node have been activated.
6035*7c568831SAndroid Build Coastguard Worker  *
6036*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
6037*7c568831SAndroid Build Coastguard Worker  */
6038*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewAllTrans(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,int lax)6039*7c568831SAndroid Build Coastguard Worker xmlAutomataNewAllTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6040*7c568831SAndroid Build Coastguard Worker 		       xmlAutomataStatePtr to, int lax) {
6041*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL))
6042*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6043*7c568831SAndroid Build Coastguard Worker     xmlFAGenerateAllTransition(am, from, to, lax);
6044*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
6045*7c568831SAndroid Build Coastguard Worker 	return(am->state);
6046*7c568831SAndroid Build Coastguard Worker     return(to);
6047*7c568831SAndroid Build Coastguard Worker }
6048*7c568831SAndroid Build Coastguard Worker 
6049*7c568831SAndroid Build Coastguard Worker /**
6050*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewCounter:
6051*7c568831SAndroid Build Coastguard Worker  * @am: an automata
6052*7c568831SAndroid Build Coastguard Worker  * @min:  the minimal value on the counter
6053*7c568831SAndroid Build Coastguard Worker  * @max:  the maximal value on the counter
6054*7c568831SAndroid Build Coastguard Worker  *
6055*7c568831SAndroid Build Coastguard Worker  * Create a new counter
6056*7c568831SAndroid Build Coastguard Worker  *
6057*7c568831SAndroid Build Coastguard Worker  * Returns the counter number or -1 in case of error
6058*7c568831SAndroid Build Coastguard Worker  */
6059*7c568831SAndroid Build Coastguard Worker int
xmlAutomataNewCounter(xmlAutomataPtr am,int min,int max)6060*7c568831SAndroid Build Coastguard Worker xmlAutomataNewCounter(xmlAutomataPtr am, int min, int max) {
6061*7c568831SAndroid Build Coastguard Worker     int ret;
6062*7c568831SAndroid Build Coastguard Worker 
6063*7c568831SAndroid Build Coastguard Worker     if (am == NULL)
6064*7c568831SAndroid Build Coastguard Worker 	return(-1);
6065*7c568831SAndroid Build Coastguard Worker 
6066*7c568831SAndroid Build Coastguard Worker     ret = xmlRegGetCounter(am);
6067*7c568831SAndroid Build Coastguard Worker     if (ret < 0)
6068*7c568831SAndroid Build Coastguard Worker 	return(-1);
6069*7c568831SAndroid Build Coastguard Worker     am->counters[ret].min = min;
6070*7c568831SAndroid Build Coastguard Worker     am->counters[ret].max = max;
6071*7c568831SAndroid Build Coastguard Worker     return(ret);
6072*7c568831SAndroid Build Coastguard Worker }
6073*7c568831SAndroid Build Coastguard Worker 
6074*7c568831SAndroid Build Coastguard Worker /**
6075*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewCountedTrans:
6076*7c568831SAndroid Build Coastguard Worker  * @am: an automata
6077*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
6078*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
6079*7c568831SAndroid Build Coastguard Worker  * @counter: the counter associated to that transition
6080*7c568831SAndroid Build Coastguard Worker  *
6081*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
6082*7c568831SAndroid Build Coastguard Worker  * and then adds an epsilon transition from the @from state to the target state
6083*7c568831SAndroid Build Coastguard Worker  * which will increment the counter provided
6084*7c568831SAndroid Build Coastguard Worker  *
6085*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
6086*7c568831SAndroid Build Coastguard Worker  */
6087*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewCountedTrans(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,int counter)6088*7c568831SAndroid Build Coastguard Worker xmlAutomataNewCountedTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6089*7c568831SAndroid Build Coastguard Worker 		xmlAutomataStatePtr to, int counter) {
6090*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (counter < 0))
6091*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6092*7c568831SAndroid Build Coastguard Worker     xmlFAGenerateCountedEpsilonTransition(am, from, to, counter);
6093*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
6094*7c568831SAndroid Build Coastguard Worker 	return(am->state);
6095*7c568831SAndroid Build Coastguard Worker     return(to);
6096*7c568831SAndroid Build Coastguard Worker }
6097*7c568831SAndroid Build Coastguard Worker 
6098*7c568831SAndroid Build Coastguard Worker /**
6099*7c568831SAndroid Build Coastguard Worker  * xmlAutomataNewCounterTrans:
6100*7c568831SAndroid Build Coastguard Worker  * @am: an automata
6101*7c568831SAndroid Build Coastguard Worker  * @from: the starting point of the transition
6102*7c568831SAndroid Build Coastguard Worker  * @to: the target point of the transition or NULL
6103*7c568831SAndroid Build Coastguard Worker  * @counter: the counter associated to that transition
6104*7c568831SAndroid Build Coastguard Worker  *
6105*7c568831SAndroid Build Coastguard Worker  * If @to is NULL, this creates first a new target state in the automata
6106*7c568831SAndroid Build Coastguard Worker  * and then adds an epsilon transition from the @from state to the target state
6107*7c568831SAndroid Build Coastguard Worker  * which will be allowed only if the counter is within the right range.
6108*7c568831SAndroid Build Coastguard Worker  *
6109*7c568831SAndroid Build Coastguard Worker  * Returns the target state or NULL in case of error
6110*7c568831SAndroid Build Coastguard Worker  */
6111*7c568831SAndroid Build Coastguard Worker xmlAutomataStatePtr
xmlAutomataNewCounterTrans(xmlAutomataPtr am,xmlAutomataStatePtr from,xmlAutomataStatePtr to,int counter)6112*7c568831SAndroid Build Coastguard Worker xmlAutomataNewCounterTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6113*7c568831SAndroid Build Coastguard Worker 		xmlAutomataStatePtr to, int counter) {
6114*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (from == NULL) || (counter < 0))
6115*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6116*7c568831SAndroid Build Coastguard Worker     xmlFAGenerateCountedTransition(am, from, to, counter);
6117*7c568831SAndroid Build Coastguard Worker     if (to == NULL)
6118*7c568831SAndroid Build Coastguard Worker 	return(am->state);
6119*7c568831SAndroid Build Coastguard Worker     return(to);
6120*7c568831SAndroid Build Coastguard Worker }
6121*7c568831SAndroid Build Coastguard Worker 
6122*7c568831SAndroid Build Coastguard Worker /**
6123*7c568831SAndroid Build Coastguard Worker  * xmlAutomataCompile:
6124*7c568831SAndroid Build Coastguard Worker  * @am: an automata
6125*7c568831SAndroid Build Coastguard Worker  *
6126*7c568831SAndroid Build Coastguard Worker  * Compile the automata into a Reg Exp ready for being executed.
6127*7c568831SAndroid Build Coastguard Worker  * The automata should be free after this point.
6128*7c568831SAndroid Build Coastguard Worker  *
6129*7c568831SAndroid Build Coastguard Worker  * Returns the compiled regexp or NULL in case of error
6130*7c568831SAndroid Build Coastguard Worker  */
6131*7c568831SAndroid Build Coastguard Worker xmlRegexpPtr
xmlAutomataCompile(xmlAutomataPtr am)6132*7c568831SAndroid Build Coastguard Worker xmlAutomataCompile(xmlAutomataPtr am) {
6133*7c568831SAndroid Build Coastguard Worker     xmlRegexpPtr ret;
6134*7c568831SAndroid Build Coastguard Worker 
6135*7c568831SAndroid Build Coastguard Worker     if ((am == NULL) || (am->error != 0)) return(NULL);
6136*7c568831SAndroid Build Coastguard Worker     xmlFAEliminateEpsilonTransitions(am);
6137*7c568831SAndroid Build Coastguard Worker     if (am->error != 0)
6138*7c568831SAndroid Build Coastguard Worker         return(NULL);
6139*7c568831SAndroid Build Coastguard Worker     /* xmlFAComputesDeterminism(am); */
6140*7c568831SAndroid Build Coastguard Worker     ret = xmlRegEpxFromParse(am);
6141*7c568831SAndroid Build Coastguard Worker 
6142*7c568831SAndroid Build Coastguard Worker     return(ret);
6143*7c568831SAndroid Build Coastguard Worker }
6144*7c568831SAndroid Build Coastguard Worker 
6145*7c568831SAndroid Build Coastguard Worker /**
6146*7c568831SAndroid Build Coastguard Worker  * xmlAutomataIsDeterminist:
6147*7c568831SAndroid Build Coastguard Worker  * @am: an automata
6148*7c568831SAndroid Build Coastguard Worker  *
6149*7c568831SAndroid Build Coastguard Worker  * Checks if an automata is determinist.
6150*7c568831SAndroid Build Coastguard Worker  *
6151*7c568831SAndroid Build Coastguard Worker  * Returns 1 if true, 0 if not, and -1 in case of error
6152*7c568831SAndroid Build Coastguard Worker  */
6153*7c568831SAndroid Build Coastguard Worker int
xmlAutomataIsDeterminist(xmlAutomataPtr am)6154*7c568831SAndroid Build Coastguard Worker xmlAutomataIsDeterminist(xmlAutomataPtr am) {
6155*7c568831SAndroid Build Coastguard Worker     int ret;
6156*7c568831SAndroid Build Coastguard Worker 
6157*7c568831SAndroid Build Coastguard Worker     if (am == NULL)
6158*7c568831SAndroid Build Coastguard Worker 	return(-1);
6159*7c568831SAndroid Build Coastguard Worker 
6160*7c568831SAndroid Build Coastguard Worker     ret = xmlFAComputesDeterminism(am);
6161*7c568831SAndroid Build Coastguard Worker     return(ret);
6162*7c568831SAndroid Build Coastguard Worker }
6163*7c568831SAndroid Build Coastguard Worker 
6164*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_EXPR_ENABLED
6165*7c568831SAndroid Build Coastguard Worker /** DOC_DISABLE */
6166*7c568831SAndroid Build Coastguard Worker /************************************************************************
6167*7c568831SAndroid Build Coastguard Worker  *									*
6168*7c568831SAndroid Build Coastguard Worker  *		Formal Expression handling code				*
6169*7c568831SAndroid Build Coastguard Worker  *									*
6170*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
6171*7c568831SAndroid Build Coastguard Worker 
6172*7c568831SAndroid Build Coastguard Worker /*
6173*7c568831SAndroid Build Coastguard Worker  * Formal regular expression handling
6174*7c568831SAndroid Build Coastguard Worker  * Its goal is to do some formal work on content models
6175*7c568831SAndroid Build Coastguard Worker  */
6176*7c568831SAndroid Build Coastguard Worker 
6177*7c568831SAndroid Build Coastguard Worker /* expressions are used within a context */
6178*7c568831SAndroid Build Coastguard Worker typedef struct _xmlExpCtxt xmlExpCtxt;
6179*7c568831SAndroid Build Coastguard Worker typedef xmlExpCtxt *xmlExpCtxtPtr;
6180*7c568831SAndroid Build Coastguard Worker 
6181*7c568831SAndroid Build Coastguard Worker XMLPUBFUN void
6182*7c568831SAndroid Build Coastguard Worker 			xmlExpFreeCtxt	(xmlExpCtxtPtr ctxt);
6183*7c568831SAndroid Build Coastguard Worker XMLPUBFUN xmlExpCtxtPtr
6184*7c568831SAndroid Build Coastguard Worker 			xmlExpNewCtxt	(int maxNodes,
6185*7c568831SAndroid Build Coastguard Worker 					 xmlDictPtr dict);
6186*7c568831SAndroid Build Coastguard Worker 
6187*7c568831SAndroid Build Coastguard Worker XMLPUBFUN int
6188*7c568831SAndroid Build Coastguard Worker 			xmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt);
6189*7c568831SAndroid Build Coastguard Worker XMLPUBFUN int
6190*7c568831SAndroid Build Coastguard Worker 			xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt);
6191*7c568831SAndroid Build Coastguard Worker 
6192*7c568831SAndroid Build Coastguard Worker /* Expressions are trees but the tree is opaque */
6193*7c568831SAndroid Build Coastguard Worker typedef struct _xmlExpNode xmlExpNode;
6194*7c568831SAndroid Build Coastguard Worker typedef xmlExpNode *xmlExpNodePtr;
6195*7c568831SAndroid Build Coastguard Worker 
6196*7c568831SAndroid Build Coastguard Worker typedef enum {
6197*7c568831SAndroid Build Coastguard Worker     XML_EXP_EMPTY = 0,
6198*7c568831SAndroid Build Coastguard Worker     XML_EXP_FORBID = 1,
6199*7c568831SAndroid Build Coastguard Worker     XML_EXP_ATOM = 2,
6200*7c568831SAndroid Build Coastguard Worker     XML_EXP_SEQ = 3,
6201*7c568831SAndroid Build Coastguard Worker     XML_EXP_OR = 4,
6202*7c568831SAndroid Build Coastguard Worker     XML_EXP_COUNT = 5
6203*7c568831SAndroid Build Coastguard Worker } xmlExpNodeType;
6204*7c568831SAndroid Build Coastguard Worker 
6205*7c568831SAndroid Build Coastguard Worker /*
6206*7c568831SAndroid Build Coastguard Worker  * 2 core expressions shared by all for the empty language set
6207*7c568831SAndroid Build Coastguard Worker  * and for the set with just the empty token
6208*7c568831SAndroid Build Coastguard Worker  */
6209*7c568831SAndroid Build Coastguard Worker XMLPUBVAR xmlExpNodePtr forbiddenExp;
6210*7c568831SAndroid Build Coastguard Worker XMLPUBVAR xmlExpNodePtr emptyExp;
6211*7c568831SAndroid Build Coastguard Worker 
6212*7c568831SAndroid Build Coastguard Worker /*
6213*7c568831SAndroid Build Coastguard Worker  * Expressions are reference counted internally
6214*7c568831SAndroid Build Coastguard Worker  */
6215*7c568831SAndroid Build Coastguard Worker XMLPUBFUN void
6216*7c568831SAndroid Build Coastguard Worker 			xmlExpFree	(xmlExpCtxtPtr ctxt,
6217*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr expr);
6218*7c568831SAndroid Build Coastguard Worker XMLPUBFUN void
6219*7c568831SAndroid Build Coastguard Worker 			xmlExpRef	(xmlExpNodePtr expr);
6220*7c568831SAndroid Build Coastguard Worker 
6221*7c568831SAndroid Build Coastguard Worker /*
6222*7c568831SAndroid Build Coastguard Worker  * constructors can be either manual or from a string
6223*7c568831SAndroid Build Coastguard Worker  */
6224*7c568831SAndroid Build Coastguard Worker XMLPUBFUN xmlExpNodePtr
6225*7c568831SAndroid Build Coastguard Worker 			xmlExpParse	(xmlExpCtxtPtr ctxt,
6226*7c568831SAndroid Build Coastguard Worker 					 const char *expr);
6227*7c568831SAndroid Build Coastguard Worker XMLPUBFUN xmlExpNodePtr
6228*7c568831SAndroid Build Coastguard Worker 			xmlExpNewAtom	(xmlExpCtxtPtr ctxt,
6229*7c568831SAndroid Build Coastguard Worker 					 const xmlChar *name,
6230*7c568831SAndroid Build Coastguard Worker 					 int len);
6231*7c568831SAndroid Build Coastguard Worker XMLPUBFUN xmlExpNodePtr
6232*7c568831SAndroid Build Coastguard Worker 			xmlExpNewOr	(xmlExpCtxtPtr ctxt,
6233*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr left,
6234*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr right);
6235*7c568831SAndroid Build Coastguard Worker XMLPUBFUN xmlExpNodePtr
6236*7c568831SAndroid Build Coastguard Worker 			xmlExpNewSeq	(xmlExpCtxtPtr ctxt,
6237*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr left,
6238*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr right);
6239*7c568831SAndroid Build Coastguard Worker XMLPUBFUN xmlExpNodePtr
6240*7c568831SAndroid Build Coastguard Worker 			xmlExpNewRange	(xmlExpCtxtPtr ctxt,
6241*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr subset,
6242*7c568831SAndroid Build Coastguard Worker 					 int min,
6243*7c568831SAndroid Build Coastguard Worker 					 int max);
6244*7c568831SAndroid Build Coastguard Worker /*
6245*7c568831SAndroid Build Coastguard Worker  * The really interesting APIs
6246*7c568831SAndroid Build Coastguard Worker  */
6247*7c568831SAndroid Build Coastguard Worker XMLPUBFUN int
6248*7c568831SAndroid Build Coastguard Worker 			xmlExpIsNillable(xmlExpNodePtr expr);
6249*7c568831SAndroid Build Coastguard Worker XMLPUBFUN int
6250*7c568831SAndroid Build Coastguard Worker 			xmlExpMaxToken	(xmlExpNodePtr expr);
6251*7c568831SAndroid Build Coastguard Worker XMLPUBFUN int
6252*7c568831SAndroid Build Coastguard Worker 			xmlExpGetLanguage(xmlExpCtxtPtr ctxt,
6253*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr expr,
6254*7c568831SAndroid Build Coastguard Worker 					 const xmlChar**langList,
6255*7c568831SAndroid Build Coastguard Worker 					 int len);
6256*7c568831SAndroid Build Coastguard Worker XMLPUBFUN int
6257*7c568831SAndroid Build Coastguard Worker 			xmlExpGetStart	(xmlExpCtxtPtr ctxt,
6258*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr expr,
6259*7c568831SAndroid Build Coastguard Worker 					 const xmlChar**tokList,
6260*7c568831SAndroid Build Coastguard Worker 					 int len);
6261*7c568831SAndroid Build Coastguard Worker XMLPUBFUN xmlExpNodePtr
6262*7c568831SAndroid Build Coastguard Worker 			xmlExpStringDerive(xmlExpCtxtPtr ctxt,
6263*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr expr,
6264*7c568831SAndroid Build Coastguard Worker 					 const xmlChar *str,
6265*7c568831SAndroid Build Coastguard Worker 					 int len);
6266*7c568831SAndroid Build Coastguard Worker XMLPUBFUN xmlExpNodePtr
6267*7c568831SAndroid Build Coastguard Worker 			xmlExpExpDerive	(xmlExpCtxtPtr ctxt,
6268*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr expr,
6269*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr sub);
6270*7c568831SAndroid Build Coastguard Worker XMLPUBFUN int
6271*7c568831SAndroid Build Coastguard Worker 			xmlExpSubsume	(xmlExpCtxtPtr ctxt,
6272*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr expr,
6273*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr sub);
6274*7c568831SAndroid Build Coastguard Worker XMLPUBFUN void
6275*7c568831SAndroid Build Coastguard Worker 			xmlExpDump	(xmlBufferPtr buf,
6276*7c568831SAndroid Build Coastguard Worker 					 xmlExpNodePtr expr);
6277*7c568831SAndroid Build Coastguard Worker 
6278*7c568831SAndroid Build Coastguard Worker /************************************************************************
6279*7c568831SAndroid Build Coastguard Worker  *									*
6280*7c568831SAndroid Build Coastguard Worker  *		Expression handling context				*
6281*7c568831SAndroid Build Coastguard Worker  *									*
6282*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
6283*7c568831SAndroid Build Coastguard Worker 
6284*7c568831SAndroid Build Coastguard Worker struct _xmlExpCtxt {
6285*7c568831SAndroid Build Coastguard Worker     xmlDictPtr dict;
6286*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr *table;
6287*7c568831SAndroid Build Coastguard Worker     int size;
6288*7c568831SAndroid Build Coastguard Worker     int nbElems;
6289*7c568831SAndroid Build Coastguard Worker     int nb_nodes;
6290*7c568831SAndroid Build Coastguard Worker     int maxNodes;
6291*7c568831SAndroid Build Coastguard Worker     const char *expr;
6292*7c568831SAndroid Build Coastguard Worker     const char *cur;
6293*7c568831SAndroid Build Coastguard Worker     int nb_cons;
6294*7c568831SAndroid Build Coastguard Worker     int tabSize;
6295*7c568831SAndroid Build Coastguard Worker };
6296*7c568831SAndroid Build Coastguard Worker 
6297*7c568831SAndroid Build Coastguard Worker /**
6298*7c568831SAndroid Build Coastguard Worker  * xmlExpNewCtxt:
6299*7c568831SAndroid Build Coastguard Worker  * @maxNodes:  the maximum number of nodes
6300*7c568831SAndroid Build Coastguard Worker  * @dict:  optional dictionary to use internally
6301*7c568831SAndroid Build Coastguard Worker  *
6302*7c568831SAndroid Build Coastguard Worker  * Creates a new context for manipulating expressions
6303*7c568831SAndroid Build Coastguard Worker  *
6304*7c568831SAndroid Build Coastguard Worker  * Returns the context or NULL in case of error
6305*7c568831SAndroid Build Coastguard Worker  */
6306*7c568831SAndroid Build Coastguard Worker xmlExpCtxtPtr
xmlExpNewCtxt(int maxNodes,xmlDictPtr dict)6307*7c568831SAndroid Build Coastguard Worker xmlExpNewCtxt(int maxNodes, xmlDictPtr dict) {
6308*7c568831SAndroid Build Coastguard Worker     xmlExpCtxtPtr ret;
6309*7c568831SAndroid Build Coastguard Worker     int size = 256;
6310*7c568831SAndroid Build Coastguard Worker 
6311*7c568831SAndroid Build Coastguard Worker     if (maxNodes <= 4096)
6312*7c568831SAndroid Build Coastguard Worker         maxNodes = 4096;
6313*7c568831SAndroid Build Coastguard Worker 
6314*7c568831SAndroid Build Coastguard Worker     ret = (xmlExpCtxtPtr) xmlMalloc(sizeof(xmlExpCtxt));
6315*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
6316*7c568831SAndroid Build Coastguard Worker         return(NULL);
6317*7c568831SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlExpCtxt));
6318*7c568831SAndroid Build Coastguard Worker     ret->size = size;
6319*7c568831SAndroid Build Coastguard Worker     ret->nbElems = 0;
6320*7c568831SAndroid Build Coastguard Worker     ret->maxNodes = maxNodes;
6321*7c568831SAndroid Build Coastguard Worker     ret->table = xmlMalloc(size * sizeof(xmlExpNodePtr));
6322*7c568831SAndroid Build Coastguard Worker     if (ret->table == NULL) {
6323*7c568831SAndroid Build Coastguard Worker         xmlFree(ret);
6324*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6325*7c568831SAndroid Build Coastguard Worker     }
6326*7c568831SAndroid Build Coastguard Worker     memset(ret->table, 0, size * sizeof(xmlExpNodePtr));
6327*7c568831SAndroid Build Coastguard Worker     if (dict == NULL) {
6328*7c568831SAndroid Build Coastguard Worker         ret->dict = xmlDictCreate();
6329*7c568831SAndroid Build Coastguard Worker 	if (ret->dict == NULL) {
6330*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret->table);
6331*7c568831SAndroid Build Coastguard Worker 	    xmlFree(ret);
6332*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
6333*7c568831SAndroid Build Coastguard Worker 	}
6334*7c568831SAndroid Build Coastguard Worker     } else {
6335*7c568831SAndroid Build Coastguard Worker         ret->dict = dict;
6336*7c568831SAndroid Build Coastguard Worker 	xmlDictReference(ret->dict);
6337*7c568831SAndroid Build Coastguard Worker     }
6338*7c568831SAndroid Build Coastguard Worker     return(ret);
6339*7c568831SAndroid Build Coastguard Worker }
6340*7c568831SAndroid Build Coastguard Worker 
6341*7c568831SAndroid Build Coastguard Worker /**
6342*7c568831SAndroid Build Coastguard Worker  * xmlExpFreeCtxt:
6343*7c568831SAndroid Build Coastguard Worker  * @ctxt:  an expression context
6344*7c568831SAndroid Build Coastguard Worker  *
6345*7c568831SAndroid Build Coastguard Worker  * Free an expression context
6346*7c568831SAndroid Build Coastguard Worker  */
6347*7c568831SAndroid Build Coastguard Worker void
xmlExpFreeCtxt(xmlExpCtxtPtr ctxt)6348*7c568831SAndroid Build Coastguard Worker xmlExpFreeCtxt(xmlExpCtxtPtr ctxt) {
6349*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
6350*7c568831SAndroid Build Coastguard Worker         return;
6351*7c568831SAndroid Build Coastguard Worker     xmlDictFree(ctxt->dict);
6352*7c568831SAndroid Build Coastguard Worker     if (ctxt->table != NULL)
6353*7c568831SAndroid Build Coastguard Worker 	xmlFree(ctxt->table);
6354*7c568831SAndroid Build Coastguard Worker     xmlFree(ctxt);
6355*7c568831SAndroid Build Coastguard Worker }
6356*7c568831SAndroid Build Coastguard Worker 
6357*7c568831SAndroid Build Coastguard Worker /************************************************************************
6358*7c568831SAndroid Build Coastguard Worker  *									*
6359*7c568831SAndroid Build Coastguard Worker  *		Structure associated to an expression node		*
6360*7c568831SAndroid Build Coastguard Worker  *									*
6361*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
6362*7c568831SAndroid Build Coastguard Worker #define MAX_NODES 10000
6363*7c568831SAndroid Build Coastguard Worker 
6364*7c568831SAndroid Build Coastguard Worker /*
6365*7c568831SAndroid Build Coastguard Worker  * TODO:
6366*7c568831SAndroid Build Coastguard Worker  * - Wildcards
6367*7c568831SAndroid Build Coastguard Worker  * - public API for creation
6368*7c568831SAndroid Build Coastguard Worker  *
6369*7c568831SAndroid Build Coastguard Worker  * Started
6370*7c568831SAndroid Build Coastguard Worker  * - regression testing
6371*7c568831SAndroid Build Coastguard Worker  *
6372*7c568831SAndroid Build Coastguard Worker  * Done
6373*7c568831SAndroid Build Coastguard Worker  * - split into module and test tool
6374*7c568831SAndroid Build Coastguard Worker  * - memleaks
6375*7c568831SAndroid Build Coastguard Worker  */
6376*7c568831SAndroid Build Coastguard Worker 
6377*7c568831SAndroid Build Coastguard Worker typedef enum {
6378*7c568831SAndroid Build Coastguard Worker     XML_EXP_NILABLE = (1 << 0)
6379*7c568831SAndroid Build Coastguard Worker } xmlExpNodeInfo;
6380*7c568831SAndroid Build Coastguard Worker 
6381*7c568831SAndroid Build Coastguard Worker #define IS_NILLABLE(node) ((node)->info & XML_EXP_NILABLE)
6382*7c568831SAndroid Build Coastguard Worker 
6383*7c568831SAndroid Build Coastguard Worker struct _xmlExpNode {
6384*7c568831SAndroid Build Coastguard Worker     unsigned char type;/* xmlExpNodeType */
6385*7c568831SAndroid Build Coastguard Worker     unsigned char info;/* OR of xmlExpNodeInfo */
6386*7c568831SAndroid Build Coastguard Worker     unsigned short key;	/* the hash key */
6387*7c568831SAndroid Build Coastguard Worker     unsigned int ref;	/* The number of references */
6388*7c568831SAndroid Build Coastguard Worker     int c_max;		/* the maximum length it can consume */
6389*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr exp_left;
6390*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr next;/* the next node in the hash table or free list */
6391*7c568831SAndroid Build Coastguard Worker     union {
6392*7c568831SAndroid Build Coastguard Worker 	struct {
6393*7c568831SAndroid Build Coastguard Worker 	    int f_min;
6394*7c568831SAndroid Build Coastguard Worker 	    int f_max;
6395*7c568831SAndroid Build Coastguard Worker 	} count;
6396*7c568831SAndroid Build Coastguard Worker 	struct {
6397*7c568831SAndroid Build Coastguard Worker 	    xmlExpNodePtr f_right;
6398*7c568831SAndroid Build Coastguard Worker 	} children;
6399*7c568831SAndroid Build Coastguard Worker         const xmlChar *f_str;
6400*7c568831SAndroid Build Coastguard Worker     } field;
6401*7c568831SAndroid Build Coastguard Worker };
6402*7c568831SAndroid Build Coastguard Worker 
6403*7c568831SAndroid Build Coastguard Worker #define exp_min field.count.f_min
6404*7c568831SAndroid Build Coastguard Worker #define exp_max field.count.f_max
6405*7c568831SAndroid Build Coastguard Worker /* #define exp_left field.children.f_left */
6406*7c568831SAndroid Build Coastguard Worker #define exp_right field.children.f_right
6407*7c568831SAndroid Build Coastguard Worker #define exp_str field.f_str
6408*7c568831SAndroid Build Coastguard Worker 
6409*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr xmlExpNewNode(xmlExpCtxtPtr ctxt, xmlExpNodeType type);
6410*7c568831SAndroid Build Coastguard Worker static xmlExpNode forbiddenExpNode = {
6411*7c568831SAndroid Build Coastguard Worker     XML_EXP_FORBID, 0, 0, 0, 0, NULL, NULL, {{ 0, 0}}
6412*7c568831SAndroid Build Coastguard Worker };
6413*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr forbiddenExp = &forbiddenExpNode;
6414*7c568831SAndroid Build Coastguard Worker static xmlExpNode emptyExpNode = {
6415*7c568831SAndroid Build Coastguard Worker     XML_EXP_EMPTY, 1, 0, 0, 0, NULL, NULL, {{ 0, 0}}
6416*7c568831SAndroid Build Coastguard Worker };
6417*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr emptyExp = &emptyExpNode;
6418*7c568831SAndroid Build Coastguard Worker 
6419*7c568831SAndroid Build Coastguard Worker /************************************************************************
6420*7c568831SAndroid Build Coastguard Worker  *									*
6421*7c568831SAndroid Build Coastguard Worker  *  The custom hash table for unicity and canonicalization		*
6422*7c568831SAndroid Build Coastguard Worker  *  of sub-expressions pointers						*
6423*7c568831SAndroid Build Coastguard Worker  *									*
6424*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
6425*7c568831SAndroid Build Coastguard Worker /*
6426*7c568831SAndroid Build Coastguard Worker  * xmlExpHashNameComputeKey:
6427*7c568831SAndroid Build Coastguard Worker  * Calculate the hash key for a token
6428*7c568831SAndroid Build Coastguard Worker  */
6429*7c568831SAndroid Build Coastguard Worker static unsigned short
xmlExpHashNameComputeKey(const xmlChar * name)6430*7c568831SAndroid Build Coastguard Worker xmlExpHashNameComputeKey(const xmlChar *name) {
6431*7c568831SAndroid Build Coastguard Worker     unsigned short value = 0L;
6432*7c568831SAndroid Build Coastguard Worker     char ch;
6433*7c568831SAndroid Build Coastguard Worker 
6434*7c568831SAndroid Build Coastguard Worker     if (name != NULL) {
6435*7c568831SAndroid Build Coastguard Worker 	value += 30 * (*name);
6436*7c568831SAndroid Build Coastguard Worker 	while ((ch = *name++) != 0) {
6437*7c568831SAndroid Build Coastguard Worker 	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
6438*7c568831SAndroid Build Coastguard Worker 	}
6439*7c568831SAndroid Build Coastguard Worker     }
6440*7c568831SAndroid Build Coastguard Worker     return (value);
6441*7c568831SAndroid Build Coastguard Worker }
6442*7c568831SAndroid Build Coastguard Worker 
6443*7c568831SAndroid Build Coastguard Worker /*
6444*7c568831SAndroid Build Coastguard Worker  * xmlExpHashComputeKey:
6445*7c568831SAndroid Build Coastguard Worker  * Calculate the hash key for a compound expression
6446*7c568831SAndroid Build Coastguard Worker  */
6447*7c568831SAndroid Build Coastguard Worker static unsigned short
xmlExpHashComputeKey(xmlExpNodeType type,xmlExpNodePtr left,xmlExpNodePtr right)6448*7c568831SAndroid Build Coastguard Worker xmlExpHashComputeKey(xmlExpNodeType type, xmlExpNodePtr left,
6449*7c568831SAndroid Build Coastguard Worker                      xmlExpNodePtr right) {
6450*7c568831SAndroid Build Coastguard Worker     unsigned long value;
6451*7c568831SAndroid Build Coastguard Worker     unsigned short ret;
6452*7c568831SAndroid Build Coastguard Worker 
6453*7c568831SAndroid Build Coastguard Worker     switch (type) {
6454*7c568831SAndroid Build Coastguard Worker         case XML_EXP_SEQ:
6455*7c568831SAndroid Build Coastguard Worker 	    value = left->key;
6456*7c568831SAndroid Build Coastguard Worker 	    value += right->key;
6457*7c568831SAndroid Build Coastguard Worker 	    value *= 3;
6458*7c568831SAndroid Build Coastguard Worker 	    ret = (unsigned short) value;
6459*7c568831SAndroid Build Coastguard Worker 	    break;
6460*7c568831SAndroid Build Coastguard Worker         case XML_EXP_OR:
6461*7c568831SAndroid Build Coastguard Worker 	    value = left->key;
6462*7c568831SAndroid Build Coastguard Worker 	    value += right->key;
6463*7c568831SAndroid Build Coastguard Worker 	    value *= 7;
6464*7c568831SAndroid Build Coastguard Worker 	    ret = (unsigned short) value;
6465*7c568831SAndroid Build Coastguard Worker 	    break;
6466*7c568831SAndroid Build Coastguard Worker         case XML_EXP_COUNT:
6467*7c568831SAndroid Build Coastguard Worker 	    value = left->key;
6468*7c568831SAndroid Build Coastguard Worker 	    value += right->key;
6469*7c568831SAndroid Build Coastguard Worker 	    ret = (unsigned short) value;
6470*7c568831SAndroid Build Coastguard Worker 	    break;
6471*7c568831SAndroid Build Coastguard Worker 	default:
6472*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
6473*7c568831SAndroid Build Coastguard Worker     }
6474*7c568831SAndroid Build Coastguard Worker     return(ret);
6475*7c568831SAndroid Build Coastguard Worker }
6476*7c568831SAndroid Build Coastguard Worker 
6477*7c568831SAndroid Build Coastguard Worker 
6478*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr
xmlExpNewNode(xmlExpCtxtPtr ctxt,xmlExpNodeType type)6479*7c568831SAndroid Build Coastguard Worker xmlExpNewNode(xmlExpCtxtPtr ctxt, xmlExpNodeType type) {
6480*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr ret;
6481*7c568831SAndroid Build Coastguard Worker 
6482*7c568831SAndroid Build Coastguard Worker     if (ctxt->nb_nodes >= MAX_NODES)
6483*7c568831SAndroid Build Coastguard Worker         return(NULL);
6484*7c568831SAndroid Build Coastguard Worker     ret = (xmlExpNodePtr) xmlMalloc(sizeof(xmlExpNode));
6485*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
6486*7c568831SAndroid Build Coastguard Worker         return(NULL);
6487*7c568831SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlExpNode));
6488*7c568831SAndroid Build Coastguard Worker     ret->type = type;
6489*7c568831SAndroid Build Coastguard Worker     ret->next = NULL;
6490*7c568831SAndroid Build Coastguard Worker     ctxt->nb_nodes++;
6491*7c568831SAndroid Build Coastguard Worker     ctxt->nb_cons++;
6492*7c568831SAndroid Build Coastguard Worker     return(ret);
6493*7c568831SAndroid Build Coastguard Worker }
6494*7c568831SAndroid Build Coastguard Worker 
6495*7c568831SAndroid Build Coastguard Worker /**
6496*7c568831SAndroid Build Coastguard Worker  * xmlExpHashGetEntry:
6497*7c568831SAndroid Build Coastguard Worker  * @table: the hash table
6498*7c568831SAndroid Build Coastguard Worker  *
6499*7c568831SAndroid Build Coastguard Worker  * Get the unique entry from the hash table. The entry is created if
6500*7c568831SAndroid Build Coastguard Worker  * needed. @left and @right are consumed, i.e. their ref count will
6501*7c568831SAndroid Build Coastguard Worker  * be decremented by the operation.
6502*7c568831SAndroid Build Coastguard Worker  *
6503*7c568831SAndroid Build Coastguard Worker  * Returns the pointer or NULL in case of error
6504*7c568831SAndroid Build Coastguard Worker  */
6505*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr
xmlExpHashGetEntry(xmlExpCtxtPtr ctxt,xmlExpNodeType type,xmlExpNodePtr left,xmlExpNodePtr right,const xmlChar * name,int min,int max)6506*7c568831SAndroid Build Coastguard Worker xmlExpHashGetEntry(xmlExpCtxtPtr ctxt, xmlExpNodeType type,
6507*7c568831SAndroid Build Coastguard Worker                    xmlExpNodePtr left, xmlExpNodePtr right,
6508*7c568831SAndroid Build Coastguard Worker 		   const xmlChar *name, int min, int max) {
6509*7c568831SAndroid Build Coastguard Worker     unsigned short kbase, key;
6510*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr entry;
6511*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr insert;
6512*7c568831SAndroid Build Coastguard Worker 
6513*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
6514*7c568831SAndroid Build Coastguard Worker 	return(NULL);
6515*7c568831SAndroid Build Coastguard Worker 
6516*7c568831SAndroid Build Coastguard Worker     /*
6517*7c568831SAndroid Build Coastguard Worker      * Check for duplicate and insertion location.
6518*7c568831SAndroid Build Coastguard Worker      */
6519*7c568831SAndroid Build Coastguard Worker     if (type == XML_EXP_ATOM) {
6520*7c568831SAndroid Build Coastguard Worker 	kbase = xmlExpHashNameComputeKey(name);
6521*7c568831SAndroid Build Coastguard Worker     } else if (type == XML_EXP_COUNT) {
6522*7c568831SAndroid Build Coastguard Worker         /* COUNT reduction rule 1 */
6523*7c568831SAndroid Build Coastguard Worker 	/* a{1} -> a */
6524*7c568831SAndroid Build Coastguard Worker 	if (min == max) {
6525*7c568831SAndroid Build Coastguard Worker 	    if (min == 1) {
6526*7c568831SAndroid Build Coastguard Worker 		return(left);
6527*7c568831SAndroid Build Coastguard Worker 	    }
6528*7c568831SAndroid Build Coastguard Worker 	    if (min == 0) {
6529*7c568831SAndroid Build Coastguard Worker 		xmlExpFree(ctxt, left);
6530*7c568831SAndroid Build Coastguard Worker 	        return(emptyExp);
6531*7c568831SAndroid Build Coastguard Worker 	    }
6532*7c568831SAndroid Build Coastguard Worker 	}
6533*7c568831SAndroid Build Coastguard Worker 	if (min < 0) {
6534*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, left);
6535*7c568831SAndroid Build Coastguard Worker 	    return(forbiddenExp);
6536*7c568831SAndroid Build Coastguard Worker 	}
6537*7c568831SAndroid Build Coastguard Worker         if (max == -1)
6538*7c568831SAndroid Build Coastguard Worker 	    kbase = min + 79;
6539*7c568831SAndroid Build Coastguard Worker 	else
6540*7c568831SAndroid Build Coastguard Worker 	    kbase = max - min;
6541*7c568831SAndroid Build Coastguard Worker 	kbase += left->key;
6542*7c568831SAndroid Build Coastguard Worker     } else if (type == XML_EXP_OR) {
6543*7c568831SAndroid Build Coastguard Worker         /* Forbid reduction rules */
6544*7c568831SAndroid Build Coastguard Worker         if (left->type == XML_EXP_FORBID) {
6545*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, left);
6546*7c568831SAndroid Build Coastguard Worker 	    return(right);
6547*7c568831SAndroid Build Coastguard Worker 	}
6548*7c568831SAndroid Build Coastguard Worker         if (right->type == XML_EXP_FORBID) {
6549*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, right);
6550*7c568831SAndroid Build Coastguard Worker 	    return(left);
6551*7c568831SAndroid Build Coastguard Worker 	}
6552*7c568831SAndroid Build Coastguard Worker 
6553*7c568831SAndroid Build Coastguard Worker         /* OR reduction rule 1 */
6554*7c568831SAndroid Build Coastguard Worker 	/* a | a reduced to a */
6555*7c568831SAndroid Build Coastguard Worker         if (left == right) {
6556*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, right);
6557*7c568831SAndroid Build Coastguard Worker 	    return(left);
6558*7c568831SAndroid Build Coastguard Worker 	}
6559*7c568831SAndroid Build Coastguard Worker         /* OR canonicalization rule 1 */
6560*7c568831SAndroid Build Coastguard Worker 	/* linearize (a | b) | c into a | (b | c) */
6561*7c568831SAndroid Build Coastguard Worker         if ((left->type == XML_EXP_OR) && (right->type != XML_EXP_OR)) {
6562*7c568831SAndroid Build Coastguard Worker 	    xmlExpNodePtr tmp = left;
6563*7c568831SAndroid Build Coastguard Worker             left = right;
6564*7c568831SAndroid Build Coastguard Worker 	    right = tmp;
6565*7c568831SAndroid Build Coastguard Worker 	}
6566*7c568831SAndroid Build Coastguard Worker         /* OR reduction rule 2 */
6567*7c568831SAndroid Build Coastguard Worker 	/* a | (a | b) and b | (a | b) are reduced to a | b */
6568*7c568831SAndroid Build Coastguard Worker         if (right->type == XML_EXP_OR) {
6569*7c568831SAndroid Build Coastguard Worker 	    if ((left == right->exp_left) ||
6570*7c568831SAndroid Build Coastguard Worker 	        (left == right->exp_right)) {
6571*7c568831SAndroid Build Coastguard Worker 		xmlExpFree(ctxt, left);
6572*7c568831SAndroid Build Coastguard Worker 		return(right);
6573*7c568831SAndroid Build Coastguard Worker 	    }
6574*7c568831SAndroid Build Coastguard Worker 	}
6575*7c568831SAndroid Build Coastguard Worker         /* OR canonicalization rule 2 */
6576*7c568831SAndroid Build Coastguard Worker 	/* linearize (a | b) | c into a | (b | c) */
6577*7c568831SAndroid Build Coastguard Worker         if (left->type == XML_EXP_OR) {
6578*7c568831SAndroid Build Coastguard Worker 	    xmlExpNodePtr tmp;
6579*7c568831SAndroid Build Coastguard Worker 
6580*7c568831SAndroid Build Coastguard Worker 	    /* OR canonicalization rule 2 */
6581*7c568831SAndroid Build Coastguard Worker 	    if ((left->exp_right->type != XML_EXP_OR) &&
6582*7c568831SAndroid Build Coastguard Worker 	        (left->exp_right->key < left->exp_left->key)) {
6583*7c568831SAndroid Build Coastguard Worker 	        tmp = left->exp_right;
6584*7c568831SAndroid Build Coastguard Worker 		left->exp_right = left->exp_left;
6585*7c568831SAndroid Build Coastguard Worker 		left->exp_left = tmp;
6586*7c568831SAndroid Build Coastguard Worker 	    }
6587*7c568831SAndroid Build Coastguard Worker 	    left->exp_right->ref++;
6588*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_right, right,
6589*7c568831SAndroid Build Coastguard Worker 	                             NULL, 0, 0);
6590*7c568831SAndroid Build Coastguard Worker 	    left->exp_left->ref++;
6591*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_left, tmp,
6592*7c568831SAndroid Build Coastguard Worker 	                             NULL, 0, 0);
6593*7c568831SAndroid Build Coastguard Worker 
6594*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, left);
6595*7c568831SAndroid Build Coastguard Worker 	    return(tmp);
6596*7c568831SAndroid Build Coastguard Worker 	}
6597*7c568831SAndroid Build Coastguard Worker 	if (right->type == XML_EXP_OR) {
6598*7c568831SAndroid Build Coastguard Worker 	    /* Ordering in the tree */
6599*7c568831SAndroid Build Coastguard Worker 	    /* C | (A | B) -> A | (B | C) */
6600*7c568831SAndroid Build Coastguard Worker 	    if (left->key > right->exp_right->key) {
6601*7c568831SAndroid Build Coastguard Worker 		xmlExpNodePtr tmp;
6602*7c568831SAndroid Build Coastguard Worker 		right->exp_right->ref++;
6603*7c568831SAndroid Build Coastguard Worker 		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_right,
6604*7c568831SAndroid Build Coastguard Worker 		                         left, NULL, 0, 0);
6605*7c568831SAndroid Build Coastguard Worker 		right->exp_left->ref++;
6606*7c568831SAndroid Build Coastguard Worker 		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_left,
6607*7c568831SAndroid Build Coastguard Worker 		                         tmp, NULL, 0, 0);
6608*7c568831SAndroid Build Coastguard Worker 		xmlExpFree(ctxt, right);
6609*7c568831SAndroid Build Coastguard Worker 		return(tmp);
6610*7c568831SAndroid Build Coastguard Worker 	    }
6611*7c568831SAndroid Build Coastguard Worker 	    /* Ordering in the tree */
6612*7c568831SAndroid Build Coastguard Worker 	    /* B | (A | C) -> A | (B | C) */
6613*7c568831SAndroid Build Coastguard Worker 	    if (left->key > right->exp_left->key) {
6614*7c568831SAndroid Build Coastguard Worker 		xmlExpNodePtr tmp;
6615*7c568831SAndroid Build Coastguard Worker 		right->exp_right->ref++;
6616*7c568831SAndroid Build Coastguard Worker 		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left,
6617*7c568831SAndroid Build Coastguard Worker 		                         right->exp_right, NULL, 0, 0);
6618*7c568831SAndroid Build Coastguard Worker 		right->exp_left->ref++;
6619*7c568831SAndroid Build Coastguard Worker 		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_left,
6620*7c568831SAndroid Build Coastguard Worker 		                         tmp, NULL, 0, 0);
6621*7c568831SAndroid Build Coastguard Worker 		xmlExpFree(ctxt, right);
6622*7c568831SAndroid Build Coastguard Worker 		return(tmp);
6623*7c568831SAndroid Build Coastguard Worker 	    }
6624*7c568831SAndroid Build Coastguard Worker 	}
6625*7c568831SAndroid Build Coastguard Worker 	/* we know both types are != XML_EXP_OR here */
6626*7c568831SAndroid Build Coastguard Worker         else if (left->key > right->key) {
6627*7c568831SAndroid Build Coastguard Worker 	    xmlExpNodePtr tmp = left;
6628*7c568831SAndroid Build Coastguard Worker             left = right;
6629*7c568831SAndroid Build Coastguard Worker 	    right = tmp;
6630*7c568831SAndroid Build Coastguard Worker 	}
6631*7c568831SAndroid Build Coastguard Worker 	kbase = xmlExpHashComputeKey(type, left, right);
6632*7c568831SAndroid Build Coastguard Worker     } else if (type == XML_EXP_SEQ) {
6633*7c568831SAndroid Build Coastguard Worker         /* Forbid reduction rules */
6634*7c568831SAndroid Build Coastguard Worker         if (left->type == XML_EXP_FORBID) {
6635*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, right);
6636*7c568831SAndroid Build Coastguard Worker 	    return(left);
6637*7c568831SAndroid Build Coastguard Worker 	}
6638*7c568831SAndroid Build Coastguard Worker         if (right->type == XML_EXP_FORBID) {
6639*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, left);
6640*7c568831SAndroid Build Coastguard Worker 	    return(right);
6641*7c568831SAndroid Build Coastguard Worker 	}
6642*7c568831SAndroid Build Coastguard Worker         /* Empty reduction rules */
6643*7c568831SAndroid Build Coastguard Worker         if (right->type == XML_EXP_EMPTY) {
6644*7c568831SAndroid Build Coastguard Worker 	    return(left);
6645*7c568831SAndroid Build Coastguard Worker 	}
6646*7c568831SAndroid Build Coastguard Worker         if (left->type == XML_EXP_EMPTY) {
6647*7c568831SAndroid Build Coastguard Worker 	    return(right);
6648*7c568831SAndroid Build Coastguard Worker 	}
6649*7c568831SAndroid Build Coastguard Worker 	kbase = xmlExpHashComputeKey(type, left, right);
6650*7c568831SAndroid Build Coastguard Worker     } else
6651*7c568831SAndroid Build Coastguard Worker         return(NULL);
6652*7c568831SAndroid Build Coastguard Worker 
6653*7c568831SAndroid Build Coastguard Worker     key = kbase % ctxt->size;
6654*7c568831SAndroid Build Coastguard Worker     if (ctxt->table[key] != NULL) {
6655*7c568831SAndroid Build Coastguard Worker 	for (insert = ctxt->table[key]; insert != NULL;
6656*7c568831SAndroid Build Coastguard Worker 	     insert = insert->next) {
6657*7c568831SAndroid Build Coastguard Worker 	    if ((insert->key == kbase) &&
6658*7c568831SAndroid Build Coastguard Worker 	        (insert->type == type)) {
6659*7c568831SAndroid Build Coastguard Worker 		if (type == XML_EXP_ATOM) {
6660*7c568831SAndroid Build Coastguard Worker 		    if (name == insert->exp_str) {
6661*7c568831SAndroid Build Coastguard Worker 			insert->ref++;
6662*7c568831SAndroid Build Coastguard Worker 			return(insert);
6663*7c568831SAndroid Build Coastguard Worker 		    }
6664*7c568831SAndroid Build Coastguard Worker 		} else if (type == XML_EXP_COUNT) {
6665*7c568831SAndroid Build Coastguard Worker 		    if ((insert->exp_min == min) && (insert->exp_max == max) &&
6666*7c568831SAndroid Build Coastguard Worker 		        (insert->exp_left == left)) {
6667*7c568831SAndroid Build Coastguard Worker 			insert->ref++;
6668*7c568831SAndroid Build Coastguard Worker 			left->ref--;
6669*7c568831SAndroid Build Coastguard Worker 			return(insert);
6670*7c568831SAndroid Build Coastguard Worker 		    }
6671*7c568831SAndroid Build Coastguard Worker 		} else if ((insert->exp_left == left) &&
6672*7c568831SAndroid Build Coastguard Worker 			   (insert->exp_right == right)) {
6673*7c568831SAndroid Build Coastguard Worker 		    insert->ref++;
6674*7c568831SAndroid Build Coastguard Worker 		    left->ref--;
6675*7c568831SAndroid Build Coastguard Worker 		    right->ref--;
6676*7c568831SAndroid Build Coastguard Worker 		    return(insert);
6677*7c568831SAndroid Build Coastguard Worker 		}
6678*7c568831SAndroid Build Coastguard Worker 	    }
6679*7c568831SAndroid Build Coastguard Worker 	}
6680*7c568831SAndroid Build Coastguard Worker     }
6681*7c568831SAndroid Build Coastguard Worker 
6682*7c568831SAndroid Build Coastguard Worker     entry = xmlExpNewNode(ctxt, type);
6683*7c568831SAndroid Build Coastguard Worker     if (entry == NULL)
6684*7c568831SAndroid Build Coastguard Worker         return(NULL);
6685*7c568831SAndroid Build Coastguard Worker     entry->key = kbase;
6686*7c568831SAndroid Build Coastguard Worker     if (type == XML_EXP_ATOM) {
6687*7c568831SAndroid Build Coastguard Worker 	entry->exp_str = name;
6688*7c568831SAndroid Build Coastguard Worker 	entry->c_max = 1;
6689*7c568831SAndroid Build Coastguard Worker     } else if (type == XML_EXP_COUNT) {
6690*7c568831SAndroid Build Coastguard Worker         entry->exp_min = min;
6691*7c568831SAndroid Build Coastguard Worker         entry->exp_max = max;
6692*7c568831SAndroid Build Coastguard Worker 	entry->exp_left = left;
6693*7c568831SAndroid Build Coastguard Worker 	if ((min == 0) || (IS_NILLABLE(left)))
6694*7c568831SAndroid Build Coastguard Worker 	    entry->info |= XML_EXP_NILABLE;
6695*7c568831SAndroid Build Coastguard Worker 	if (max < 0)
6696*7c568831SAndroid Build Coastguard Worker 	    entry->c_max = -1;
6697*7c568831SAndroid Build Coastguard Worker 	else
6698*7c568831SAndroid Build Coastguard Worker 	    entry->c_max = max * entry->exp_left->c_max;
6699*7c568831SAndroid Build Coastguard Worker     } else {
6700*7c568831SAndroid Build Coastguard Worker 	entry->exp_left = left;
6701*7c568831SAndroid Build Coastguard Worker 	entry->exp_right = right;
6702*7c568831SAndroid Build Coastguard Worker 	if (type == XML_EXP_OR) {
6703*7c568831SAndroid Build Coastguard Worker 	    if ((IS_NILLABLE(left)) || (IS_NILLABLE(right)))
6704*7c568831SAndroid Build Coastguard Worker 		entry->info |= XML_EXP_NILABLE;
6705*7c568831SAndroid Build Coastguard Worker 	    if ((entry->exp_left->c_max == -1) ||
6706*7c568831SAndroid Build Coastguard Worker 	        (entry->exp_right->c_max == -1))
6707*7c568831SAndroid Build Coastguard Worker 		entry->c_max = -1;
6708*7c568831SAndroid Build Coastguard Worker 	    else if (entry->exp_left->c_max > entry->exp_right->c_max)
6709*7c568831SAndroid Build Coastguard Worker 	        entry->c_max = entry->exp_left->c_max;
6710*7c568831SAndroid Build Coastguard Worker 	    else
6711*7c568831SAndroid Build Coastguard Worker 	        entry->c_max = entry->exp_right->c_max;
6712*7c568831SAndroid Build Coastguard Worker 	} else {
6713*7c568831SAndroid Build Coastguard Worker 	    if ((IS_NILLABLE(left)) && (IS_NILLABLE(right)))
6714*7c568831SAndroid Build Coastguard Worker 		entry->info |= XML_EXP_NILABLE;
6715*7c568831SAndroid Build Coastguard Worker 	    if ((entry->exp_left->c_max == -1) ||
6716*7c568831SAndroid Build Coastguard Worker 	        (entry->exp_right->c_max == -1))
6717*7c568831SAndroid Build Coastguard Worker 		entry->c_max = -1;
6718*7c568831SAndroid Build Coastguard Worker 	    else
6719*7c568831SAndroid Build Coastguard Worker 	        entry->c_max = entry->exp_left->c_max + entry->exp_right->c_max;
6720*7c568831SAndroid Build Coastguard Worker 	}
6721*7c568831SAndroid Build Coastguard Worker     }
6722*7c568831SAndroid Build Coastguard Worker     entry->ref = 1;
6723*7c568831SAndroid Build Coastguard Worker     if (ctxt->table[key] != NULL)
6724*7c568831SAndroid Build Coastguard Worker         entry->next = ctxt->table[key];
6725*7c568831SAndroid Build Coastguard Worker 
6726*7c568831SAndroid Build Coastguard Worker     ctxt->table[key] = entry;
6727*7c568831SAndroid Build Coastguard Worker     ctxt->nbElems++;
6728*7c568831SAndroid Build Coastguard Worker 
6729*7c568831SAndroid Build Coastguard Worker     return(entry);
6730*7c568831SAndroid Build Coastguard Worker }
6731*7c568831SAndroid Build Coastguard Worker 
6732*7c568831SAndroid Build Coastguard Worker /**
6733*7c568831SAndroid Build Coastguard Worker  * xmlExpFree:
6734*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expression context
6735*7c568831SAndroid Build Coastguard Worker  * @exp: the expression
6736*7c568831SAndroid Build Coastguard Worker  *
6737*7c568831SAndroid Build Coastguard Worker  * Dereference the expression
6738*7c568831SAndroid Build Coastguard Worker  */
6739*7c568831SAndroid Build Coastguard Worker void
xmlExpFree(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp)6740*7c568831SAndroid Build Coastguard Worker xmlExpFree(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp) {
6741*7c568831SAndroid Build Coastguard Worker     if ((exp == NULL) || (exp == forbiddenExp) || (exp == emptyExp))
6742*7c568831SAndroid Build Coastguard Worker         return;
6743*7c568831SAndroid Build Coastguard Worker     exp->ref--;
6744*7c568831SAndroid Build Coastguard Worker     if (exp->ref == 0) {
6745*7c568831SAndroid Build Coastguard Worker         unsigned short key;
6746*7c568831SAndroid Build Coastguard Worker 
6747*7c568831SAndroid Build Coastguard Worker         /* Unlink it first from the hash table */
6748*7c568831SAndroid Build Coastguard Worker 	key = exp->key % ctxt->size;
6749*7c568831SAndroid Build Coastguard Worker 	if (ctxt->table[key] == exp) {
6750*7c568831SAndroid Build Coastguard Worker 	    ctxt->table[key] = exp->next;
6751*7c568831SAndroid Build Coastguard Worker 	} else {
6752*7c568831SAndroid Build Coastguard Worker 	    xmlExpNodePtr tmp;
6753*7c568831SAndroid Build Coastguard Worker 
6754*7c568831SAndroid Build Coastguard Worker 	    tmp = ctxt->table[key];
6755*7c568831SAndroid Build Coastguard Worker 	    while (tmp != NULL) {
6756*7c568831SAndroid Build Coastguard Worker 	        if (tmp->next == exp) {
6757*7c568831SAndroid Build Coastguard Worker 		    tmp->next = exp->next;
6758*7c568831SAndroid Build Coastguard Worker 		    break;
6759*7c568831SAndroid Build Coastguard Worker 		}
6760*7c568831SAndroid Build Coastguard Worker 	        tmp = tmp->next;
6761*7c568831SAndroid Build Coastguard Worker 	    }
6762*7c568831SAndroid Build Coastguard Worker 	}
6763*7c568831SAndroid Build Coastguard Worker 
6764*7c568831SAndroid Build Coastguard Worker         if ((exp->type == XML_EXP_SEQ) || (exp->type == XML_EXP_OR)) {
6765*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, exp->exp_left);
6766*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, exp->exp_right);
6767*7c568831SAndroid Build Coastguard Worker 	} else if (exp->type == XML_EXP_COUNT) {
6768*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, exp->exp_left);
6769*7c568831SAndroid Build Coastguard Worker 	}
6770*7c568831SAndroid Build Coastguard Worker         xmlFree(exp);
6771*7c568831SAndroid Build Coastguard Worker 	ctxt->nb_nodes--;
6772*7c568831SAndroid Build Coastguard Worker     }
6773*7c568831SAndroid Build Coastguard Worker }
6774*7c568831SAndroid Build Coastguard Worker 
6775*7c568831SAndroid Build Coastguard Worker /**
6776*7c568831SAndroid Build Coastguard Worker  * xmlExpRef:
6777*7c568831SAndroid Build Coastguard Worker  * @exp: the expression
6778*7c568831SAndroid Build Coastguard Worker  *
6779*7c568831SAndroid Build Coastguard Worker  * Increase the reference count of the expression
6780*7c568831SAndroid Build Coastguard Worker  */
6781*7c568831SAndroid Build Coastguard Worker void
xmlExpRef(xmlExpNodePtr exp)6782*7c568831SAndroid Build Coastguard Worker xmlExpRef(xmlExpNodePtr exp) {
6783*7c568831SAndroid Build Coastguard Worker     if (exp != NULL)
6784*7c568831SAndroid Build Coastguard Worker         exp->ref++;
6785*7c568831SAndroid Build Coastguard Worker }
6786*7c568831SAndroid Build Coastguard Worker 
6787*7c568831SAndroid Build Coastguard Worker /**
6788*7c568831SAndroid Build Coastguard Worker  * xmlExpNewAtom:
6789*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expression context
6790*7c568831SAndroid Build Coastguard Worker  * @name: the atom name
6791*7c568831SAndroid Build Coastguard Worker  * @len: the atom name length in byte (or -1);
6792*7c568831SAndroid Build Coastguard Worker  *
6793*7c568831SAndroid Build Coastguard Worker  * Get the atom associated to this name from that context
6794*7c568831SAndroid Build Coastguard Worker  *
6795*7c568831SAndroid Build Coastguard Worker  * Returns the node or NULL in case of error
6796*7c568831SAndroid Build Coastguard Worker  */
6797*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr
xmlExpNewAtom(xmlExpCtxtPtr ctxt,const xmlChar * name,int len)6798*7c568831SAndroid Build Coastguard Worker xmlExpNewAtom(xmlExpCtxtPtr ctxt, const xmlChar *name, int len) {
6799*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (name == NULL))
6800*7c568831SAndroid Build Coastguard Worker         return(NULL);
6801*7c568831SAndroid Build Coastguard Worker     name = xmlDictLookup(ctxt->dict, name, len);
6802*7c568831SAndroid Build Coastguard Worker     if (name == NULL)
6803*7c568831SAndroid Build Coastguard Worker         return(NULL);
6804*7c568831SAndroid Build Coastguard Worker     return(xmlExpHashGetEntry(ctxt, XML_EXP_ATOM, NULL, NULL, name, 0, 0));
6805*7c568831SAndroid Build Coastguard Worker }
6806*7c568831SAndroid Build Coastguard Worker 
6807*7c568831SAndroid Build Coastguard Worker /**
6808*7c568831SAndroid Build Coastguard Worker  * xmlExpNewOr:
6809*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expression context
6810*7c568831SAndroid Build Coastguard Worker  * @left: left expression
6811*7c568831SAndroid Build Coastguard Worker  * @right: right expression
6812*7c568831SAndroid Build Coastguard Worker  *
6813*7c568831SAndroid Build Coastguard Worker  * Get the atom associated to the choice @left | @right
6814*7c568831SAndroid Build Coastguard Worker  * Note that @left and @right are consumed in the operation, to keep
6815*7c568831SAndroid Build Coastguard Worker  * an handle on them use xmlExpRef() and use xmlExpFree() to release them,
6816*7c568831SAndroid Build Coastguard Worker  * this is true even in case of failure (unless ctxt == NULL).
6817*7c568831SAndroid Build Coastguard Worker  *
6818*7c568831SAndroid Build Coastguard Worker  * Returns the node or NULL in case of error
6819*7c568831SAndroid Build Coastguard Worker  */
6820*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr
xmlExpNewOr(xmlExpCtxtPtr ctxt,xmlExpNodePtr left,xmlExpNodePtr right)6821*7c568831SAndroid Build Coastguard Worker xmlExpNewOr(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) {
6822*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
6823*7c568831SAndroid Build Coastguard Worker         return(NULL);
6824*7c568831SAndroid Build Coastguard Worker     if ((left == NULL) || (right == NULL)) {
6825*7c568831SAndroid Build Coastguard Worker         xmlExpFree(ctxt, left);
6826*7c568831SAndroid Build Coastguard Worker         xmlExpFree(ctxt, right);
6827*7c568831SAndroid Build Coastguard Worker         return(NULL);
6828*7c568831SAndroid Build Coastguard Worker     }
6829*7c568831SAndroid Build Coastguard Worker     return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, left, right, NULL, 0, 0));
6830*7c568831SAndroid Build Coastguard Worker }
6831*7c568831SAndroid Build Coastguard Worker 
6832*7c568831SAndroid Build Coastguard Worker /**
6833*7c568831SAndroid Build Coastguard Worker  * xmlExpNewSeq:
6834*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expression context
6835*7c568831SAndroid Build Coastguard Worker  * @left: left expression
6836*7c568831SAndroid Build Coastguard Worker  * @right: right expression
6837*7c568831SAndroid Build Coastguard Worker  *
6838*7c568831SAndroid Build Coastguard Worker  * Get the atom associated to the sequence @left , @right
6839*7c568831SAndroid Build Coastguard Worker  * Note that @left and @right are consumed in the operation, to keep
6840*7c568831SAndroid Build Coastguard Worker  * an handle on them use xmlExpRef() and use xmlExpFree() to release them,
6841*7c568831SAndroid Build Coastguard Worker  * this is true even in case of failure (unless ctxt == NULL).
6842*7c568831SAndroid Build Coastguard Worker  *
6843*7c568831SAndroid Build Coastguard Worker  * Returns the node or NULL in case of error
6844*7c568831SAndroid Build Coastguard Worker  */
6845*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr
xmlExpNewSeq(xmlExpCtxtPtr ctxt,xmlExpNodePtr left,xmlExpNodePtr right)6846*7c568831SAndroid Build Coastguard Worker xmlExpNewSeq(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) {
6847*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
6848*7c568831SAndroid Build Coastguard Worker         return(NULL);
6849*7c568831SAndroid Build Coastguard Worker     if ((left == NULL) || (right == NULL)) {
6850*7c568831SAndroid Build Coastguard Worker         xmlExpFree(ctxt, left);
6851*7c568831SAndroid Build Coastguard Worker         xmlExpFree(ctxt, right);
6852*7c568831SAndroid Build Coastguard Worker         return(NULL);
6853*7c568831SAndroid Build Coastguard Worker     }
6854*7c568831SAndroid Build Coastguard Worker     return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, left, right, NULL, 0, 0));
6855*7c568831SAndroid Build Coastguard Worker }
6856*7c568831SAndroid Build Coastguard Worker 
6857*7c568831SAndroid Build Coastguard Worker /**
6858*7c568831SAndroid Build Coastguard Worker  * xmlExpNewRange:
6859*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expression context
6860*7c568831SAndroid Build Coastguard Worker  * @subset: the expression to be repeated
6861*7c568831SAndroid Build Coastguard Worker  * @min: the lower bound for the repetition
6862*7c568831SAndroid Build Coastguard Worker  * @max: the upper bound for the repetition, -1 means infinite
6863*7c568831SAndroid Build Coastguard Worker  *
6864*7c568831SAndroid Build Coastguard Worker  * Get the atom associated to the range (@subset){@min, @max}
6865*7c568831SAndroid Build Coastguard Worker  * Note that @subset is consumed in the operation, to keep
6866*7c568831SAndroid Build Coastguard Worker  * an handle on it use xmlExpRef() and use xmlExpFree() to release it,
6867*7c568831SAndroid Build Coastguard Worker  * this is true even in case of failure (unless ctxt == NULL).
6868*7c568831SAndroid Build Coastguard Worker  *
6869*7c568831SAndroid Build Coastguard Worker  * Returns the node or NULL in case of error
6870*7c568831SAndroid Build Coastguard Worker  */
6871*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr
xmlExpNewRange(xmlExpCtxtPtr ctxt,xmlExpNodePtr subset,int min,int max)6872*7c568831SAndroid Build Coastguard Worker xmlExpNewRange(xmlExpCtxtPtr ctxt, xmlExpNodePtr subset, int min, int max) {
6873*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
6874*7c568831SAndroid Build Coastguard Worker         return(NULL);
6875*7c568831SAndroid Build Coastguard Worker     if ((subset == NULL) || (min < 0) || (max < -1) ||
6876*7c568831SAndroid Build Coastguard Worker         ((max >= 0) && (min > max))) {
6877*7c568831SAndroid Build Coastguard Worker 	xmlExpFree(ctxt, subset);
6878*7c568831SAndroid Build Coastguard Worker         return(NULL);
6879*7c568831SAndroid Build Coastguard Worker     }
6880*7c568831SAndroid Build Coastguard Worker     return(xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, subset,
6881*7c568831SAndroid Build Coastguard Worker                               NULL, NULL, min, max));
6882*7c568831SAndroid Build Coastguard Worker }
6883*7c568831SAndroid Build Coastguard Worker 
6884*7c568831SAndroid Build Coastguard Worker /************************************************************************
6885*7c568831SAndroid Build Coastguard Worker  *									*
6886*7c568831SAndroid Build Coastguard Worker  *		Public API for operations on expressions		*
6887*7c568831SAndroid Build Coastguard Worker  *									*
6888*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
6889*7c568831SAndroid Build Coastguard Worker 
6890*7c568831SAndroid Build Coastguard Worker static int
xmlExpGetLanguageInt(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,const xmlChar ** list,int len,int nb)6891*7c568831SAndroid Build Coastguard Worker xmlExpGetLanguageInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
6892*7c568831SAndroid Build Coastguard Worker                      const xmlChar**list, int len, int nb) {
6893*7c568831SAndroid Build Coastguard Worker     int tmp, tmp2;
6894*7c568831SAndroid Build Coastguard Worker tail:
6895*7c568831SAndroid Build Coastguard Worker     switch (exp->type) {
6896*7c568831SAndroid Build Coastguard Worker         case XML_EXP_EMPTY:
6897*7c568831SAndroid Build Coastguard Worker 	    return(0);
6898*7c568831SAndroid Build Coastguard Worker         case XML_EXP_ATOM:
6899*7c568831SAndroid Build Coastguard Worker 	    for (tmp = 0;tmp < nb;tmp++)
6900*7c568831SAndroid Build Coastguard Worker 	        if (list[tmp] == exp->exp_str)
6901*7c568831SAndroid Build Coastguard Worker 		    return(0);
6902*7c568831SAndroid Build Coastguard Worker             if (nb >= len)
6903*7c568831SAndroid Build Coastguard Worker 	        return(-2);
6904*7c568831SAndroid Build Coastguard Worker 	    list[nb] = exp->exp_str;
6905*7c568831SAndroid Build Coastguard Worker 	    return(1);
6906*7c568831SAndroid Build Coastguard Worker         case XML_EXP_COUNT:
6907*7c568831SAndroid Build Coastguard Worker 	    exp = exp->exp_left;
6908*7c568831SAndroid Build Coastguard Worker 	    goto tail;
6909*7c568831SAndroid Build Coastguard Worker         case XML_EXP_SEQ:
6910*7c568831SAndroid Build Coastguard Worker         case XML_EXP_OR:
6911*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpGetLanguageInt(ctxt, exp->exp_left, list, len, nb);
6912*7c568831SAndroid Build Coastguard Worker 	    if (tmp < 0)
6913*7c568831SAndroid Build Coastguard Worker 	        return(tmp);
6914*7c568831SAndroid Build Coastguard Worker 	    tmp2 = xmlExpGetLanguageInt(ctxt, exp->exp_right, list, len,
6915*7c568831SAndroid Build Coastguard Worker 	                                nb + tmp);
6916*7c568831SAndroid Build Coastguard Worker 	    if (tmp2 < 0)
6917*7c568831SAndroid Build Coastguard Worker 	        return(tmp2);
6918*7c568831SAndroid Build Coastguard Worker             return(tmp + tmp2);
6919*7c568831SAndroid Build Coastguard Worker     }
6920*7c568831SAndroid Build Coastguard Worker     return(-1);
6921*7c568831SAndroid Build Coastguard Worker }
6922*7c568831SAndroid Build Coastguard Worker 
6923*7c568831SAndroid Build Coastguard Worker /**
6924*7c568831SAndroid Build Coastguard Worker  * xmlExpGetLanguage:
6925*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expression context
6926*7c568831SAndroid Build Coastguard Worker  * @exp: the expression
6927*7c568831SAndroid Build Coastguard Worker  * @langList: where to store the tokens
6928*7c568831SAndroid Build Coastguard Worker  * @len: the allocated length of @list
6929*7c568831SAndroid Build Coastguard Worker  *
6930*7c568831SAndroid Build Coastguard Worker  * Find all the strings used in @exp and store them in @list
6931*7c568831SAndroid Build Coastguard Worker  *
6932*7c568831SAndroid Build Coastguard Worker  * Returns the number of unique strings found, -1 in case of errors and
6933*7c568831SAndroid Build Coastguard Worker  *         -2 if there is more than @len strings
6934*7c568831SAndroid Build Coastguard Worker  */
6935*7c568831SAndroid Build Coastguard Worker int
xmlExpGetLanguage(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,const xmlChar ** langList,int len)6936*7c568831SAndroid Build Coastguard Worker xmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
6937*7c568831SAndroid Build Coastguard Worker                   const xmlChar**langList, int len) {
6938*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (exp == NULL) || (langList == NULL) || (len <= 0))
6939*7c568831SAndroid Build Coastguard Worker         return(-1);
6940*7c568831SAndroid Build Coastguard Worker     return(xmlExpGetLanguageInt(ctxt, exp, langList, len, 0));
6941*7c568831SAndroid Build Coastguard Worker }
6942*7c568831SAndroid Build Coastguard Worker 
6943*7c568831SAndroid Build Coastguard Worker static int
xmlExpGetStartInt(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,const xmlChar ** list,int len,int nb)6944*7c568831SAndroid Build Coastguard Worker xmlExpGetStartInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
6945*7c568831SAndroid Build Coastguard Worker                   const xmlChar**list, int len, int nb) {
6946*7c568831SAndroid Build Coastguard Worker     int tmp, tmp2;
6947*7c568831SAndroid Build Coastguard Worker tail:
6948*7c568831SAndroid Build Coastguard Worker     switch (exp->type) {
6949*7c568831SAndroid Build Coastguard Worker         case XML_EXP_FORBID:
6950*7c568831SAndroid Build Coastguard Worker 	    return(0);
6951*7c568831SAndroid Build Coastguard Worker         case XML_EXP_EMPTY:
6952*7c568831SAndroid Build Coastguard Worker 	    return(0);
6953*7c568831SAndroid Build Coastguard Worker         case XML_EXP_ATOM:
6954*7c568831SAndroid Build Coastguard Worker 	    for (tmp = 0;tmp < nb;tmp++)
6955*7c568831SAndroid Build Coastguard Worker 	        if (list[tmp] == exp->exp_str)
6956*7c568831SAndroid Build Coastguard Worker 		    return(0);
6957*7c568831SAndroid Build Coastguard Worker             if (nb >= len)
6958*7c568831SAndroid Build Coastguard Worker 	        return(-2);
6959*7c568831SAndroid Build Coastguard Worker 	    list[nb] = exp->exp_str;
6960*7c568831SAndroid Build Coastguard Worker 	    return(1);
6961*7c568831SAndroid Build Coastguard Worker         case XML_EXP_COUNT:
6962*7c568831SAndroid Build Coastguard Worker 	    exp = exp->exp_left;
6963*7c568831SAndroid Build Coastguard Worker 	    goto tail;
6964*7c568831SAndroid Build Coastguard Worker         case XML_EXP_SEQ:
6965*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb);
6966*7c568831SAndroid Build Coastguard Worker 	    if (tmp < 0)
6967*7c568831SAndroid Build Coastguard Worker 	        return(tmp);
6968*7c568831SAndroid Build Coastguard Worker 	    if (IS_NILLABLE(exp->exp_left)) {
6969*7c568831SAndroid Build Coastguard Worker 		tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len,
6970*7c568831SAndroid Build Coastguard Worker 					    nb + tmp);
6971*7c568831SAndroid Build Coastguard Worker 		if (tmp2 < 0)
6972*7c568831SAndroid Build Coastguard Worker 		    return(tmp2);
6973*7c568831SAndroid Build Coastguard Worker 		tmp += tmp2;
6974*7c568831SAndroid Build Coastguard Worker 	    }
6975*7c568831SAndroid Build Coastguard Worker             return(tmp);
6976*7c568831SAndroid Build Coastguard Worker         case XML_EXP_OR:
6977*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb);
6978*7c568831SAndroid Build Coastguard Worker 	    if (tmp < 0)
6979*7c568831SAndroid Build Coastguard Worker 	        return(tmp);
6980*7c568831SAndroid Build Coastguard Worker 	    tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len,
6981*7c568831SAndroid Build Coastguard Worker 	                                nb + tmp);
6982*7c568831SAndroid Build Coastguard Worker 	    if (tmp2 < 0)
6983*7c568831SAndroid Build Coastguard Worker 	        return(tmp2);
6984*7c568831SAndroid Build Coastguard Worker             return(tmp + tmp2);
6985*7c568831SAndroid Build Coastguard Worker     }
6986*7c568831SAndroid Build Coastguard Worker     return(-1);
6987*7c568831SAndroid Build Coastguard Worker }
6988*7c568831SAndroid Build Coastguard Worker 
6989*7c568831SAndroid Build Coastguard Worker /**
6990*7c568831SAndroid Build Coastguard Worker  * xmlExpGetStart:
6991*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expression context
6992*7c568831SAndroid Build Coastguard Worker  * @exp: the expression
6993*7c568831SAndroid Build Coastguard Worker  * @tokList: where to store the tokens
6994*7c568831SAndroid Build Coastguard Worker  * @len: the allocated length of @list
6995*7c568831SAndroid Build Coastguard Worker  *
6996*7c568831SAndroid Build Coastguard Worker  * Find all the strings that appears at the start of the languages
6997*7c568831SAndroid Build Coastguard Worker  * accepted by @exp and store them in @list. E.g. for (a, b) | c
6998*7c568831SAndroid Build Coastguard Worker  * it will return the list [a, c]
6999*7c568831SAndroid Build Coastguard Worker  *
7000*7c568831SAndroid Build Coastguard Worker  * Returns the number of unique strings found, -1 in case of errors and
7001*7c568831SAndroid Build Coastguard Worker  *         -2 if there is more than @len strings
7002*7c568831SAndroid Build Coastguard Worker  */
7003*7c568831SAndroid Build Coastguard Worker int
xmlExpGetStart(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,const xmlChar ** tokList,int len)7004*7c568831SAndroid Build Coastguard Worker xmlExpGetStart(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
7005*7c568831SAndroid Build Coastguard Worker                const xmlChar**tokList, int len) {
7006*7c568831SAndroid Build Coastguard Worker     if ((ctxt == NULL) || (exp == NULL) || (tokList == NULL) || (len <= 0))
7007*7c568831SAndroid Build Coastguard Worker         return(-1);
7008*7c568831SAndroid Build Coastguard Worker     return(xmlExpGetStartInt(ctxt, exp, tokList, len, 0));
7009*7c568831SAndroid Build Coastguard Worker }
7010*7c568831SAndroid Build Coastguard Worker 
7011*7c568831SAndroid Build Coastguard Worker /**
7012*7c568831SAndroid Build Coastguard Worker  * xmlExpIsNillable:
7013*7c568831SAndroid Build Coastguard Worker  * @exp: the expression
7014*7c568831SAndroid Build Coastguard Worker  *
7015*7c568831SAndroid Build Coastguard Worker  * Finds if the expression is nillable, i.e. if it accepts the empty sequence
7016*7c568831SAndroid Build Coastguard Worker  *
7017*7c568831SAndroid Build Coastguard Worker  * Returns 1 if nillable, 0 if not and -1 in case of error
7018*7c568831SAndroid Build Coastguard Worker  */
7019*7c568831SAndroid Build Coastguard Worker int
xmlExpIsNillable(xmlExpNodePtr exp)7020*7c568831SAndroid Build Coastguard Worker xmlExpIsNillable(xmlExpNodePtr exp) {
7021*7c568831SAndroid Build Coastguard Worker     if (exp == NULL)
7022*7c568831SAndroid Build Coastguard Worker         return(-1);
7023*7c568831SAndroid Build Coastguard Worker     return(IS_NILLABLE(exp) != 0);
7024*7c568831SAndroid Build Coastguard Worker }
7025*7c568831SAndroid Build Coastguard Worker 
7026*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr
xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,const xmlChar * str)7027*7c568831SAndroid Build Coastguard Worker xmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str)
7028*7c568831SAndroid Build Coastguard Worker {
7029*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr ret;
7030*7c568831SAndroid Build Coastguard Worker 
7031*7c568831SAndroid Build Coastguard Worker     switch (exp->type) {
7032*7c568831SAndroid Build Coastguard Worker 	case XML_EXP_EMPTY:
7033*7c568831SAndroid Build Coastguard Worker 	    return(forbiddenExp);
7034*7c568831SAndroid Build Coastguard Worker 	case XML_EXP_FORBID:
7035*7c568831SAndroid Build Coastguard Worker 	    return(forbiddenExp);
7036*7c568831SAndroid Build Coastguard Worker 	case XML_EXP_ATOM:
7037*7c568831SAndroid Build Coastguard Worker 	    if (exp->exp_str == str) {
7038*7c568831SAndroid Build Coastguard Worker 	        ret = emptyExp;
7039*7c568831SAndroid Build Coastguard Worker 	    } else {
7040*7c568831SAndroid Build Coastguard Worker 	        /* TODO wildcards here */
7041*7c568831SAndroid Build Coastguard Worker 		ret = forbiddenExp;
7042*7c568831SAndroid Build Coastguard Worker 	    }
7043*7c568831SAndroid Build Coastguard Worker 	    return(ret);
7044*7c568831SAndroid Build Coastguard Worker 	case XML_EXP_OR: {
7045*7c568831SAndroid Build Coastguard Worker 	    xmlExpNodePtr tmp;
7046*7c568831SAndroid Build Coastguard Worker 
7047*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
7048*7c568831SAndroid Build Coastguard Worker 	    if (tmp == NULL) {
7049*7c568831SAndroid Build Coastguard Worker 		return(NULL);
7050*7c568831SAndroid Build Coastguard Worker 	    }
7051*7c568831SAndroid Build Coastguard Worker 	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str);
7052*7c568831SAndroid Build Coastguard Worker 	    if (ret == NULL) {
7053*7c568831SAndroid Build Coastguard Worker 	        xmlExpFree(ctxt, tmp);
7054*7c568831SAndroid Build Coastguard Worker 		return(NULL);
7055*7c568831SAndroid Build Coastguard Worker 	    }
7056*7c568831SAndroid Build Coastguard Worker             ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret,
7057*7c568831SAndroid Build Coastguard Worker 			     NULL, 0, 0);
7058*7c568831SAndroid Build Coastguard Worker 	    return(ret);
7059*7c568831SAndroid Build Coastguard Worker 	}
7060*7c568831SAndroid Build Coastguard Worker 	case XML_EXP_SEQ:
7061*7c568831SAndroid Build Coastguard Worker 	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
7062*7c568831SAndroid Build Coastguard Worker 	    if (ret == NULL) {
7063*7c568831SAndroid Build Coastguard Worker 	        return(NULL);
7064*7c568831SAndroid Build Coastguard Worker 	    } else if (ret == forbiddenExp) {
7065*7c568831SAndroid Build Coastguard Worker 	        if (IS_NILLABLE(exp->exp_left)) {
7066*7c568831SAndroid Build Coastguard Worker 		    ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str);
7067*7c568831SAndroid Build Coastguard Worker 		}
7068*7c568831SAndroid Build Coastguard Worker 	    } else {
7069*7c568831SAndroid Build Coastguard Worker 	        exp->exp_right->ref++;
7070*7c568831SAndroid Build Coastguard Worker 	        ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, exp->exp_right,
7071*7c568831SAndroid Build Coastguard Worker 		                         NULL, 0, 0);
7072*7c568831SAndroid Build Coastguard Worker 	    }
7073*7c568831SAndroid Build Coastguard Worker 	    return(ret);
7074*7c568831SAndroid Build Coastguard Worker 	case XML_EXP_COUNT: {
7075*7c568831SAndroid Build Coastguard Worker 	    int min, max;
7076*7c568831SAndroid Build Coastguard Worker 	    xmlExpNodePtr tmp;
7077*7c568831SAndroid Build Coastguard Worker 
7078*7c568831SAndroid Build Coastguard Worker 	    if (exp->exp_max == 0)
7079*7c568831SAndroid Build Coastguard Worker 		return(forbiddenExp);
7080*7c568831SAndroid Build Coastguard Worker 	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
7081*7c568831SAndroid Build Coastguard Worker 	    if (ret == NULL)
7082*7c568831SAndroid Build Coastguard Worker 	        return(NULL);
7083*7c568831SAndroid Build Coastguard Worker 	    if (ret == forbiddenExp) {
7084*7c568831SAndroid Build Coastguard Worker 	        return(ret);
7085*7c568831SAndroid Build Coastguard Worker 	    }
7086*7c568831SAndroid Build Coastguard Worker 	    if (exp->exp_max == 1)
7087*7c568831SAndroid Build Coastguard Worker 		return(ret);
7088*7c568831SAndroid Build Coastguard Worker 	    if (exp->exp_max < 0) /* unbounded */
7089*7c568831SAndroid Build Coastguard Worker 		max = -1;
7090*7c568831SAndroid Build Coastguard Worker 	    else
7091*7c568831SAndroid Build Coastguard Worker 		max = exp->exp_max - 1;
7092*7c568831SAndroid Build Coastguard Worker 	    if (exp->exp_min > 0)
7093*7c568831SAndroid Build Coastguard Worker 		min = exp->exp_min - 1;
7094*7c568831SAndroid Build Coastguard Worker 	    else
7095*7c568831SAndroid Build Coastguard Worker 		min = 0;
7096*7c568831SAndroid Build Coastguard Worker 	    exp->exp_left->ref++;
7097*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, NULL,
7098*7c568831SAndroid Build Coastguard Worker 				     NULL, min, max);
7099*7c568831SAndroid Build Coastguard Worker 	    if (ret == emptyExp) {
7100*7c568831SAndroid Build Coastguard Worker 	        return(tmp);
7101*7c568831SAndroid Build Coastguard Worker 	    }
7102*7c568831SAndroid Build Coastguard Worker 	    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, tmp,
7103*7c568831SAndroid Build Coastguard Worker 	                              NULL, 0, 0));
7104*7c568831SAndroid Build Coastguard Worker 	}
7105*7c568831SAndroid Build Coastguard Worker     }
7106*7c568831SAndroid Build Coastguard Worker     return(NULL);
7107*7c568831SAndroid Build Coastguard Worker }
7108*7c568831SAndroid Build Coastguard Worker 
7109*7c568831SAndroid Build Coastguard Worker /**
7110*7c568831SAndroid Build Coastguard Worker  * xmlExpStringDerive:
7111*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expression context
7112*7c568831SAndroid Build Coastguard Worker  * @exp: the expression
7113*7c568831SAndroid Build Coastguard Worker  * @str: the string
7114*7c568831SAndroid Build Coastguard Worker  * @len: the string len in bytes if available
7115*7c568831SAndroid Build Coastguard Worker  *
7116*7c568831SAndroid Build Coastguard Worker  * Do one step of Brzozowski derivation of the expression @exp with
7117*7c568831SAndroid Build Coastguard Worker  * respect to the input string
7118*7c568831SAndroid Build Coastguard Worker  *
7119*7c568831SAndroid Build Coastguard Worker  * Returns the resulting expression or NULL in case of internal error
7120*7c568831SAndroid Build Coastguard Worker  */
7121*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr
xmlExpStringDerive(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,const xmlChar * str,int len)7122*7c568831SAndroid Build Coastguard Worker xmlExpStringDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
7123*7c568831SAndroid Build Coastguard Worker                    const xmlChar *str, int len) {
7124*7c568831SAndroid Build Coastguard Worker     const xmlChar *input;
7125*7c568831SAndroid Build Coastguard Worker 
7126*7c568831SAndroid Build Coastguard Worker     if ((exp == NULL) || (ctxt == NULL) || (str == NULL)) {
7127*7c568831SAndroid Build Coastguard Worker         return(NULL);
7128*7c568831SAndroid Build Coastguard Worker     }
7129*7c568831SAndroid Build Coastguard Worker     /*
7130*7c568831SAndroid Build Coastguard Worker      * check the string is in the dictionary, if yes use an interned
7131*7c568831SAndroid Build Coastguard Worker      * copy, otherwise we know it's not an acceptable input
7132*7c568831SAndroid Build Coastguard Worker      */
7133*7c568831SAndroid Build Coastguard Worker     input = xmlDictExists(ctxt->dict, str, len);
7134*7c568831SAndroid Build Coastguard Worker     if (input == NULL) {
7135*7c568831SAndroid Build Coastguard Worker         return(forbiddenExp);
7136*7c568831SAndroid Build Coastguard Worker     }
7137*7c568831SAndroid Build Coastguard Worker     return(xmlExpStringDeriveInt(ctxt, exp, input));
7138*7c568831SAndroid Build Coastguard Worker }
7139*7c568831SAndroid Build Coastguard Worker 
7140*7c568831SAndroid Build Coastguard Worker static int
xmlExpCheckCard(xmlExpNodePtr exp,xmlExpNodePtr sub)7141*7c568831SAndroid Build Coastguard Worker xmlExpCheckCard(xmlExpNodePtr exp, xmlExpNodePtr sub) {
7142*7c568831SAndroid Build Coastguard Worker     int ret = 1;
7143*7c568831SAndroid Build Coastguard Worker 
7144*7c568831SAndroid Build Coastguard Worker     if (sub->c_max == -1) {
7145*7c568831SAndroid Build Coastguard Worker         if (exp->c_max != -1)
7146*7c568831SAndroid Build Coastguard Worker 	    ret = 0;
7147*7c568831SAndroid Build Coastguard Worker     } else if ((exp->c_max >= 0) && (exp->c_max < sub->c_max)) {
7148*7c568831SAndroid Build Coastguard Worker         ret = 0;
7149*7c568831SAndroid Build Coastguard Worker     }
7150*7c568831SAndroid Build Coastguard Worker     return(ret);
7151*7c568831SAndroid Build Coastguard Worker }
7152*7c568831SAndroid Build Coastguard Worker 
7153*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
7154*7c568831SAndroid Build Coastguard Worker                                         xmlExpNodePtr sub);
7155*7c568831SAndroid Build Coastguard Worker /**
7156*7c568831SAndroid Build Coastguard Worker  * xmlExpDivide:
7157*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expressions context
7158*7c568831SAndroid Build Coastguard Worker  * @exp: the englobing expression
7159*7c568831SAndroid Build Coastguard Worker  * @sub: the subexpression
7160*7c568831SAndroid Build Coastguard Worker  * @mult: the multiple expression
7161*7c568831SAndroid Build Coastguard Worker  * @remain: the remain from the derivation of the multiple
7162*7c568831SAndroid Build Coastguard Worker  *
7163*7c568831SAndroid Build Coastguard Worker  * Check if exp is a multiple of sub, i.e. if there is a finite number n
7164*7c568831SAndroid Build Coastguard Worker  * so that sub{n} subsume exp
7165*7c568831SAndroid Build Coastguard Worker  *
7166*7c568831SAndroid Build Coastguard Worker  * Returns the multiple value if successful, 0 if it is not a multiple
7167*7c568831SAndroid Build Coastguard Worker  *         and -1 in case of internal error.
7168*7c568831SAndroid Build Coastguard Worker  */
7169*7c568831SAndroid Build Coastguard Worker 
7170*7c568831SAndroid Build Coastguard Worker static int
xmlExpDivide(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,xmlExpNodePtr sub,xmlExpNodePtr * mult,xmlExpNodePtr * remain)7171*7c568831SAndroid Build Coastguard Worker xmlExpDivide(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub,
7172*7c568831SAndroid Build Coastguard Worker              xmlExpNodePtr *mult, xmlExpNodePtr *remain) {
7173*7c568831SAndroid Build Coastguard Worker     int i;
7174*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr tmp, tmp2;
7175*7c568831SAndroid Build Coastguard Worker 
7176*7c568831SAndroid Build Coastguard Worker     if (mult != NULL) *mult = NULL;
7177*7c568831SAndroid Build Coastguard Worker     if (remain != NULL) *remain = NULL;
7178*7c568831SAndroid Build Coastguard Worker     if (exp->c_max == -1) return(0);
7179*7c568831SAndroid Build Coastguard Worker     if (IS_NILLABLE(exp) && (!IS_NILLABLE(sub))) return(0);
7180*7c568831SAndroid Build Coastguard Worker 
7181*7c568831SAndroid Build Coastguard Worker     for (i = 1;i <= exp->c_max;i++) {
7182*7c568831SAndroid Build Coastguard Worker         sub->ref++;
7183*7c568831SAndroid Build Coastguard Worker         tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT,
7184*7c568831SAndroid Build Coastguard Worker 				 sub, NULL, NULL, i, i);
7185*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL) {
7186*7c568831SAndroid Build Coastguard Worker 	    return(-1);
7187*7c568831SAndroid Build Coastguard Worker 	}
7188*7c568831SAndroid Build Coastguard Worker 	if (!xmlExpCheckCard(tmp, exp)) {
7189*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, tmp);
7190*7c568831SAndroid Build Coastguard Worker 	    continue;
7191*7c568831SAndroid Build Coastguard Worker 	}
7192*7c568831SAndroid Build Coastguard Worker 	tmp2 = xmlExpExpDeriveInt(ctxt, tmp, exp);
7193*7c568831SAndroid Build Coastguard Worker 	if (tmp2 == NULL) {
7194*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, tmp);
7195*7c568831SAndroid Build Coastguard Worker 	    return(-1);
7196*7c568831SAndroid Build Coastguard Worker 	}
7197*7c568831SAndroid Build Coastguard Worker 	if ((tmp2 != forbiddenExp) && (IS_NILLABLE(tmp2))) {
7198*7c568831SAndroid Build Coastguard Worker 	    if (remain != NULL)
7199*7c568831SAndroid Build Coastguard Worker 	        *remain = tmp2;
7200*7c568831SAndroid Build Coastguard Worker 	    else
7201*7c568831SAndroid Build Coastguard Worker 	        xmlExpFree(ctxt, tmp2);
7202*7c568831SAndroid Build Coastguard Worker 	    if (mult != NULL)
7203*7c568831SAndroid Build Coastguard Worker 	        *mult = tmp;
7204*7c568831SAndroid Build Coastguard Worker 	    else
7205*7c568831SAndroid Build Coastguard Worker 	        xmlExpFree(ctxt, tmp);
7206*7c568831SAndroid Build Coastguard Worker 	    return(i);
7207*7c568831SAndroid Build Coastguard Worker 	}
7208*7c568831SAndroid Build Coastguard Worker 	xmlExpFree(ctxt, tmp);
7209*7c568831SAndroid Build Coastguard Worker 	xmlExpFree(ctxt, tmp2);
7210*7c568831SAndroid Build Coastguard Worker     }
7211*7c568831SAndroid Build Coastguard Worker     return(0);
7212*7c568831SAndroid Build Coastguard Worker }
7213*7c568831SAndroid Build Coastguard Worker 
7214*7c568831SAndroid Build Coastguard Worker /**
7215*7c568831SAndroid Build Coastguard Worker  * xmlExpExpDeriveInt:
7216*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expressions context
7217*7c568831SAndroid Build Coastguard Worker  * @exp: the englobing expression
7218*7c568831SAndroid Build Coastguard Worker  * @sub: the subexpression
7219*7c568831SAndroid Build Coastguard Worker  *
7220*7c568831SAndroid Build Coastguard Worker  * Try to do a step of Brzozowski derivation but at a higher level
7221*7c568831SAndroid Build Coastguard Worker  * the input being a subexpression.
7222*7c568831SAndroid Build Coastguard Worker  *
7223*7c568831SAndroid Build Coastguard Worker  * Returns the resulting expression or NULL in case of internal error
7224*7c568831SAndroid Build Coastguard Worker  */
7225*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr
xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,xmlExpNodePtr sub)7226*7c568831SAndroid Build Coastguard Worker xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
7227*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr ret, tmp, tmp2, tmp3;
7228*7c568831SAndroid Build Coastguard Worker     const xmlChar **tab;
7229*7c568831SAndroid Build Coastguard Worker     int len, i;
7230*7c568831SAndroid Build Coastguard Worker 
7231*7c568831SAndroid Build Coastguard Worker     /*
7232*7c568831SAndroid Build Coastguard Worker      * In case of equality and if the expression can only consume a finite
7233*7c568831SAndroid Build Coastguard Worker      * amount, then the derivation is empty
7234*7c568831SAndroid Build Coastguard Worker      */
7235*7c568831SAndroid Build Coastguard Worker     if ((exp == sub) && (exp->c_max >= 0)) {
7236*7c568831SAndroid Build Coastguard Worker         return(emptyExp);
7237*7c568831SAndroid Build Coastguard Worker     }
7238*7c568831SAndroid Build Coastguard Worker     /*
7239*7c568831SAndroid Build Coastguard Worker      * decompose sub sequence first
7240*7c568831SAndroid Build Coastguard Worker      */
7241*7c568831SAndroid Build Coastguard Worker     if (sub->type == XML_EXP_EMPTY) {
7242*7c568831SAndroid Build Coastguard Worker 	exp->ref++;
7243*7c568831SAndroid Build Coastguard Worker         return(exp);
7244*7c568831SAndroid Build Coastguard Worker     }
7245*7c568831SAndroid Build Coastguard Worker     if (sub->type == XML_EXP_SEQ) {
7246*7c568831SAndroid Build Coastguard Worker         tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left);
7247*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL)
7248*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7249*7c568831SAndroid Build Coastguard Worker 	if (tmp == forbiddenExp)
7250*7c568831SAndroid Build Coastguard Worker 	    return(tmp);
7251*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpExpDeriveInt(ctxt, tmp, sub->exp_right);
7252*7c568831SAndroid Build Coastguard Worker 	xmlExpFree(ctxt, tmp);
7253*7c568831SAndroid Build Coastguard Worker 	return(ret);
7254*7c568831SAndroid Build Coastguard Worker     }
7255*7c568831SAndroid Build Coastguard Worker     if (sub->type == XML_EXP_OR) {
7256*7c568831SAndroid Build Coastguard Worker         tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left);
7257*7c568831SAndroid Build Coastguard Worker 	if (tmp == forbiddenExp)
7258*7c568831SAndroid Build Coastguard Worker 	    return(tmp);
7259*7c568831SAndroid Build Coastguard Worker 	if (tmp == NULL)
7260*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7261*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpExpDeriveInt(ctxt, exp, sub->exp_right);
7262*7c568831SAndroid Build Coastguard Worker 	if ((ret == NULL) || (ret == forbiddenExp)) {
7263*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, tmp);
7264*7c568831SAndroid Build Coastguard Worker 	    return(ret);
7265*7c568831SAndroid Build Coastguard Worker 	}
7266*7c568831SAndroid Build Coastguard Worker 	return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret, NULL, 0, 0));
7267*7c568831SAndroid Build Coastguard Worker     }
7268*7c568831SAndroid Build Coastguard Worker     if (!xmlExpCheckCard(exp, sub)) {
7269*7c568831SAndroid Build Coastguard Worker         return(forbiddenExp);
7270*7c568831SAndroid Build Coastguard Worker     }
7271*7c568831SAndroid Build Coastguard Worker     switch (exp->type) {
7272*7c568831SAndroid Build Coastguard Worker         case XML_EXP_EMPTY:
7273*7c568831SAndroid Build Coastguard Worker 	    if (sub == emptyExp)
7274*7c568831SAndroid Build Coastguard Worker 	        return(emptyExp);
7275*7c568831SAndroid Build Coastguard Worker 	    return(forbiddenExp);
7276*7c568831SAndroid Build Coastguard Worker         case XML_EXP_FORBID:
7277*7c568831SAndroid Build Coastguard Worker 	    return(forbiddenExp);
7278*7c568831SAndroid Build Coastguard Worker         case XML_EXP_ATOM:
7279*7c568831SAndroid Build Coastguard Worker 	    if (sub->type == XML_EXP_ATOM) {
7280*7c568831SAndroid Build Coastguard Worker 	        /* TODO: handle wildcards */
7281*7c568831SAndroid Build Coastguard Worker 	        if (exp->exp_str == sub->exp_str) {
7282*7c568831SAndroid Build Coastguard Worker 		    return(emptyExp);
7283*7c568831SAndroid Build Coastguard Worker                 }
7284*7c568831SAndroid Build Coastguard Worker 	        return(forbiddenExp);
7285*7c568831SAndroid Build Coastguard Worker 	    }
7286*7c568831SAndroid Build Coastguard Worker 	    if ((sub->type == XML_EXP_COUNT) &&
7287*7c568831SAndroid Build Coastguard Worker 	        (sub->exp_max == 1) &&
7288*7c568831SAndroid Build Coastguard Worker 	        (sub->exp_left->type == XML_EXP_ATOM)) {
7289*7c568831SAndroid Build Coastguard Worker 	        /* TODO: handle wildcards */
7290*7c568831SAndroid Build Coastguard Worker 	        if (exp->exp_str == sub->exp_left->exp_str) {
7291*7c568831SAndroid Build Coastguard Worker 		    return(emptyExp);
7292*7c568831SAndroid Build Coastguard Worker 		}
7293*7c568831SAndroid Build Coastguard Worker 	        return(forbiddenExp);
7294*7c568831SAndroid Build Coastguard Worker 	    }
7295*7c568831SAndroid Build Coastguard Worker 	    return(forbiddenExp);
7296*7c568831SAndroid Build Coastguard Worker         case XML_EXP_SEQ:
7297*7c568831SAndroid Build Coastguard Worker 	    /* try to get the sequence consumed only if possible */
7298*7c568831SAndroid Build Coastguard Worker 	    if (xmlExpCheckCard(exp->exp_left, sub)) {
7299*7c568831SAndroid Build Coastguard Worker 		/* See if the sequence can be consumed directly */
7300*7c568831SAndroid Build Coastguard Worker 		ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
7301*7c568831SAndroid Build Coastguard Worker 		if ((ret != forbiddenExp) && (ret != NULL)) {
7302*7c568831SAndroid Build Coastguard Worker 		    /*
7303*7c568831SAndroid Build Coastguard Worker 		     * TODO: assumption here that we are determinist
7304*7c568831SAndroid Build Coastguard Worker 		     *       i.e. we won't get to a nillable exp left
7305*7c568831SAndroid Build Coastguard Worker 		     *       subset which could be matched by the right
7306*7c568831SAndroid Build Coastguard Worker 		     *       part too.
7307*7c568831SAndroid Build Coastguard Worker 		     * e.g.: (a | b)+,(a | c) and 'a+,a'
7308*7c568831SAndroid Build Coastguard Worker 		     */
7309*7c568831SAndroid Build Coastguard Worker 		    exp->exp_right->ref++;
7310*7c568831SAndroid Build Coastguard Worker 		    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret,
7311*7c568831SAndroid Build Coastguard Worker 					      exp->exp_right, NULL, 0, 0));
7312*7c568831SAndroid Build Coastguard Worker 		}
7313*7c568831SAndroid Build Coastguard Worker 	    }
7314*7c568831SAndroid Build Coastguard Worker 	    /* Try instead to decompose */
7315*7c568831SAndroid Build Coastguard Worker 	    if (sub->type == XML_EXP_COUNT) {
7316*7c568831SAndroid Build Coastguard Worker 		int min, max;
7317*7c568831SAndroid Build Coastguard Worker 
7318*7c568831SAndroid Build Coastguard Worker 	        ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left);
7319*7c568831SAndroid Build Coastguard Worker 		if (ret == NULL)
7320*7c568831SAndroid Build Coastguard Worker 		    return(NULL);
7321*7c568831SAndroid Build Coastguard Worker 		if (ret != forbiddenExp) {
7322*7c568831SAndroid Build Coastguard Worker 		    if (sub->exp_max < 0)
7323*7c568831SAndroid Build Coastguard Worker 		        max = -1;
7324*7c568831SAndroid Build Coastguard Worker 	            else
7325*7c568831SAndroid Build Coastguard Worker 		        max = sub->exp_max -1;
7326*7c568831SAndroid Build Coastguard Worker 		    if (sub->exp_min > 0)
7327*7c568831SAndroid Build Coastguard Worker 		        min = sub->exp_min -1;
7328*7c568831SAndroid Build Coastguard Worker 		    else
7329*7c568831SAndroid Build Coastguard Worker 		        min = 0;
7330*7c568831SAndroid Build Coastguard Worker 		    exp->exp_right->ref++;
7331*7c568831SAndroid Build Coastguard Worker 		    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret,
7332*7c568831SAndroid Build Coastguard Worker 		                             exp->exp_right, NULL, 0, 0);
7333*7c568831SAndroid Build Coastguard Worker 		    if (tmp == NULL)
7334*7c568831SAndroid Build Coastguard Worker 		        return(NULL);
7335*7c568831SAndroid Build Coastguard Worker 
7336*7c568831SAndroid Build Coastguard Worker 		    sub->exp_left->ref++;
7337*7c568831SAndroid Build Coastguard Worker 		    tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT,
7338*7c568831SAndroid Build Coastguard Worker 				      sub->exp_left, NULL, NULL, min, max);
7339*7c568831SAndroid Build Coastguard Worker 		    if (tmp2 == NULL) {
7340*7c568831SAndroid Build Coastguard Worker 		        xmlExpFree(ctxt, tmp);
7341*7c568831SAndroid Build Coastguard Worker 			return(NULL);
7342*7c568831SAndroid Build Coastguard Worker 		    }
7343*7c568831SAndroid Build Coastguard Worker 		    ret = xmlExpExpDeriveInt(ctxt, tmp, tmp2);
7344*7c568831SAndroid Build Coastguard Worker 		    xmlExpFree(ctxt, tmp);
7345*7c568831SAndroid Build Coastguard Worker 		    xmlExpFree(ctxt, tmp2);
7346*7c568831SAndroid Build Coastguard Worker 		    return(ret);
7347*7c568831SAndroid Build Coastguard Worker 		}
7348*7c568831SAndroid Build Coastguard Worker 	    }
7349*7c568831SAndroid Build Coastguard Worker 	    /* we made no progress on structured operations */
7350*7c568831SAndroid Build Coastguard Worker 	    break;
7351*7c568831SAndroid Build Coastguard Worker         case XML_EXP_OR:
7352*7c568831SAndroid Build Coastguard Worker 	    ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
7353*7c568831SAndroid Build Coastguard Worker 	    if (ret == NULL)
7354*7c568831SAndroid Build Coastguard Worker 	        return(NULL);
7355*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpExpDeriveInt(ctxt, exp->exp_right, sub);
7356*7c568831SAndroid Build Coastguard Worker 	    if (tmp == NULL) {
7357*7c568831SAndroid Build Coastguard Worker 		xmlExpFree(ctxt, ret);
7358*7c568831SAndroid Build Coastguard Worker 	        return(NULL);
7359*7c568831SAndroid Build Coastguard Worker 	    }
7360*7c568831SAndroid Build Coastguard Worker 	    return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, tmp, NULL, 0, 0));
7361*7c568831SAndroid Build Coastguard Worker         case XML_EXP_COUNT: {
7362*7c568831SAndroid Build Coastguard Worker 	    int min, max;
7363*7c568831SAndroid Build Coastguard Worker 
7364*7c568831SAndroid Build Coastguard Worker 	    if (sub->type == XML_EXP_COUNT) {
7365*7c568831SAndroid Build Coastguard Worker 	        /*
7366*7c568831SAndroid Build Coastguard Worker 		 * Try to see if the loop is completely subsumed
7367*7c568831SAndroid Build Coastguard Worker 		 */
7368*7c568831SAndroid Build Coastguard Worker 	        tmp = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left);
7369*7c568831SAndroid Build Coastguard Worker 		if (tmp == NULL)
7370*7c568831SAndroid Build Coastguard Worker 		    return(NULL);
7371*7c568831SAndroid Build Coastguard Worker 		if (tmp == forbiddenExp) {
7372*7c568831SAndroid Build Coastguard Worker 		    int mult;
7373*7c568831SAndroid Build Coastguard Worker 
7374*7c568831SAndroid Build Coastguard Worker 		    mult = xmlExpDivide(ctxt, sub->exp_left, exp->exp_left,
7375*7c568831SAndroid Build Coastguard Worker 		                        NULL, &tmp);
7376*7c568831SAndroid Build Coastguard Worker 		    if (mult <= 0) {
7377*7c568831SAndroid Build Coastguard Worker                         return(forbiddenExp);
7378*7c568831SAndroid Build Coastguard Worker 		    }
7379*7c568831SAndroid Build Coastguard Worker 		    if (sub->exp_max == -1) {
7380*7c568831SAndroid Build Coastguard Worker 		        max = -1;
7381*7c568831SAndroid Build Coastguard Worker 			if (exp->exp_max == -1) {
7382*7c568831SAndroid Build Coastguard Worker 			    if (exp->exp_min <= sub->exp_min * mult)
7383*7c568831SAndroid Build Coastguard Worker 			        min = 0;
7384*7c568831SAndroid Build Coastguard Worker 			    else
7385*7c568831SAndroid Build Coastguard Worker 			        min = exp->exp_min - sub->exp_min * mult;
7386*7c568831SAndroid Build Coastguard Worker 			} else {
7387*7c568831SAndroid Build Coastguard Worker                             xmlExpFree(ctxt, tmp);
7388*7c568831SAndroid Build Coastguard Worker 			    return(forbiddenExp);
7389*7c568831SAndroid Build Coastguard Worker 			}
7390*7c568831SAndroid Build Coastguard Worker 		    } else {
7391*7c568831SAndroid Build Coastguard Worker 			if (exp->exp_max == -1) {
7392*7c568831SAndroid Build Coastguard Worker 			    if (exp->exp_min > sub->exp_min * mult) {
7393*7c568831SAndroid Build Coastguard Worker 				max = -1;
7394*7c568831SAndroid Build Coastguard Worker 				min = exp->exp_min - sub->exp_min * mult;
7395*7c568831SAndroid Build Coastguard Worker 			    } else {
7396*7c568831SAndroid Build Coastguard Worker 				max = -1;
7397*7c568831SAndroid Build Coastguard Worker 				min = 0;
7398*7c568831SAndroid Build Coastguard Worker 			    }
7399*7c568831SAndroid Build Coastguard Worker 			} else {
7400*7c568831SAndroid Build Coastguard Worker 			    if (exp->exp_max < sub->exp_max * mult) {
7401*7c568831SAndroid Build Coastguard Worker 				xmlExpFree(ctxt, tmp);
7402*7c568831SAndroid Build Coastguard Worker 				return(forbiddenExp);
7403*7c568831SAndroid Build Coastguard Worker 			    }
7404*7c568831SAndroid Build Coastguard Worker 			    if (sub->exp_max * mult > exp->exp_min)
7405*7c568831SAndroid Build Coastguard Worker 				min = 0;
7406*7c568831SAndroid Build Coastguard Worker 			    else
7407*7c568831SAndroid Build Coastguard Worker 				min = exp->exp_min - sub->exp_max * mult;
7408*7c568831SAndroid Build Coastguard Worker 			    max = exp->exp_max - sub->exp_max * mult;
7409*7c568831SAndroid Build Coastguard Worker 			}
7410*7c568831SAndroid Build Coastguard Worker 		    }
7411*7c568831SAndroid Build Coastguard Worker 		} else if (!IS_NILLABLE(tmp)) {
7412*7c568831SAndroid Build Coastguard Worker 		    /*
7413*7c568831SAndroid Build Coastguard Worker 		     * TODO: loop here to try to grow if working on finite
7414*7c568831SAndroid Build Coastguard Worker 		     *       blocks.
7415*7c568831SAndroid Build Coastguard Worker 		     */
7416*7c568831SAndroid Build Coastguard Worker 		    xmlExpFree(ctxt, tmp);
7417*7c568831SAndroid Build Coastguard Worker 		    return(forbiddenExp);
7418*7c568831SAndroid Build Coastguard Worker 		} else if (sub->exp_max == -1) {
7419*7c568831SAndroid Build Coastguard Worker 		    if (exp->exp_max == -1) {
7420*7c568831SAndroid Build Coastguard Worker 		        if (exp->exp_min <= sub->exp_min) {
7421*7c568831SAndroid Build Coastguard Worker                             max = -1;
7422*7c568831SAndroid Build Coastguard Worker 			    min = 0;
7423*7c568831SAndroid Build Coastguard Worker 			} else {
7424*7c568831SAndroid Build Coastguard Worker                             max = -1;
7425*7c568831SAndroid Build Coastguard Worker 			    min = exp->exp_min - sub->exp_min;
7426*7c568831SAndroid Build Coastguard Worker 			}
7427*7c568831SAndroid Build Coastguard Worker 		    } else if (exp->exp_min > sub->exp_min) {
7428*7c568831SAndroid Build Coastguard Worker 		        xmlExpFree(ctxt, tmp);
7429*7c568831SAndroid Build Coastguard Worker 		        return(forbiddenExp);
7430*7c568831SAndroid Build Coastguard Worker 		    } else {
7431*7c568831SAndroid Build Coastguard Worker 			max = -1;
7432*7c568831SAndroid Build Coastguard Worker 			min = 0;
7433*7c568831SAndroid Build Coastguard Worker 		    }
7434*7c568831SAndroid Build Coastguard Worker 		} else {
7435*7c568831SAndroid Build Coastguard Worker 		    if (exp->exp_max == -1) {
7436*7c568831SAndroid Build Coastguard Worker 		        if (exp->exp_min > sub->exp_min) {
7437*7c568831SAndroid Build Coastguard Worker 			    max = -1;
7438*7c568831SAndroid Build Coastguard Worker 			    min = exp->exp_min - sub->exp_min;
7439*7c568831SAndroid Build Coastguard Worker 			} else {
7440*7c568831SAndroid Build Coastguard Worker 			    max = -1;
7441*7c568831SAndroid Build Coastguard Worker 			    min = 0;
7442*7c568831SAndroid Build Coastguard Worker 			}
7443*7c568831SAndroid Build Coastguard Worker 		    } else {
7444*7c568831SAndroid Build Coastguard Worker 		        if (exp->exp_max < sub->exp_max) {
7445*7c568831SAndroid Build Coastguard Worker 			    xmlExpFree(ctxt, tmp);
7446*7c568831SAndroid Build Coastguard Worker 			    return(forbiddenExp);
7447*7c568831SAndroid Build Coastguard Worker 			}
7448*7c568831SAndroid Build Coastguard Worker 			if (sub->exp_max > exp->exp_min)
7449*7c568831SAndroid Build Coastguard Worker 			    min = 0;
7450*7c568831SAndroid Build Coastguard Worker 			else
7451*7c568831SAndroid Build Coastguard Worker 			    min = exp->exp_min - sub->exp_max;
7452*7c568831SAndroid Build Coastguard Worker 			max = exp->exp_max - sub->exp_max;
7453*7c568831SAndroid Build Coastguard Worker 		    }
7454*7c568831SAndroid Build Coastguard Worker 		}
7455*7c568831SAndroid Build Coastguard Worker 		exp->exp_left->ref++;
7456*7c568831SAndroid Build Coastguard Worker 		tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left,
7457*7c568831SAndroid Build Coastguard Worker 		                          NULL, NULL, min, max);
7458*7c568831SAndroid Build Coastguard Worker 		if (tmp2 == NULL) {
7459*7c568831SAndroid Build Coastguard Worker 		    return(NULL);
7460*7c568831SAndroid Build Coastguard Worker 		}
7461*7c568831SAndroid Build Coastguard Worker                 ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, tmp, tmp2,
7462*7c568831SAndroid Build Coastguard Worker 		                         NULL, 0, 0);
7463*7c568831SAndroid Build Coastguard Worker 		return(ret);
7464*7c568831SAndroid Build Coastguard Worker 	    }
7465*7c568831SAndroid Build Coastguard Worker 	    tmp = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
7466*7c568831SAndroid Build Coastguard Worker 	    if (tmp == NULL)
7467*7c568831SAndroid Build Coastguard Worker 		return(NULL);
7468*7c568831SAndroid Build Coastguard Worker 	    if (tmp == forbiddenExp) {
7469*7c568831SAndroid Build Coastguard Worker 		return(forbiddenExp);
7470*7c568831SAndroid Build Coastguard Worker 	    }
7471*7c568831SAndroid Build Coastguard Worker 	    if (exp->exp_min > 0)
7472*7c568831SAndroid Build Coastguard Worker 		min = exp->exp_min - 1;
7473*7c568831SAndroid Build Coastguard Worker 	    else
7474*7c568831SAndroid Build Coastguard Worker 		min = 0;
7475*7c568831SAndroid Build Coastguard Worker 	    if (exp->exp_max < 0)
7476*7c568831SAndroid Build Coastguard Worker 		max = -1;
7477*7c568831SAndroid Build Coastguard Worker 	    else
7478*7c568831SAndroid Build Coastguard Worker 		max = exp->exp_max - 1;
7479*7c568831SAndroid Build Coastguard Worker 
7480*7c568831SAndroid Build Coastguard Worker 	    exp->exp_left->ref++;
7481*7c568831SAndroid Build Coastguard Worker 	    tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left,
7482*7c568831SAndroid Build Coastguard Worker 				      NULL, NULL, min, max);
7483*7c568831SAndroid Build Coastguard Worker 	    if (tmp2 == NULL)
7484*7c568831SAndroid Build Coastguard Worker 		return(NULL);
7485*7c568831SAndroid Build Coastguard Worker 	    ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, tmp, tmp2,
7486*7c568831SAndroid Build Coastguard Worker 				     NULL, 0, 0);
7487*7c568831SAndroid Build Coastguard Worker 	    return(ret);
7488*7c568831SAndroid Build Coastguard Worker 	}
7489*7c568831SAndroid Build Coastguard Worker     }
7490*7c568831SAndroid Build Coastguard Worker 
7491*7c568831SAndroid Build Coastguard Worker     if (IS_NILLABLE(sub)) {
7492*7c568831SAndroid Build Coastguard Worker         if (!(IS_NILLABLE(exp)))
7493*7c568831SAndroid Build Coastguard Worker 	    return(forbiddenExp);
7494*7c568831SAndroid Build Coastguard Worker 	else
7495*7c568831SAndroid Build Coastguard Worker 	    ret = emptyExp;
7496*7c568831SAndroid Build Coastguard Worker     } else
7497*7c568831SAndroid Build Coastguard Worker 	ret = NULL;
7498*7c568831SAndroid Build Coastguard Worker     /*
7499*7c568831SAndroid Build Coastguard Worker      * here the structured derivation made no progress so
7500*7c568831SAndroid Build Coastguard Worker      * we use the default token based derivation to force one more step
7501*7c568831SAndroid Build Coastguard Worker      */
7502*7c568831SAndroid Build Coastguard Worker     if (ctxt->tabSize == 0)
7503*7c568831SAndroid Build Coastguard Worker         ctxt->tabSize = 40;
7504*7c568831SAndroid Build Coastguard Worker 
7505*7c568831SAndroid Build Coastguard Worker     tab = (const xmlChar **) xmlMalloc(ctxt->tabSize *
7506*7c568831SAndroid Build Coastguard Worker 	                               sizeof(const xmlChar *));
7507*7c568831SAndroid Build Coastguard Worker     if (tab == NULL) {
7508*7c568831SAndroid Build Coastguard Worker 	return(NULL);
7509*7c568831SAndroid Build Coastguard Worker     }
7510*7c568831SAndroid Build Coastguard Worker 
7511*7c568831SAndroid Build Coastguard Worker     /*
7512*7c568831SAndroid Build Coastguard Worker      * collect all the strings accepted by the subexpression on input
7513*7c568831SAndroid Build Coastguard Worker      */
7514*7c568831SAndroid Build Coastguard Worker     len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0);
7515*7c568831SAndroid Build Coastguard Worker     while (len < 0) {
7516*7c568831SAndroid Build Coastguard Worker         const xmlChar **temp;
7517*7c568831SAndroid Build Coastguard Worker 	temp = (const xmlChar **) xmlRealloc((xmlChar **) tab, ctxt->tabSize * 2 *
7518*7c568831SAndroid Build Coastguard Worker 	                                     sizeof(const xmlChar *));
7519*7c568831SAndroid Build Coastguard Worker 	if (temp == NULL) {
7520*7c568831SAndroid Build Coastguard Worker 	    xmlFree((xmlChar **) tab);
7521*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7522*7c568831SAndroid Build Coastguard Worker 	}
7523*7c568831SAndroid Build Coastguard Worker 	tab = temp;
7524*7c568831SAndroid Build Coastguard Worker 	ctxt->tabSize *= 2;
7525*7c568831SAndroid Build Coastguard Worker 	len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0);
7526*7c568831SAndroid Build Coastguard Worker     }
7527*7c568831SAndroid Build Coastguard Worker     for (i = 0;i < len;i++) {
7528*7c568831SAndroid Build Coastguard Worker         tmp = xmlExpStringDeriveInt(ctxt, exp, tab[i]);
7529*7c568831SAndroid Build Coastguard Worker 	if ((tmp == NULL) || (tmp == forbiddenExp)) {
7530*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, ret);
7531*7c568831SAndroid Build Coastguard Worker 	    xmlFree((xmlChar **) tab);
7532*7c568831SAndroid Build Coastguard Worker 	    return(tmp);
7533*7c568831SAndroid Build Coastguard Worker 	}
7534*7c568831SAndroid Build Coastguard Worker 	tmp2 = xmlExpStringDeriveInt(ctxt, sub, tab[i]);
7535*7c568831SAndroid Build Coastguard Worker 	if ((tmp2 == NULL) || (tmp2 == forbiddenExp)) {
7536*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, tmp);
7537*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, ret);
7538*7c568831SAndroid Build Coastguard Worker 	    xmlFree((xmlChar **) tab);
7539*7c568831SAndroid Build Coastguard Worker 	    return(tmp);
7540*7c568831SAndroid Build Coastguard Worker 	}
7541*7c568831SAndroid Build Coastguard Worker 	tmp3 = xmlExpExpDeriveInt(ctxt, tmp, tmp2);
7542*7c568831SAndroid Build Coastguard Worker 	xmlExpFree(ctxt, tmp);
7543*7c568831SAndroid Build Coastguard Worker 	xmlExpFree(ctxt, tmp2);
7544*7c568831SAndroid Build Coastguard Worker 
7545*7c568831SAndroid Build Coastguard Worker 	if ((tmp3 == NULL) || (tmp3 == forbiddenExp)) {
7546*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, ret);
7547*7c568831SAndroid Build Coastguard Worker 	    xmlFree((xmlChar **) tab);
7548*7c568831SAndroid Build Coastguard Worker 	    return(tmp3);
7549*7c568831SAndroid Build Coastguard Worker 	}
7550*7c568831SAndroid Build Coastguard Worker 
7551*7c568831SAndroid Build Coastguard Worker 	if (ret == NULL)
7552*7c568831SAndroid Build Coastguard Worker 	    ret = tmp3;
7553*7c568831SAndroid Build Coastguard Worker 	else {
7554*7c568831SAndroid Build Coastguard Worker 	    ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, tmp3, NULL, 0, 0);
7555*7c568831SAndroid Build Coastguard Worker 	    if (ret == NULL) {
7556*7c568831SAndroid Build Coastguard Worker 		xmlFree((xmlChar **) tab);
7557*7c568831SAndroid Build Coastguard Worker 	        return(NULL);
7558*7c568831SAndroid Build Coastguard Worker 	    }
7559*7c568831SAndroid Build Coastguard Worker 	}
7560*7c568831SAndroid Build Coastguard Worker     }
7561*7c568831SAndroid Build Coastguard Worker     xmlFree((xmlChar **) tab);
7562*7c568831SAndroid Build Coastguard Worker     return(ret);
7563*7c568831SAndroid Build Coastguard Worker }
7564*7c568831SAndroid Build Coastguard Worker 
7565*7c568831SAndroid Build Coastguard Worker /**
7566*7c568831SAndroid Build Coastguard Worker  * xmlExpExpDerive:
7567*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expressions context
7568*7c568831SAndroid Build Coastguard Worker  * @exp: the englobing expression
7569*7c568831SAndroid Build Coastguard Worker  * @sub: the subexpression
7570*7c568831SAndroid Build Coastguard Worker  *
7571*7c568831SAndroid Build Coastguard Worker  * Evaluates the expression resulting from @exp consuming a sub expression @sub
7572*7c568831SAndroid Build Coastguard Worker  * Based on algebraic derivation and sometimes direct Brzozowski derivation
7573*7c568831SAndroid Build Coastguard Worker  * it usually takes less than linear time and can handle expressions generating
7574*7c568831SAndroid Build Coastguard Worker  * infinite languages.
7575*7c568831SAndroid Build Coastguard Worker  *
7576*7c568831SAndroid Build Coastguard Worker  * Returns the resulting expression or NULL in case of internal error, the
7577*7c568831SAndroid Build Coastguard Worker  *         result must be freed
7578*7c568831SAndroid Build Coastguard Worker  */
7579*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr
xmlExpExpDerive(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,xmlExpNodePtr sub)7580*7c568831SAndroid Build Coastguard Worker xmlExpExpDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
7581*7c568831SAndroid Build Coastguard Worker     if ((exp == NULL) || (ctxt == NULL) || (sub == NULL))
7582*7c568831SAndroid Build Coastguard Worker         return(NULL);
7583*7c568831SAndroid Build Coastguard Worker 
7584*7c568831SAndroid Build Coastguard Worker     /*
7585*7c568831SAndroid Build Coastguard Worker      * O(1) speedups
7586*7c568831SAndroid Build Coastguard Worker      */
7587*7c568831SAndroid Build Coastguard Worker     if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) {
7588*7c568831SAndroid Build Coastguard Worker         return(forbiddenExp);
7589*7c568831SAndroid Build Coastguard Worker     }
7590*7c568831SAndroid Build Coastguard Worker     if (xmlExpCheckCard(exp, sub) == 0) {
7591*7c568831SAndroid Build Coastguard Worker         return(forbiddenExp);
7592*7c568831SAndroid Build Coastguard Worker     }
7593*7c568831SAndroid Build Coastguard Worker     return(xmlExpExpDeriveInt(ctxt, exp, sub));
7594*7c568831SAndroid Build Coastguard Worker }
7595*7c568831SAndroid Build Coastguard Worker 
7596*7c568831SAndroid Build Coastguard Worker /**
7597*7c568831SAndroid Build Coastguard Worker  * xmlExpSubsume:
7598*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expressions context
7599*7c568831SAndroid Build Coastguard Worker  * @exp: the englobing expression
7600*7c568831SAndroid Build Coastguard Worker  * @sub: the subexpression
7601*7c568831SAndroid Build Coastguard Worker  *
7602*7c568831SAndroid Build Coastguard Worker  * Check whether @exp accepts all the languages accepted by @sub
7603*7c568831SAndroid Build Coastguard Worker  * the input being a subexpression.
7604*7c568831SAndroid Build Coastguard Worker  *
7605*7c568831SAndroid Build Coastguard Worker  * Returns 1 if true 0 if false and -1 in case of failure.
7606*7c568831SAndroid Build Coastguard Worker  */
7607*7c568831SAndroid Build Coastguard Worker int
xmlExpSubsume(xmlExpCtxtPtr ctxt,xmlExpNodePtr exp,xmlExpNodePtr sub)7608*7c568831SAndroid Build Coastguard Worker xmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
7609*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr tmp;
7610*7c568831SAndroid Build Coastguard Worker 
7611*7c568831SAndroid Build Coastguard Worker     if ((exp == NULL) || (ctxt == NULL) || (sub == NULL))
7612*7c568831SAndroid Build Coastguard Worker         return(-1);
7613*7c568831SAndroid Build Coastguard Worker 
7614*7c568831SAndroid Build Coastguard Worker     /*
7615*7c568831SAndroid Build Coastguard Worker      * TODO: speedup by checking the language of sub is a subset of the
7616*7c568831SAndroid Build Coastguard Worker      *       language of exp
7617*7c568831SAndroid Build Coastguard Worker      */
7618*7c568831SAndroid Build Coastguard Worker     /*
7619*7c568831SAndroid Build Coastguard Worker      * O(1) speedups
7620*7c568831SAndroid Build Coastguard Worker      */
7621*7c568831SAndroid Build Coastguard Worker     if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) {
7622*7c568831SAndroid Build Coastguard Worker         return(0);
7623*7c568831SAndroid Build Coastguard Worker     }
7624*7c568831SAndroid Build Coastguard Worker     if (xmlExpCheckCard(exp, sub) == 0) {
7625*7c568831SAndroid Build Coastguard Worker         return(0);
7626*7c568831SAndroid Build Coastguard Worker     }
7627*7c568831SAndroid Build Coastguard Worker     tmp = xmlExpExpDeriveInt(ctxt, exp, sub);
7628*7c568831SAndroid Build Coastguard Worker     if (tmp == NULL)
7629*7c568831SAndroid Build Coastguard Worker         return(-1);
7630*7c568831SAndroid Build Coastguard Worker     if (tmp == forbiddenExp)
7631*7c568831SAndroid Build Coastguard Worker 	return(0);
7632*7c568831SAndroid Build Coastguard Worker     if (tmp == emptyExp)
7633*7c568831SAndroid Build Coastguard Worker 	return(1);
7634*7c568831SAndroid Build Coastguard Worker     if ((tmp != NULL) && (IS_NILLABLE(tmp))) {
7635*7c568831SAndroid Build Coastguard Worker         xmlExpFree(ctxt, tmp);
7636*7c568831SAndroid Build Coastguard Worker         return(1);
7637*7c568831SAndroid Build Coastguard Worker     }
7638*7c568831SAndroid Build Coastguard Worker     xmlExpFree(ctxt, tmp);
7639*7c568831SAndroid Build Coastguard Worker     return(0);
7640*7c568831SAndroid Build Coastguard Worker }
7641*7c568831SAndroid Build Coastguard Worker 
7642*7c568831SAndroid Build Coastguard Worker /************************************************************************
7643*7c568831SAndroid Build Coastguard Worker  *									*
7644*7c568831SAndroid Build Coastguard Worker  *			Parsing expression				*
7645*7c568831SAndroid Build Coastguard Worker  *									*
7646*7c568831SAndroid Build Coastguard Worker  ************************************************************************/
7647*7c568831SAndroid Build Coastguard Worker 
7648*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr xmlExpParseExpr(xmlExpCtxtPtr ctxt);
7649*7c568831SAndroid Build Coastguard Worker 
7650*7c568831SAndroid Build Coastguard Worker #undef CUR
7651*7c568831SAndroid Build Coastguard Worker #define CUR (*ctxt->cur)
7652*7c568831SAndroid Build Coastguard Worker #undef NEXT
7653*7c568831SAndroid Build Coastguard Worker #define NEXT ctxt->cur++;
7654*7c568831SAndroid Build Coastguard Worker #undef IS_BLANK
7655*7c568831SAndroid Build Coastguard Worker #define IS_BLANK(c) ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))
7656*7c568831SAndroid Build Coastguard Worker #define SKIP_BLANKS while (IS_BLANK(*ctxt->cur)) ctxt->cur++;
7657*7c568831SAndroid Build Coastguard Worker 
7658*7c568831SAndroid Build Coastguard Worker static int
xmlExpParseNumber(xmlExpCtxtPtr ctxt)7659*7c568831SAndroid Build Coastguard Worker xmlExpParseNumber(xmlExpCtxtPtr ctxt) {
7660*7c568831SAndroid Build Coastguard Worker     int ret = 0;
7661*7c568831SAndroid Build Coastguard Worker 
7662*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS
7663*7c568831SAndroid Build Coastguard Worker     if (CUR == '*') {
7664*7c568831SAndroid Build Coastguard Worker 	NEXT
7665*7c568831SAndroid Build Coastguard Worker 	return(-1);
7666*7c568831SAndroid Build Coastguard Worker     }
7667*7c568831SAndroid Build Coastguard Worker     if ((CUR < '0') || (CUR > '9'))
7668*7c568831SAndroid Build Coastguard Worker         return(-1);
7669*7c568831SAndroid Build Coastguard Worker     while ((CUR >= '0') && (CUR <= '9')) {
7670*7c568831SAndroid Build Coastguard Worker         ret = ret * 10 + (CUR - '0');
7671*7c568831SAndroid Build Coastguard Worker 	NEXT
7672*7c568831SAndroid Build Coastguard Worker     }
7673*7c568831SAndroid Build Coastguard Worker     return(ret);
7674*7c568831SAndroid Build Coastguard Worker }
7675*7c568831SAndroid Build Coastguard Worker 
7676*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr
xmlExpParseOr(xmlExpCtxtPtr ctxt)7677*7c568831SAndroid Build Coastguard Worker xmlExpParseOr(xmlExpCtxtPtr ctxt) {
7678*7c568831SAndroid Build Coastguard Worker     const char *base;
7679*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr ret;
7680*7c568831SAndroid Build Coastguard Worker     const xmlChar *val;
7681*7c568831SAndroid Build Coastguard Worker 
7682*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS
7683*7c568831SAndroid Build Coastguard Worker     base = ctxt->cur;
7684*7c568831SAndroid Build Coastguard Worker     if (*ctxt->cur == '(') {
7685*7c568831SAndroid Build Coastguard Worker         NEXT
7686*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpParseExpr(ctxt);
7687*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS
7688*7c568831SAndroid Build Coastguard Worker 	if (*ctxt->cur != ')') {
7689*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, ret);
7690*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7691*7c568831SAndroid Build Coastguard Worker 	}
7692*7c568831SAndroid Build Coastguard Worker 	NEXT;
7693*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS
7694*7c568831SAndroid Build Coastguard Worker 	goto parse_quantifier;
7695*7c568831SAndroid Build Coastguard Worker     }
7696*7c568831SAndroid Build Coastguard Worker     while ((CUR != 0) && (!(IS_BLANK(CUR))) && (CUR != '(') &&
7697*7c568831SAndroid Build Coastguard Worker            (CUR != ')') && (CUR != '|') && (CUR != ',') && (CUR != '{') &&
7698*7c568831SAndroid Build Coastguard Worker 	   (CUR != '*') && (CUR != '+') && (CUR != '?') && (CUR != '}'))
7699*7c568831SAndroid Build Coastguard Worker 	NEXT;
7700*7c568831SAndroid Build Coastguard Worker     val = xmlDictLookup(ctxt->dict, BAD_CAST base, ctxt->cur - base);
7701*7c568831SAndroid Build Coastguard Worker     if (val == NULL)
7702*7c568831SAndroid Build Coastguard Worker         return(NULL);
7703*7c568831SAndroid Build Coastguard Worker     ret = xmlExpHashGetEntry(ctxt, XML_EXP_ATOM, NULL, NULL, val, 0, 0);
7704*7c568831SAndroid Build Coastguard Worker     if (ret == NULL)
7705*7c568831SAndroid Build Coastguard Worker         return(NULL);
7706*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS
7707*7c568831SAndroid Build Coastguard Worker parse_quantifier:
7708*7c568831SAndroid Build Coastguard Worker     if (CUR == '{') {
7709*7c568831SAndroid Build Coastguard Worker         int min, max;
7710*7c568831SAndroid Build Coastguard Worker 
7711*7c568831SAndroid Build Coastguard Worker         NEXT
7712*7c568831SAndroid Build Coastguard Worker 	min = xmlExpParseNumber(ctxt);
7713*7c568831SAndroid Build Coastguard Worker 	if (min < 0) {
7714*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, ret);
7715*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7716*7c568831SAndroid Build Coastguard Worker 	}
7717*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS
7718*7c568831SAndroid Build Coastguard Worker 	if (CUR == ',') {
7719*7c568831SAndroid Build Coastguard Worker 	    NEXT
7720*7c568831SAndroid Build Coastguard Worker 	    max = xmlExpParseNumber(ctxt);
7721*7c568831SAndroid Build Coastguard Worker 	    SKIP_BLANKS
7722*7c568831SAndroid Build Coastguard Worker 	} else
7723*7c568831SAndroid Build Coastguard Worker 	    max = min;
7724*7c568831SAndroid Build Coastguard Worker 	if (CUR != '}') {
7725*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, ret);
7726*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7727*7c568831SAndroid Build Coastguard Worker 	}
7728*7c568831SAndroid Build Coastguard Worker         NEXT
7729*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7730*7c568831SAndroid Build Coastguard Worker 	                         min, max);
7731*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS
7732*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '?') {
7733*7c568831SAndroid Build Coastguard Worker         NEXT
7734*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7735*7c568831SAndroid Build Coastguard Worker 	                         0, 1);
7736*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS
7737*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '+') {
7738*7c568831SAndroid Build Coastguard Worker         NEXT
7739*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7740*7c568831SAndroid Build Coastguard Worker 	                         1, -1);
7741*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS
7742*7c568831SAndroid Build Coastguard Worker     } else if (CUR == '*') {
7743*7c568831SAndroid Build Coastguard Worker         NEXT
7744*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7745*7c568831SAndroid Build Coastguard Worker 	                         0, -1);
7746*7c568831SAndroid Build Coastguard Worker 	SKIP_BLANKS
7747*7c568831SAndroid Build Coastguard Worker     }
7748*7c568831SAndroid Build Coastguard Worker     return(ret);
7749*7c568831SAndroid Build Coastguard Worker }
7750*7c568831SAndroid Build Coastguard Worker 
7751*7c568831SAndroid Build Coastguard Worker 
7752*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr
xmlExpParseSeq(xmlExpCtxtPtr ctxt)7753*7c568831SAndroid Build Coastguard Worker xmlExpParseSeq(xmlExpCtxtPtr ctxt) {
7754*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr ret, right;
7755*7c568831SAndroid Build Coastguard Worker 
7756*7c568831SAndroid Build Coastguard Worker     ret = xmlExpParseOr(ctxt);
7757*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS
7758*7c568831SAndroid Build Coastguard Worker     while (CUR == '|') {
7759*7c568831SAndroid Build Coastguard Worker         NEXT
7760*7c568831SAndroid Build Coastguard Worker 	right = xmlExpParseOr(ctxt);
7761*7c568831SAndroid Build Coastguard Worker 	if (right == NULL) {
7762*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, ret);
7763*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7764*7c568831SAndroid Build Coastguard Worker 	}
7765*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, right, NULL, 0, 0);
7766*7c568831SAndroid Build Coastguard Worker 	if (ret == NULL)
7767*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7768*7c568831SAndroid Build Coastguard Worker     }
7769*7c568831SAndroid Build Coastguard Worker     return(ret);
7770*7c568831SAndroid Build Coastguard Worker }
7771*7c568831SAndroid Build Coastguard Worker 
7772*7c568831SAndroid Build Coastguard Worker static xmlExpNodePtr
xmlExpParseExpr(xmlExpCtxtPtr ctxt)7773*7c568831SAndroid Build Coastguard Worker xmlExpParseExpr(xmlExpCtxtPtr ctxt) {
7774*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr ret, right;
7775*7c568831SAndroid Build Coastguard Worker 
7776*7c568831SAndroid Build Coastguard Worker     ret = xmlExpParseSeq(ctxt);
7777*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS
7778*7c568831SAndroid Build Coastguard Worker     while (CUR == ',') {
7779*7c568831SAndroid Build Coastguard Worker         NEXT
7780*7c568831SAndroid Build Coastguard Worker 	right = xmlExpParseSeq(ctxt);
7781*7c568831SAndroid Build Coastguard Worker 	if (right == NULL) {
7782*7c568831SAndroid Build Coastguard Worker 	    xmlExpFree(ctxt, ret);
7783*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7784*7c568831SAndroid Build Coastguard Worker 	}
7785*7c568831SAndroid Build Coastguard Worker 	ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, right, NULL, 0, 0);
7786*7c568831SAndroid Build Coastguard Worker 	if (ret == NULL)
7787*7c568831SAndroid Build Coastguard Worker 	    return(NULL);
7788*7c568831SAndroid Build Coastguard Worker     }
7789*7c568831SAndroid Build Coastguard Worker     return(ret);
7790*7c568831SAndroid Build Coastguard Worker }
7791*7c568831SAndroid Build Coastguard Worker 
7792*7c568831SAndroid Build Coastguard Worker /**
7793*7c568831SAndroid Build Coastguard Worker  * xmlExpParse:
7794*7c568831SAndroid Build Coastguard Worker  * @ctxt: the expressions context
7795*7c568831SAndroid Build Coastguard Worker  * @expr: the 0 terminated string
7796*7c568831SAndroid Build Coastguard Worker  *
7797*7c568831SAndroid Build Coastguard Worker  * Minimal parser for regexps, it understand the following constructs
7798*7c568831SAndroid Build Coastguard Worker  *  - string terminals
7799*7c568831SAndroid Build Coastguard Worker  *  - choice operator |
7800*7c568831SAndroid Build Coastguard Worker  *  - sequence operator ,
7801*7c568831SAndroid Build Coastguard Worker  *  - subexpressions (...)
7802*7c568831SAndroid Build Coastguard Worker  *  - usual cardinality operators + * and ?
7803*7c568831SAndroid Build Coastguard Worker  *  - finite sequences  { min, max }
7804*7c568831SAndroid Build Coastguard Worker  *  - infinite sequences { min, * }
7805*7c568831SAndroid Build Coastguard Worker  * There is minimal checkings made especially no checking on strings values
7806*7c568831SAndroid Build Coastguard Worker  *
7807*7c568831SAndroid Build Coastguard Worker  * Returns a new expression or NULL in case of failure
7808*7c568831SAndroid Build Coastguard Worker  */
7809*7c568831SAndroid Build Coastguard Worker xmlExpNodePtr
xmlExpParse(xmlExpCtxtPtr ctxt,const char * expr)7810*7c568831SAndroid Build Coastguard Worker xmlExpParse(xmlExpCtxtPtr ctxt, const char *expr) {
7811*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr ret;
7812*7c568831SAndroid Build Coastguard Worker 
7813*7c568831SAndroid Build Coastguard Worker     ctxt->expr = expr;
7814*7c568831SAndroid Build Coastguard Worker     ctxt->cur = expr;
7815*7c568831SAndroid Build Coastguard Worker 
7816*7c568831SAndroid Build Coastguard Worker     ret = xmlExpParseExpr(ctxt);
7817*7c568831SAndroid Build Coastguard Worker     SKIP_BLANKS
7818*7c568831SAndroid Build Coastguard Worker     if (*ctxt->cur != 0) {
7819*7c568831SAndroid Build Coastguard Worker         xmlExpFree(ctxt, ret);
7820*7c568831SAndroid Build Coastguard Worker         return(NULL);
7821*7c568831SAndroid Build Coastguard Worker     }
7822*7c568831SAndroid Build Coastguard Worker     return(ret);
7823*7c568831SAndroid Build Coastguard Worker }
7824*7c568831SAndroid Build Coastguard Worker 
7825*7c568831SAndroid Build Coastguard Worker static void
xmlExpDumpInt(xmlBufferPtr buf,xmlExpNodePtr expr,int glob)7826*7c568831SAndroid Build Coastguard Worker xmlExpDumpInt(xmlBufferPtr buf, xmlExpNodePtr expr, int glob) {
7827*7c568831SAndroid Build Coastguard Worker     xmlExpNodePtr c;
7828*7c568831SAndroid Build Coastguard Worker 
7829*7c568831SAndroid Build Coastguard Worker     if (expr == NULL) return;
7830*7c568831SAndroid Build Coastguard Worker     if (glob) xmlBufferWriteChar(buf, "(");
7831*7c568831SAndroid Build Coastguard Worker     switch (expr->type) {
7832*7c568831SAndroid Build Coastguard Worker         case XML_EXP_EMPTY:
7833*7c568831SAndroid Build Coastguard Worker 	    xmlBufferWriteChar(buf, "empty");
7834*7c568831SAndroid Build Coastguard Worker 	    break;
7835*7c568831SAndroid Build Coastguard Worker         case XML_EXP_FORBID:
7836*7c568831SAndroid Build Coastguard Worker 	    xmlBufferWriteChar(buf, "forbidden");
7837*7c568831SAndroid Build Coastguard Worker 	    break;
7838*7c568831SAndroid Build Coastguard Worker         case XML_EXP_ATOM:
7839*7c568831SAndroid Build Coastguard Worker 	    xmlBufferWriteCHAR(buf, expr->exp_str);
7840*7c568831SAndroid Build Coastguard Worker 	    break;
7841*7c568831SAndroid Build Coastguard Worker         case XML_EXP_SEQ:
7842*7c568831SAndroid Build Coastguard Worker 	    c = expr->exp_left;
7843*7c568831SAndroid Build Coastguard Worker 	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
7844*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 1);
7845*7c568831SAndroid Build Coastguard Worker 	    else
7846*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 0);
7847*7c568831SAndroid Build Coastguard Worker 	    xmlBufferWriteChar(buf, " , ");
7848*7c568831SAndroid Build Coastguard Worker 	    c = expr->exp_right;
7849*7c568831SAndroid Build Coastguard Worker 	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
7850*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 1);
7851*7c568831SAndroid Build Coastguard Worker 	    else
7852*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 0);
7853*7c568831SAndroid Build Coastguard Worker             break;
7854*7c568831SAndroid Build Coastguard Worker         case XML_EXP_OR:
7855*7c568831SAndroid Build Coastguard Worker 	    c = expr->exp_left;
7856*7c568831SAndroid Build Coastguard Worker 	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
7857*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 1);
7858*7c568831SAndroid Build Coastguard Worker 	    else
7859*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 0);
7860*7c568831SAndroid Build Coastguard Worker 	    xmlBufferWriteChar(buf, " | ");
7861*7c568831SAndroid Build Coastguard Worker 	    c = expr->exp_right;
7862*7c568831SAndroid Build Coastguard Worker 	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
7863*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 1);
7864*7c568831SAndroid Build Coastguard Worker 	    else
7865*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 0);
7866*7c568831SAndroid Build Coastguard Worker             break;
7867*7c568831SAndroid Build Coastguard Worker         case XML_EXP_COUNT: {
7868*7c568831SAndroid Build Coastguard Worker 	    char rep[40];
7869*7c568831SAndroid Build Coastguard Worker 
7870*7c568831SAndroid Build Coastguard Worker 	    c = expr->exp_left;
7871*7c568831SAndroid Build Coastguard Worker 	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
7872*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 1);
7873*7c568831SAndroid Build Coastguard Worker 	    else
7874*7c568831SAndroid Build Coastguard Worker 	        xmlExpDumpInt(buf, c, 0);
7875*7c568831SAndroid Build Coastguard Worker 	    if ((expr->exp_min == 0) && (expr->exp_max == 1)) {
7876*7c568831SAndroid Build Coastguard Worker 		rep[0] = '?';
7877*7c568831SAndroid Build Coastguard Worker 		rep[1] = 0;
7878*7c568831SAndroid Build Coastguard Worker 	    } else if ((expr->exp_min == 0) && (expr->exp_max == -1)) {
7879*7c568831SAndroid Build Coastguard Worker 		rep[0] = '*';
7880*7c568831SAndroid Build Coastguard Worker 		rep[1] = 0;
7881*7c568831SAndroid Build Coastguard Worker 	    } else if ((expr->exp_min == 1) && (expr->exp_max == -1)) {
7882*7c568831SAndroid Build Coastguard Worker 		rep[0] = '+';
7883*7c568831SAndroid Build Coastguard Worker 		rep[1] = 0;
7884*7c568831SAndroid Build Coastguard Worker 	    } else if (expr->exp_max == expr->exp_min) {
7885*7c568831SAndroid Build Coastguard Worker 	        snprintf(rep, 39, "{%d}", expr->exp_min);
7886*7c568831SAndroid Build Coastguard Worker 	    } else if (expr->exp_max < 0) {
7887*7c568831SAndroid Build Coastguard Worker 	        snprintf(rep, 39, "{%d,inf}", expr->exp_min);
7888*7c568831SAndroid Build Coastguard Worker 	    } else {
7889*7c568831SAndroid Build Coastguard Worker 	        snprintf(rep, 39, "{%d,%d}", expr->exp_min, expr->exp_max);
7890*7c568831SAndroid Build Coastguard Worker 	    }
7891*7c568831SAndroid Build Coastguard Worker 	    rep[39] = 0;
7892*7c568831SAndroid Build Coastguard Worker 	    xmlBufferWriteChar(buf, rep);
7893*7c568831SAndroid Build Coastguard Worker 	    break;
7894*7c568831SAndroid Build Coastguard Worker 	}
7895*7c568831SAndroid Build Coastguard Worker 	default:
7896*7c568831SAndroid Build Coastguard Worker             break;
7897*7c568831SAndroid Build Coastguard Worker     }
7898*7c568831SAndroid Build Coastguard Worker     if (glob)
7899*7c568831SAndroid Build Coastguard Worker         xmlBufferWriteChar(buf, ")");
7900*7c568831SAndroid Build Coastguard Worker }
7901*7c568831SAndroid Build Coastguard Worker /**
7902*7c568831SAndroid Build Coastguard Worker  * xmlExpDump:
7903*7c568831SAndroid Build Coastguard Worker  * @buf:  a buffer to receive the output
7904*7c568831SAndroid Build Coastguard Worker  * @expr:  the compiled expression
7905*7c568831SAndroid Build Coastguard Worker  *
7906*7c568831SAndroid Build Coastguard Worker  * Serialize the expression as compiled to the buffer
7907*7c568831SAndroid Build Coastguard Worker  */
7908*7c568831SAndroid Build Coastguard Worker void
xmlExpDump(xmlBufferPtr buf,xmlExpNodePtr expr)7909*7c568831SAndroid Build Coastguard Worker xmlExpDump(xmlBufferPtr buf, xmlExpNodePtr expr) {
7910*7c568831SAndroid Build Coastguard Worker     if ((buf == NULL) || (expr == NULL))
7911*7c568831SAndroid Build Coastguard Worker         return;
7912*7c568831SAndroid Build Coastguard Worker     xmlExpDumpInt(buf, expr, 0);
7913*7c568831SAndroid Build Coastguard Worker }
7914*7c568831SAndroid Build Coastguard Worker 
7915*7c568831SAndroid Build Coastguard Worker /**
7916*7c568831SAndroid Build Coastguard Worker  * xmlExpMaxToken:
7917*7c568831SAndroid Build Coastguard Worker  * @expr: a compiled expression
7918*7c568831SAndroid Build Coastguard Worker  *
7919*7c568831SAndroid Build Coastguard Worker  * Indicate the maximum number of input a expression can accept
7920*7c568831SAndroid Build Coastguard Worker  *
7921*7c568831SAndroid Build Coastguard Worker  * Returns the maximum length or -1 in case of error
7922*7c568831SAndroid Build Coastguard Worker  */
7923*7c568831SAndroid Build Coastguard Worker int
xmlExpMaxToken(xmlExpNodePtr expr)7924*7c568831SAndroid Build Coastguard Worker xmlExpMaxToken(xmlExpNodePtr expr) {
7925*7c568831SAndroid Build Coastguard Worker     if (expr == NULL)
7926*7c568831SAndroid Build Coastguard Worker         return(-1);
7927*7c568831SAndroid Build Coastguard Worker     return(expr->c_max);
7928*7c568831SAndroid Build Coastguard Worker }
7929*7c568831SAndroid Build Coastguard Worker 
7930*7c568831SAndroid Build Coastguard Worker /**
7931*7c568831SAndroid Build Coastguard Worker  * xmlExpCtxtNbNodes:
7932*7c568831SAndroid Build Coastguard Worker  * @ctxt: an expression context
7933*7c568831SAndroid Build Coastguard Worker  *
7934*7c568831SAndroid Build Coastguard Worker  * Debugging facility provides the number of allocated nodes at a that point
7935*7c568831SAndroid Build Coastguard Worker  *
7936*7c568831SAndroid Build Coastguard Worker  * Returns the number of nodes in use or -1 in case of error
7937*7c568831SAndroid Build Coastguard Worker  */
7938*7c568831SAndroid Build Coastguard Worker int
xmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt)7939*7c568831SAndroid Build Coastguard Worker xmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt) {
7940*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
7941*7c568831SAndroid Build Coastguard Worker         return(-1);
7942*7c568831SAndroid Build Coastguard Worker     return(ctxt->nb_nodes);
7943*7c568831SAndroid Build Coastguard Worker }
7944*7c568831SAndroid Build Coastguard Worker 
7945*7c568831SAndroid Build Coastguard Worker /**
7946*7c568831SAndroid Build Coastguard Worker  * xmlExpCtxtNbCons:
7947*7c568831SAndroid Build Coastguard Worker  * @ctxt: an expression context
7948*7c568831SAndroid Build Coastguard Worker  *
7949*7c568831SAndroid Build Coastguard Worker  * Debugging facility provides the number of allocated nodes over lifetime
7950*7c568831SAndroid Build Coastguard Worker  *
7951*7c568831SAndroid Build Coastguard Worker  * Returns the number of nodes ever allocated or -1 in case of error
7952*7c568831SAndroid Build Coastguard Worker  */
7953*7c568831SAndroid Build Coastguard Worker int
xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt)7954*7c568831SAndroid Build Coastguard Worker xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt) {
7955*7c568831SAndroid Build Coastguard Worker     if (ctxt == NULL)
7956*7c568831SAndroid Build Coastguard Worker         return(-1);
7957*7c568831SAndroid Build Coastguard Worker     return(ctxt->nb_cons);
7958*7c568831SAndroid Build Coastguard Worker }
7959*7c568831SAndroid Build Coastguard Worker 
7960*7c568831SAndroid Build Coastguard Worker /** DOC_ENABLE */
7961*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_EXPR_ENABLED */
7962*7c568831SAndroid Build Coastguard Worker 
7963*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_REGEXP_ENABLED */
7964