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