OLD | NEW |
1 /* | 1 /* |
2 * regexp.c: generic and extensible Regular Expression engine | 2 * regexp.c: generic and extensible Regular Expression engine |
3 * | 3 * |
4 * Basically designed with the purpose of compiling regexps for | 4 * Basically designed with the purpose of compiling regexps for |
5 * the variety of validation/shemas mechanisms now available in | 5 * the variety of validation/shemas mechanisms now available in |
6 * XML related specifications these include: | 6 * XML related specifications these include: |
7 * - XML-1.0 DTD validation | 7 * - XML-1.0 DTD validation |
8 * - XML Schemas structure part 1 | 8 * - XML Schemas structure part 1 |
9 * - XML Schemas Datatypes part 2 especially Appendix F | 9 * - XML Schemas Datatypes part 2 especially Appendix F |
10 * - RELAX-NG/TREX i.e. the counter proposal | 10 * - RELAX-NG/TREX i.e. the counter proposal |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 xmlRegTrans *trans; | 226 xmlRegTrans *trans; |
227 /* knowing states ponting to us can speed things up */ | 227 /* knowing states ponting to us can speed things up */ |
228 int maxTransTo; | 228 int maxTransTo; |
229 int nbTransTo; | 229 int nbTransTo; |
230 int *transTo; | 230 int *transTo; |
231 }; | 231 }; |
232 | 232 |
233 typedef struct _xmlAutomata xmlRegParserCtxt; | 233 typedef struct _xmlAutomata xmlRegParserCtxt; |
234 typedef xmlRegParserCtxt *xmlRegParserCtxtPtr; | 234 typedef xmlRegParserCtxt *xmlRegParserCtxtPtr; |
235 | 235 |
| 236 #define AM_AUTOMATA_RNG 1 |
| 237 |
236 struct _xmlAutomata { | 238 struct _xmlAutomata { |
237 xmlChar *string; | 239 xmlChar *string; |
238 xmlChar *cur; | 240 xmlChar *cur; |
239 | 241 |
240 int error; | 242 int error; |
241 int neg; | 243 int neg; |
242 | 244 |
243 xmlRegStatePtr start; | 245 xmlRegStatePtr start; |
244 xmlRegStatePtr end; | 246 xmlRegStatePtr end; |
245 xmlRegStatePtr state; | 247 xmlRegStatePtr state; |
246 | 248 |
247 xmlRegAtomPtr atom; | 249 xmlRegAtomPtr atom; |
248 | 250 |
249 int maxAtoms; | 251 int maxAtoms; |
250 int nbAtoms; | 252 int nbAtoms; |
251 xmlRegAtomPtr *atoms; | 253 xmlRegAtomPtr *atoms; |
252 | 254 |
253 int maxStates; | 255 int maxStates; |
254 int nbStates; | 256 int nbStates; |
255 xmlRegStatePtr *states; | 257 xmlRegStatePtr *states; |
256 | 258 |
257 int maxCounters; | 259 int maxCounters; |
258 int nbCounters; | 260 int nbCounters; |
259 xmlRegCounter *counters; | 261 xmlRegCounter *counters; |
260 | 262 |
261 int determinist; | 263 int determinist; |
262 int negs; | 264 int negs; |
| 265 int flags; |
263 }; | 266 }; |
264 | 267 |
265 struct _xmlRegexp { | 268 struct _xmlRegexp { |
266 xmlChar *string; | 269 xmlChar *string; |
267 int nbStates; | 270 int nbStates; |
268 xmlRegStatePtr *states; | 271 xmlRegStatePtr *states; |
269 int nbAtoms; | 272 int nbAtoms; |
270 xmlRegAtomPtr *atoms; | 273 xmlRegAtomPtr *atoms; |
271 int nbCounters; | 274 int nbCounters; |
272 xmlRegCounter *counters; | 275 xmlRegCounter *counters; |
273 int determinist; | 276 int determinist; |
| 277 int flags; |
274 /* | 278 /* |
275 * That's the compact form for determinists automatas | 279 * That's the compact form for determinists automatas |
276 */ | 280 */ |
277 int nbstates; | 281 int nbstates; |
278 int *compact; | 282 int *compact; |
279 void **transdata; | 283 void **transdata; |
280 int nbstrings; | 284 int nbstrings; |
281 xmlChar **stringMap; | 285 xmlChar **stringMap; |
282 }; | 286 }; |
283 | 287 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 #define REGEXP_ALL_LAX_COUNTER 0x123457 | 350 #define REGEXP_ALL_LAX_COUNTER 0x123457 |
347 | 351 |
348 static void xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top); | 352 static void xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top); |
349 static void xmlRegFreeState(xmlRegStatePtr state); | 353 static void xmlRegFreeState(xmlRegStatePtr state); |
350 static void xmlRegFreeAtom(xmlRegAtomPtr atom); | 354 static void xmlRegFreeAtom(xmlRegAtomPtr atom); |
351 static int xmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr); | 355 static int xmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr); |
352 static int xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint); | 356 static int xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint); |
353 static int xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint, | 357 static int xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint, |
354 int neg, int start, int end, const xmlChar *blockName); | 358 int neg, int start, int end, const xmlChar *blockName); |
355 | 359 |
| 360 void xmlAutomataSetFlags(xmlAutomataPtr am, int flags); |
| 361 |
356 /************************************************************************ | 362 /************************************************************************ |
357 * * | 363 * * |
358 * Regexp memory error handler * | 364 * Regexp memory error handler * |
359 * * | 365 * * |
360 ************************************************************************/ | 366 ************************************************************************/ |
361 /** | 367 /** |
362 * xmlRegexpErrMemory: | 368 * xmlRegexpErrMemory: |
363 * @extra: extra information | 369 * @extra: extra information |
364 * | 370 * |
365 * Handle an out of memory condition | 371 * Handle an out of memory condition |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 } | 433 } |
428 memset(ret, 0, sizeof(xmlRegexp)); | 434 memset(ret, 0, sizeof(xmlRegexp)); |
429 ret->string = ctxt->string; | 435 ret->string = ctxt->string; |
430 ret->nbStates = ctxt->nbStates; | 436 ret->nbStates = ctxt->nbStates; |
431 ret->states = ctxt->states; | 437 ret->states = ctxt->states; |
432 ret->nbAtoms = ctxt->nbAtoms; | 438 ret->nbAtoms = ctxt->nbAtoms; |
433 ret->atoms = ctxt->atoms; | 439 ret->atoms = ctxt->atoms; |
434 ret->nbCounters = ctxt->nbCounters; | 440 ret->nbCounters = ctxt->nbCounters; |
435 ret->counters = ctxt->counters; | 441 ret->counters = ctxt->counters; |
436 ret->determinist = ctxt->determinist; | 442 ret->determinist = ctxt->determinist; |
| 443 ret->flags = ctxt->flags; |
437 if (ret->determinist == -1) { | 444 if (ret->determinist == -1) { |
438 xmlRegexpIsDeterminist(ret); | 445 xmlRegexpIsDeterminist(ret); |
439 } | 446 } |
440 | 447 |
441 if ((ret->determinist != 0) && | 448 if ((ret->determinist != 0) && |
442 (ret->nbCounters == 0) && | 449 (ret->nbCounters == 0) && |
443 (ctxt->negs == 0) && | 450 (ctxt->negs == 0) && |
444 (ret->atoms != NULL) && | 451 (ret->atoms != NULL) && |
445 (ret->atoms[0] != NULL) && | 452 (ret->atoms[0] != NULL) && |
446 (ret->atoms[0]->type == XML_REGEXP_STRING)) { | 453 (ret->atoms[0]->type == XML_REGEXP_STRING)) { |
(...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 #endif | 1569 #endif |
1563 } | 1570 } |
1564 switch (atom->quant) { | 1571 switch (atom->quant) { |
1565 case XML_REGEXP_QUANT_OPT: | 1572 case XML_REGEXP_QUANT_OPT: |
1566 atom->quant = XML_REGEXP_QUANT_ONCE; | 1573 atom->quant = XML_REGEXP_QUANT_ONCE; |
1567 /* | 1574 /* |
1568 * transition done to the state after end of atom. | 1575 * transition done to the state after end of atom. |
1569 * 1. set transition from atom start to new state | 1576 * 1. set transition from atom start to new state |
1570 * 2. set transition from atom end to this state. | 1577 * 2. set transition from atom end to this state. |
1571 */ | 1578 */ |
1572 » » xmlFAGenerateEpsilonTransition(ctxt, atom->start, 0); | 1579 if (to == NULL) { |
1573 » » xmlFAGenerateEpsilonTransition(ctxt, atom->stop, ctxt->state); | 1580 xmlFAGenerateEpsilonTransition(ctxt, atom->start, 0); |
| 1581 xmlFAGenerateEpsilonTransition(ctxt, atom->stop, |
| 1582 ctxt->state); |
| 1583 } else { |
| 1584 xmlFAGenerateEpsilonTransition(ctxt, atom->start, to); |
| 1585 } |
1574 break; | 1586 break; |
1575 case XML_REGEXP_QUANT_MULT: | 1587 case XML_REGEXP_QUANT_MULT: |
1576 atom->quant = XML_REGEXP_QUANT_ONCE; | 1588 atom->quant = XML_REGEXP_QUANT_ONCE; |
1577 xmlFAGenerateEpsilonTransition(ctxt, atom->start, atom->stop); | 1589 xmlFAGenerateEpsilonTransition(ctxt, atom->start, atom->stop); |
1578 xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start); | 1590 xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start); |
1579 break; | 1591 break; |
1580 case XML_REGEXP_QUANT_PLUS: | 1592 case XML_REGEXP_QUANT_PLUS: |
1581 atom->quant = XML_REGEXP_QUANT_ONCE; | 1593 atom->quant = XML_REGEXP_QUANT_ONCE; |
1582 xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start); | 1594 xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start); |
1583 break; | 1595 break; |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 range1 = range2; | 2088 range1 = range2; |
2077 range2 = tmp; | 2089 range2 = tmp; |
2078 } | 2090 } |
2079 if ((range1->type == XML_REGEXP_ANYCHAR) || | 2091 if ((range1->type == XML_REGEXP_ANYCHAR) || |
2080 (range2->type == XML_REGEXP_ANYCHAR)) { | 2092 (range2->type == XML_REGEXP_ANYCHAR)) { |
2081 ret = 1; | 2093 ret = 1; |
2082 } else if ((range1->type == XML_REGEXP_EPSILON) || | 2094 } else if ((range1->type == XML_REGEXP_EPSILON) || |
2083 (range2->type == XML_REGEXP_EPSILON)) { | 2095 (range2->type == XML_REGEXP_EPSILON)) { |
2084 return(0); | 2096 return(0); |
2085 } else if (range1->type == range2->type) { | 2097 } else if (range1->type == range2->type) { |
2086 if ((range1->type != XML_REGEXP_CHARVAL) || | 2098 if (range1->type != XML_REGEXP_CHARVAL) |
2087 » (range1->end < range2->start) || | 2099 ret = 1; |
2088 » (range2->end < range1->start)) | 2100 else if ((range1->end < range2->start) || |
| 2101 » (range2->end < range1->start)) |
| 2102 » ret = 0; |
| 2103 » else |
2089 ret = 1; | 2104 ret = 1; |
2090 else | |
2091 ret = 0; | |
2092 } else if (range1->type == XML_REGEXP_CHARVAL) { | 2105 } else if (range1->type == XML_REGEXP_CHARVAL) { |
2093 int codepoint; | 2106 int codepoint; |
2094 int neg = 0; | 2107 int neg = 0; |
2095 | 2108 |
2096 /* | 2109 /* |
2097 * just check all codepoints in the range for acceptance, | 2110 * just check all codepoints in the range for acceptance, |
2098 * this is usually way cheaper since done only once at | 2111 * this is usually way cheaper since done only once at |
2099 * compilation than testing over and over at runtime or | 2112 * compilation than testing over and over at runtime or |
2100 * pushing too many states when evaluating. | 2113 * pushing too many states when evaluating. |
2101 */ | 2114 */ |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2208 ret = 0; | 2221 ret = 0; |
2209 else { | 2222 else { |
2210 /* safety net ! */ | 2223 /* safety net ! */ |
2211 return(1); | 2224 return(1); |
2212 } | 2225 } |
2213 } | 2226 } |
2214 } | 2227 } |
2215 if (((range1->neg == 0) && (range2->neg != 0)) || | 2228 if (((range1->neg == 0) && (range2->neg != 0)) || |
2216 ((range1->neg != 0) && (range2->neg == 0))) | 2229 ((range1->neg != 0) && (range2->neg == 0))) |
2217 ret = !ret; | 2230 ret = !ret; |
2218 return(1); | 2231 return(ret); |
2219 } | 2232 } |
2220 | 2233 |
2221 /** | 2234 /** |
2222 * xmlFACompareAtomTypes: | 2235 * xmlFACompareAtomTypes: |
2223 * @type1: an atom type | 2236 * @type1: an atom type |
2224 * @type2: an atom type | 2237 * @type2: an atom type |
2225 * | 2238 * |
2226 * Compares two atoms type to check whether they intersect in some ways, | 2239 * Compares two atoms type to check whether they intersect in some ways, |
2227 * this is used by xmlFACompareAtoms only | 2240 * this is used by xmlFACompareAtoms only |
2228 * | 2241 * |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2416 default: | 2429 default: |
2417 break; | 2430 break; |
2418 } | 2431 } |
2419 return(1); | 2432 return(1); |
2420 } | 2433 } |
2421 | 2434 |
2422 /** | 2435 /** |
2423 * xmlFAEqualAtoms: | 2436 * xmlFAEqualAtoms: |
2424 * @atom1: an atom | 2437 * @atom1: an atom |
2425 * @atom2: an atom | 2438 * @atom2: an atom |
| 2439 * @deep: if not set only compare string pointers |
2426 * | 2440 * |
2427 * Compares two atoms to check whether they are the same exactly | 2441 * Compares two atoms to check whether they are the same exactly |
2428 * this is used to remove equivalent transitions | 2442 * this is used to remove equivalent transitions |
2429 * | 2443 * |
2430 * Returns 1 if same and 0 otherwise | 2444 * Returns 1 if same and 0 otherwise |
2431 */ | 2445 */ |
2432 static int | 2446 static int |
2433 xmlFAEqualAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2) { | 2447 xmlFAEqualAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2, int deep) { |
2434 int ret = 0; | 2448 int ret = 0; |
2435 | 2449 |
2436 if (atom1 == atom2) | 2450 if (atom1 == atom2) |
2437 return(1); | 2451 return(1); |
2438 if ((atom1 == NULL) || (atom2 == NULL)) | 2452 if ((atom1 == NULL) || (atom2 == NULL)) |
2439 return(0); | 2453 return(0); |
2440 | 2454 |
2441 if (atom1->type != atom2->type) | 2455 if (atom1->type != atom2->type) |
2442 return(0); | 2456 return(0); |
2443 switch (atom1->type) { | 2457 switch (atom1->type) { |
2444 case XML_REGEXP_EPSILON: | 2458 case XML_REGEXP_EPSILON: |
2445 ret = 0; | 2459 ret = 0; |
2446 break; | 2460 break; |
2447 case XML_REGEXP_STRING: | 2461 case XML_REGEXP_STRING: |
2448 » ret = xmlStrEqual((xmlChar *)atom1->valuep, | 2462 if (!deep) |
2449 » (xmlChar *)atom2->valuep); | 2463 ret = (atom1->valuep == atom2->valuep); |
| 2464 else |
| 2465 ret = xmlStrEqual((xmlChar *)atom1->valuep, |
| 2466 (xmlChar *)atom2->valuep); |
2450 break; | 2467 break; |
2451 case XML_REGEXP_CHARVAL: | 2468 case XML_REGEXP_CHARVAL: |
2452 ret = (atom1->codepoint == atom2->codepoint); | 2469 ret = (atom1->codepoint == atom2->codepoint); |
2453 break; | 2470 break; |
2454 case XML_REGEXP_RANGES: | 2471 case XML_REGEXP_RANGES: |
2455 /* too hard to do in the general case */ | 2472 /* too hard to do in the general case */ |
2456 ret = 0; | 2473 ret = 0; |
2457 default: | 2474 default: |
2458 break; | 2475 break; |
2459 } | 2476 } |
2460 return(ret); | 2477 return(ret); |
2461 } | 2478 } |
2462 | 2479 |
2463 /** | 2480 /** |
2464 * xmlFACompareAtoms: | 2481 * xmlFACompareAtoms: |
2465 * @atom1: an atom | 2482 * @atom1: an atom |
2466 * @atom2: an atom | 2483 * @atom2: an atom |
| 2484 * @deep: if not set only compare string pointers |
2467 * | 2485 * |
2468 * Compares two atoms to check whether they intersect in some ways, | 2486 * Compares two atoms to check whether they intersect in some ways, |
2469 * this is used by xmlFAComputesDeterminism and xmlFARecurseDeterminism only | 2487 * this is used by xmlFAComputesDeterminism and xmlFARecurseDeterminism only |
2470 * | 2488 * |
2471 * Returns 1 if yes and 0 otherwise | 2489 * Returns 1 if yes and 0 otherwise |
2472 */ | 2490 */ |
2473 static int | 2491 static int |
2474 xmlFACompareAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2) { | 2492 xmlFACompareAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2, int deep) { |
2475 int ret = 1; | 2493 int ret = 1; |
2476 | 2494 |
2477 if (atom1 == atom2) | 2495 if (atom1 == atom2) |
2478 return(1); | 2496 return(1); |
2479 if ((atom1 == NULL) || (atom2 == NULL)) | 2497 if ((atom1 == NULL) || (atom2 == NULL)) |
2480 return(0); | 2498 return(0); |
2481 | 2499 |
2482 if ((atom1->type == XML_REGEXP_ANYCHAR) || | 2500 if ((atom1->type == XML_REGEXP_ANYCHAR) || |
2483 (atom2->type == XML_REGEXP_ANYCHAR)) | 2501 (atom2->type == XML_REGEXP_ANYCHAR)) |
2484 return(1); | 2502 return(1); |
2485 | 2503 |
2486 if (atom1->type > atom2->type) { | 2504 if (atom1->type > atom2->type) { |
2487 xmlRegAtomPtr tmp; | 2505 xmlRegAtomPtr tmp; |
2488 tmp = atom1; | 2506 tmp = atom1; |
2489 atom1 = atom2; | 2507 atom1 = atom2; |
2490 atom2 = tmp; | 2508 atom2 = tmp; |
2491 } | 2509 } |
2492 if (atom1->type != atom2->type) { | 2510 if (atom1->type != atom2->type) { |
2493 ret = xmlFACompareAtomTypes(atom1->type, atom2->type); | 2511 ret = xmlFACompareAtomTypes(atom1->type, atom2->type); |
2494 /* if they can't intersect at the type level break now */ | 2512 /* if they can't intersect at the type level break now */ |
2495 if (ret == 0) | 2513 if (ret == 0) |
2496 return(0); | 2514 return(0); |
2497 } | 2515 } |
2498 switch (atom1->type) { | 2516 switch (atom1->type) { |
2499 case XML_REGEXP_STRING: | 2517 case XML_REGEXP_STRING: |
2500 » ret = xmlRegStrEqualWildcard((xmlChar *)atom1->valuep, | 2518 if (!deep) |
2501 » (xmlChar *)atom2->valuep); | 2519 ret = (atom1->valuep != atom2->valuep); |
| 2520 else |
| 2521 ret = xmlRegStrEqualWildcard((xmlChar *)atom1->valuep, |
| 2522 (xmlChar *)atom2->valuep); |
2502 break; | 2523 break; |
2503 case XML_REGEXP_EPSILON: | 2524 case XML_REGEXP_EPSILON: |
2504 goto not_determinist; | 2525 goto not_determinist; |
2505 case XML_REGEXP_CHARVAL: | 2526 case XML_REGEXP_CHARVAL: |
2506 if (atom2->type == XML_REGEXP_CHARVAL) { | 2527 if (atom2->type == XML_REGEXP_CHARVAL) { |
2507 ret = (atom1->codepoint == atom2->codepoint); | 2528 ret = (atom1->codepoint == atom2->codepoint); |
2508 } else { | 2529 } else { |
2509 ret = xmlRegCheckCharacter(atom2, atom1->codepoint); | 2530 ret = xmlRegCheckCharacter(atom2, atom1->codepoint); |
2510 if (ret < 0) | 2531 if (ret < 0) |
2511 ret = 1; | 2532 ret = 1; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2554 * should be called after xmlFAEliminateEpsilonTransitions() | 2575 * should be called after xmlFAEliminateEpsilonTransitions() |
2555 * | 2576 * |
2556 */ | 2577 */ |
2557 static int | 2578 static int |
2558 xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, | 2579 xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, |
2559 int to, xmlRegAtomPtr atom) { | 2580 int to, xmlRegAtomPtr atom) { |
2560 int ret = 1; | 2581 int ret = 1; |
2561 int res; | 2582 int res; |
2562 int transnr, nbTrans; | 2583 int transnr, nbTrans; |
2563 xmlRegTransPtr t1; | 2584 xmlRegTransPtr t1; |
| 2585 int deep = 1; |
2564 | 2586 |
2565 if (state == NULL) | 2587 if (state == NULL) |
2566 return(ret); | 2588 return(ret); |
| 2589 |
| 2590 if (ctxt->flags & AM_AUTOMATA_RNG) |
| 2591 deep = 0; |
| 2592 |
2567 /* | 2593 /* |
2568 * don't recurse on transitions potentially added in the course of | 2594 * don't recurse on transitions potentially added in the course of |
2569 * the elimination. | 2595 * the elimination. |
2570 */ | 2596 */ |
2571 nbTrans = state->nbTrans; | 2597 nbTrans = state->nbTrans; |
2572 for (transnr = 0;transnr < nbTrans;transnr++) { | 2598 for (transnr = 0;transnr < nbTrans;transnr++) { |
2573 t1 = &(state->trans[transnr]); | 2599 t1 = &(state->trans[transnr]); |
2574 /* | 2600 /* |
2575 * check transitions conflicting with the one looked at | 2601 * check transitions conflicting with the one looked at |
2576 */ | 2602 */ |
2577 if (t1->atom == NULL) { | 2603 if (t1->atom == NULL) { |
2578 if (t1->to < 0) | 2604 if (t1->to < 0) |
2579 continue; | 2605 continue; |
2580 res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to], | 2606 res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to], |
2581 to, atom); | 2607 to, atom); |
2582 if (res == 0) { | 2608 if (res == 0) { |
2583 ret = 0; | 2609 ret = 0; |
2584 /* t1->nd = 1; */ | 2610 /* t1->nd = 1; */ |
2585 } | 2611 } |
2586 continue; | 2612 continue; |
2587 } | 2613 } |
2588 if (t1->to != to) | 2614 if (t1->to != to) |
2589 continue; | 2615 continue; |
2590 » if (xmlFACompareAtoms(t1->atom, atom)) { | 2616 » if (xmlFACompareAtoms(t1->atom, atom, deep)) { |
2591 ret = 0; | 2617 ret = 0; |
2592 /* mark the transition as non-deterministic */ | 2618 /* mark the transition as non-deterministic */ |
2593 t1->nd = 1; | 2619 t1->nd = 1; |
2594 } | 2620 } |
2595 } | 2621 } |
2596 return(ret); | 2622 return(ret); |
2597 } | 2623 } |
2598 | 2624 |
2599 /** | 2625 /** |
2600 * xmlFAComputesDeterminism: | 2626 * xmlFAComputesDeterminism: |
2601 * @ctxt: a regexp parser context | 2627 * @ctxt: a regexp parser context |
2602 * | 2628 * |
2603 * Check whether the associated regexp is determinist, | 2629 * Check whether the associated regexp is determinist, |
2604 * should be called after xmlFAEliminateEpsilonTransitions() | 2630 * should be called after xmlFAEliminateEpsilonTransitions() |
2605 * | 2631 * |
2606 */ | 2632 */ |
2607 static int | 2633 static int |
2608 xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) { | 2634 xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) { |
2609 int statenr, transnr; | 2635 int statenr, transnr; |
2610 xmlRegStatePtr state; | 2636 xmlRegStatePtr state; |
2611 xmlRegTransPtr t1, t2, last; | 2637 xmlRegTransPtr t1, t2, last; |
2612 int i; | 2638 int i; |
2613 int ret = 1; | 2639 int ret = 1; |
| 2640 int deep = 1; |
2614 | 2641 |
2615 #ifdef DEBUG_REGEXP_GRAPH | 2642 #ifdef DEBUG_REGEXP_GRAPH |
2616 printf("xmlFAComputesDeterminism\n"); | 2643 printf("xmlFAComputesDeterminism\n"); |
2617 xmlRegPrintCtxt(stdout, ctxt); | 2644 xmlRegPrintCtxt(stdout, ctxt); |
2618 #endif | 2645 #endif |
2619 if (ctxt->determinist != -1) | 2646 if (ctxt->determinist != -1) |
2620 return(ctxt->determinist); | 2647 return(ctxt->determinist); |
2621 | 2648 |
| 2649 if (ctxt->flags & AM_AUTOMATA_RNG) |
| 2650 deep = 0; |
| 2651 |
2622 /* | 2652 /* |
2623 * First cleanup the automata removing cancelled transitions | 2653 * First cleanup the automata removing cancelled transitions |
2624 */ | 2654 */ |
2625 for (statenr = 0;statenr < ctxt->nbStates;statenr++) { | 2655 for (statenr = 0;statenr < ctxt->nbStates;statenr++) { |
2626 state = ctxt->states[statenr]; | 2656 state = ctxt->states[statenr]; |
2627 if (state == NULL) | 2657 if (state == NULL) |
2628 continue; | 2658 continue; |
2629 if (state->nbTrans < 2) | 2659 if (state->nbTrans < 2) |
2630 continue; | 2660 continue; |
2631 for (transnr = 0;transnr < state->nbTrans;transnr++) { | 2661 for (transnr = 0;transnr < state->nbTrans;transnr++) { |
2632 t1 = &(state->trans[transnr]); | 2662 t1 = &(state->trans[transnr]); |
2633 /* | 2663 /* |
2634 * Determinism checks in case of counted or all transitions | 2664 * Determinism checks in case of counted or all transitions |
2635 * will have to be handled separately | 2665 * will have to be handled separately |
2636 */ | 2666 */ |
2637 if (t1->atom == NULL) { | 2667 if (t1->atom == NULL) { |
2638 /* t1->nd = 1; */ | 2668 /* t1->nd = 1; */ |
2639 continue; | 2669 continue; |
2640 } | 2670 } |
2641 if (t1->to == -1) /* eliminated */ | 2671 if (t1->to == -1) /* eliminated */ |
2642 continue; | 2672 continue; |
2643 for (i = 0;i < transnr;i++) { | 2673 for (i = 0;i < transnr;i++) { |
2644 t2 = &(state->trans[i]); | 2674 t2 = &(state->trans[i]); |
2645 if (t2->to == -1) /* eliminated */ | 2675 if (t2->to == -1) /* eliminated */ |
2646 continue; | 2676 continue; |
2647 if (t2->atom != NULL) { | 2677 if (t2->atom != NULL) { |
2648 if (t1->to == t2->to) { | 2678 if (t1->to == t2->to) { |
2649 » » » if (xmlFAEqualAtoms(t1->atom, t2->atom)) | 2679 /* |
| 2680 * Here we use deep because we want to keep the |
| 2681 * transitions which indicate a conflict |
| 2682 */ |
| 2683 » » » if (xmlFAEqualAtoms(t1->atom, t2->atom, deep) && |
| 2684 (t1->counter == t2->counter) && |
| 2685 (t1->count == t2->count)) |
2650 t2->to = -1; /* eliminated */ | 2686 t2->to = -1; /* eliminated */ |
2651 } | 2687 } |
2652 } | 2688 } |
2653 } | 2689 } |
2654 } | 2690 } |
2655 } | 2691 } |
2656 | 2692 |
2657 /* | 2693 /* |
2658 * Check for all states that there aren't 2 transitions | 2694 * Check for all states that there aren't 2 transitions |
2659 * with the same atom and a different target. | 2695 * with the same atom and a different target. |
(...skipping 14 matching lines...) Expand all Loading... |
2674 if (t1->atom == NULL) { | 2710 if (t1->atom == NULL) { |
2675 continue; | 2711 continue; |
2676 } | 2712 } |
2677 if (t1->to == -1) /* eliminated */ | 2713 if (t1->to == -1) /* eliminated */ |
2678 continue; | 2714 continue; |
2679 for (i = 0;i < transnr;i++) { | 2715 for (i = 0;i < transnr;i++) { |
2680 t2 = &(state->trans[i]); | 2716 t2 = &(state->trans[i]); |
2681 if (t2->to == -1) /* eliminated */ | 2717 if (t2->to == -1) /* eliminated */ |
2682 continue; | 2718 continue; |
2683 if (t2->atom != NULL) { | 2719 if (t2->atom != NULL) { |
2684 » » /* not determinist ! */ | 2720 /* |
2685 » » if (xmlFACompareAtoms(t1->atom, t2->atom)) { | 2721 * But here we don't use deep because we want to |
| 2722 * find transitions which indicate a conflict |
| 2723 */ |
| 2724 » » if (xmlFACompareAtoms(t1->atom, t2->atom, 1)) { |
2686 ret = 0; | 2725 ret = 0; |
2687 /* mark the transitions as non-deterministic ones */ | 2726 /* mark the transitions as non-deterministic ones */ |
2688 t1->nd = 1; | 2727 t1->nd = 1; |
2689 t2->nd = 1; | 2728 t2->nd = 1; |
2690 last = t1; | 2729 last = t1; |
2691 } | 2730 } |
2692 } else if (t1->to != -1) { | 2731 } else if (t1->to != -1) { |
2693 /* | 2732 /* |
2694 * do the closure in case of remaining specific | 2733 * do the closure in case of remaining specific |
2695 * epsilon transitions like choices or all | 2734 * epsilon transitions like choices or all |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3155 exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)); | 3194 exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)); |
3156 if (exec->counts == NULL) { | 3195 if (exec->counts == NULL) { |
3157 xmlRegexpErrMemory(NULL, "running regexp"); | 3196 xmlRegexpErrMemory(NULL, "running regexp"); |
3158 return(-1); | 3197 return(-1); |
3159 } | 3198 } |
3160 memset(exec->counts, 0, comp->nbCounters * sizeof(int)); | 3199 memset(exec->counts, 0, comp->nbCounters * sizeof(int)); |
3161 } else | 3200 } else |
3162 exec->counts = NULL; | 3201 exec->counts = NULL; |
3163 while ((exec->status == 0) && | 3202 while ((exec->status == 0) && |
3164 ((exec->inputString[exec->index] != 0) || | 3203 ((exec->inputString[exec->index] != 0) || |
3165 » (exec->state->type != XML_REGEXP_FINAL_STATE))) { | 3204 » ((exec->state != NULL) && |
| 3205 » (exec->state->type != XML_REGEXP_FINAL_STATE)))) { |
3166 xmlRegTransPtr trans; | 3206 xmlRegTransPtr trans; |
3167 xmlRegAtomPtr atom; | 3207 xmlRegAtomPtr atom; |
3168 | 3208 |
3169 /* | 3209 /* |
3170 * If end of input on non-terminal state, rollback, however we may | 3210 * If end of input on non-terminal state, rollback, however we may |
3171 * still have epsilon like transition for counted transitions | 3211 * still have epsilon like transition for counted transitions |
3172 * on counters, in that case don't break too early. Additionally, | 3212 * on counters, in that case don't break too early. Additionally, |
3173 * if we are working on a range like "AB{0,2}", where B is not present, | 3213 * if we are working on a range like "AB{0,2}", where B is not present, |
3174 * we don't want to break. | 3214 * we don't want to break. |
3175 */ | 3215 */ |
(...skipping 1669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4845 ctxt->atom->codepoint = '\r'; | 4885 ctxt->atom->codepoint = '\r'; |
4846 break; | 4886 break; |
4847 case 't': | 4887 case 't': |
4848 ctxt->atom->codepoint = '\t'; | 4888 ctxt->atom->codepoint = '\t'; |
4849 break; | 4889 break; |
4850 default: | 4890 default: |
4851 ctxt->atom->codepoint = cur; | 4891 ctxt->atom->codepoint = cur; |
4852 } | 4892 } |
4853 } | 4893 } |
4854 } else if (ctxt->atom->type == XML_REGEXP_RANGES) { | 4894 } else if (ctxt->atom->type == XML_REGEXP_RANGES) { |
| 4895 switch (cur) { |
| 4896 case 'n': |
| 4897 cur = '\n'; |
| 4898 break; |
| 4899 case 'r': |
| 4900 cur = '\r'; |
| 4901 break; |
| 4902 case 't': |
| 4903 cur = '\t'; |
| 4904 break; |
| 4905 } |
4855 xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, | 4906 xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, |
4856 XML_REGEXP_CHARVAL, cur, cur, NULL); | 4907 XML_REGEXP_CHARVAL, cur, cur, NULL); |
4857 } | 4908 } |
4858 NEXT; | 4909 NEXT; |
4859 } else if ((cur == 's') || (cur == 'S') || (cur == 'i') || (cur == 'I') || | 4910 } else if ((cur == 's') || (cur == 'S') || (cur == 'i') || (cur == 'I') || |
4860 (cur == 'c') || (cur == 'C') || (cur == 'd') || (cur == 'D') || | 4911 (cur == 'c') || (cur == 'C') || (cur == 'd') || (cur == 'D') || |
4861 (cur == 'w') || (cur == 'W')) { | 4912 (cur == 'w') || (cur == 'W')) { |
4862 xmlRegAtomType type = XML_REGEXP_ANYSPACE; | 4913 xmlRegAtomType type = XML_REGEXP_ANYSPACE; |
4863 | 4914 |
4864 switch (cur) { | 4915 switch (cur) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4899 } else if (ctxt->atom->type == XML_REGEXP_RANGES) { | 4950 } else if (ctxt->atom->type == XML_REGEXP_RANGES) { |
4900 xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, | 4951 xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, |
4901 type, 0, 0, NULL); | 4952 type, 0, 0, NULL); |
4902 } | 4953 } |
4903 } else { | 4954 } else { |
4904 ERROR("Wrong escape sequence, misuse of character '\\'"); | 4955 ERROR("Wrong escape sequence, misuse of character '\\'"); |
4905 } | 4956 } |
4906 } | 4957 } |
4907 | 4958 |
4908 /** | 4959 /** |
4909 * xmlFAParseCharRef: | |
4910 * @ctxt: a regexp parser context | |
4911 * | |
4912 * [19] XmlCharRef ::= ( '&#' [0-9]+ ';' ) | (' &#x' [0-9a-fA-F]+ ';' ) | |
4913 */ | |
4914 static int | |
4915 xmlFAParseCharRef(xmlRegParserCtxtPtr ctxt) { | |
4916 int ret = 0, cur; | |
4917 | |
4918 if ((CUR != '&') || (NXT(1) != '#')) | |
4919 return(-1); | |
4920 NEXT; | |
4921 NEXT; | |
4922 cur = CUR; | |
4923 if (cur == 'x') { | |
4924 NEXT; | |
4925 cur = CUR; | |
4926 if (((cur >= '0') && (cur <= '9')) || | |
4927 ((cur >= 'a') && (cur <= 'f')) || | |
4928 ((cur >= 'A') && (cur <= 'F'))) { | |
4929 while (((cur >= '0') && (cur <= '9')) || | |
4930 ((cur >= 'a') && (cur <= 'f')) || | |
4931 ((cur >= 'A') && (cur <= 'F'))) { | |
4932 if ((cur >= '0') && (cur <= '9')) | |
4933 ret = ret * 16 + cur - '0'; | |
4934 else if ((cur >= 'a') && (cur <= 'f')) | |
4935 ret = ret * 16 + 10 + (cur - 'a'); | |
4936 else | |
4937 ret = ret * 16 + 10 + (cur - 'A'); | |
4938 NEXT; | |
4939 cur = CUR; | |
4940 } | |
4941 } else { | |
4942 ERROR("Char ref: expecting [0-9A-F]"); | |
4943 return(-1); | |
4944 } | |
4945 } else { | |
4946 if ((cur >= '0') && (cur <= '9')) { | |
4947 while ((cur >= '0') && (cur <= '9')) { | |
4948 ret = ret * 10 + cur - '0'; | |
4949 NEXT; | |
4950 cur = CUR; | |
4951 } | |
4952 } else { | |
4953 ERROR("Char ref: expecting [0-9]"); | |
4954 return(-1); | |
4955 } | |
4956 } | |
4957 if (cur != ';') { | |
4958 ERROR("Char ref: expecting ';'"); | |
4959 return(-1); | |
4960 } else { | |
4961 NEXT; | |
4962 } | |
4963 return(ret); | |
4964 } | |
4965 | |
4966 /** | |
4967 * xmlFAParseCharRange: | 4960 * xmlFAParseCharRange: |
4968 * @ctxt: a regexp parser context | 4961 * @ctxt: a regexp parser context |
4969 * | 4962 * |
4970 * [17] charRange ::= seRange | XmlCharRef | XmlCharIncDash | 4963 * [17] charRange ::= seRange | XmlCharRef | XmlCharIncDash |
4971 * [18] seRange ::= charOrEsc '-' charOrEsc | 4964 * [18] seRange ::= charOrEsc '-' charOrEsc |
4972 * [20] charOrEsc ::= XmlChar | SingleCharEsc | 4965 * [20] charOrEsc ::= XmlChar | SingleCharEsc |
4973 * [21] XmlChar ::= [^\#x2D#x5B#x5D] | 4966 * [21] XmlChar ::= [^\#x2D#x5B#x5D] |
4974 * [22] XmlCharIncDash ::= [^\#x5B#x5D] | 4967 * [22] XmlCharIncDash ::= [^\#x5B#x5D] |
4975 */ | 4968 */ |
4976 static void | 4969 static void |
4977 xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) { | 4970 xmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) { |
4978 int cur, len; | 4971 int cur, len; |
4979 int start = -1; | 4972 int start = -1; |
4980 int end = -1; | 4973 int end = -1; |
4981 | 4974 |
4982 if (CUR == '\0') { | 4975 if (CUR == '\0') { |
4983 ERROR("Expecting ']'"); | 4976 ERROR("Expecting ']'"); |
4984 return; | 4977 return; |
4985 } | 4978 } |
4986 | 4979 |
4987 if ((CUR == '&') && (NXT(1) == '#')) { | |
4988 end = start = xmlFAParseCharRef(ctxt); | |
4989 xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg, | |
4990 XML_REGEXP_CHARVAL, start, end, NULL); | |
4991 return; | |
4992 } | |
4993 cur = CUR; | 4980 cur = CUR; |
4994 if (cur == '\\') { | 4981 if (cur == '\\') { |
4995 NEXT; | 4982 NEXT; |
4996 cur = CUR; | 4983 cur = CUR; |
4997 switch (cur) { | 4984 switch (cur) { |
4998 case 'n': start = 0xA; break; | 4985 case 'n': start = 0xA; break; |
4999 case 'r': start = 0xD; break; | 4986 case 'r': start = 0xD; break; |
5000 case 't': start = 0x9; break; | 4987 case 't': start = 0x9; break; |
5001 case '\\': case '|': case '.': case '-': case '^': case '?': | 4988 case '\\': case '|': case '.': case '-': case '^': case '?': |
5002 case '*': case '+': case '{': case '}': case '(': case ')': | 4989 case '*': case '+': case '{': case '}': case '(': case ')': |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5526 | 5513 |
5527 for (i = 0;i < am->nbStates;i++) | 5514 for (i = 0;i < am->nbStates;i++) |
5528 xmlRegFreeState(am->states[i]); | 5515 xmlRegFreeState(am->states[i]); |
5529 xmlFree(am->states); | 5516 xmlFree(am->states); |
5530 } | 5517 } |
5531 am->nbAtoms = comp->nbAtoms; | 5518 am->nbAtoms = comp->nbAtoms; |
5532 am->atoms = comp->atoms; | 5519 am->atoms = comp->atoms; |
5533 am->nbStates = comp->nbStates; | 5520 am->nbStates = comp->nbStates; |
5534 am->states = comp->states; | 5521 am->states = comp->states; |
5535 am->determinist = -1; | 5522 am->determinist = -1; |
| 5523 am->flags = comp->flags; |
5536 ret = xmlFAComputesDeterminism(am); | 5524 ret = xmlFAComputesDeterminism(am); |
5537 am->atoms = NULL; | 5525 am->atoms = NULL; |
5538 am->states = NULL; | 5526 am->states = NULL; |
5539 xmlFreeAutomata(am); | 5527 xmlFreeAutomata(am); |
| 5528 comp->determinist = ret; |
5540 return(ret); | 5529 return(ret); |
5541 } | 5530 } |
5542 | 5531 |
5543 /** | 5532 /** |
5544 * xmlRegFreeRegexp: | 5533 * xmlRegFreeRegexp: |
5545 * @regexp: the regexp | 5534 * @regexp: the regexp |
5546 * | 5535 * |
5547 * Free a regexp | 5536 * Free a regexp |
5548 */ | 5537 */ |
5549 void | 5538 void |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5607 if (ctxt->start == NULL) { | 5596 if (ctxt->start == NULL) { |
5608 xmlFreeAutomata(ctxt); | 5597 xmlFreeAutomata(ctxt); |
5609 return(NULL); | 5598 return(NULL); |
5610 } | 5599 } |
5611 ctxt->start->type = XML_REGEXP_START_STATE; | 5600 ctxt->start->type = XML_REGEXP_START_STATE; |
5612 if (xmlRegStatePush(ctxt, ctxt->start) < 0) { | 5601 if (xmlRegStatePush(ctxt, ctxt->start) < 0) { |
5613 xmlRegFreeState(ctxt->start); | 5602 xmlRegFreeState(ctxt->start); |
5614 xmlFreeAutomata(ctxt); | 5603 xmlFreeAutomata(ctxt); |
5615 return(NULL); | 5604 return(NULL); |
5616 } | 5605 } |
| 5606 ctxt->flags = 0; |
5617 | 5607 |
5618 return(ctxt); | 5608 return(ctxt); |
5619 } | 5609 } |
5620 | 5610 |
5621 /** | 5611 /** |
5622 * xmlFreeAutomata: | 5612 * xmlFreeAutomata: |
5623 * @am: an automata | 5613 * @am: an automata |
5624 * | 5614 * |
5625 * Free an automata | 5615 * Free an automata |
5626 */ | 5616 */ |
5627 void | 5617 void |
5628 xmlFreeAutomata(xmlAutomataPtr am) { | 5618 xmlFreeAutomata(xmlAutomataPtr am) { |
5629 if (am == NULL) | 5619 if (am == NULL) |
5630 return; | 5620 return; |
5631 xmlRegFreeParserCtxt(am); | 5621 xmlRegFreeParserCtxt(am); |
5632 } | 5622 } |
5633 | 5623 |
5634 /** | 5624 /** |
| 5625 * xmlAutomataSetFlags: |
| 5626 * @am: an automata |
| 5627 * @flags: a set of internal flags |
| 5628 * |
| 5629 * Set some flags on the automata |
| 5630 */ |
| 5631 void |
| 5632 xmlAutomataSetFlags(xmlAutomataPtr am, int flags) { |
| 5633 if (am == NULL) |
| 5634 return; |
| 5635 am->flags |= flags; |
| 5636 } |
| 5637 |
| 5638 /** |
5635 * xmlAutomataGetInitState: | 5639 * xmlAutomataGetInitState: |
5636 * @am: an automata | 5640 * @am: an automata |
5637 * | 5641 * |
5638 * Initial state lookup | 5642 * Initial state lookup |
5639 * | 5643 * |
5640 * Returns the initial state of the automata | 5644 * Returns the initial state of the automata |
5641 */ | 5645 */ |
5642 xmlAutomataStatePtr | 5646 xmlAutomataStatePtr |
5643 xmlAutomataGetInitState(xmlAutomataPtr am) { | 5647 xmlAutomataGetInitState(xmlAutomataPtr am) { |
5644 if (am == NULL) | 5648 if (am == NULL) |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6310 * Expression handling context * | 6314 * Expression handling context * |
6311 * * | 6315 * * |
6312 ************************************************************************/ | 6316 ************************************************************************/ |
6313 | 6317 |
6314 struct _xmlExpCtxt { | 6318 struct _xmlExpCtxt { |
6315 xmlDictPtr dict; | 6319 xmlDictPtr dict; |
6316 xmlExpNodePtr *table; | 6320 xmlExpNodePtr *table; |
6317 int size; | 6321 int size; |
6318 int nbElems; | 6322 int nbElems; |
6319 int nb_nodes; | 6323 int nb_nodes; |
| 6324 int maxNodes; |
6320 const char *expr; | 6325 const char *expr; |
6321 const char *cur; | 6326 const char *cur; |
6322 int nb_cons; | 6327 int nb_cons; |
6323 int tabSize; | 6328 int tabSize; |
6324 }; | 6329 }; |
6325 | 6330 |
6326 /** | 6331 /** |
6327 * xmlExpNewCtxt: | 6332 * xmlExpNewCtxt: |
6328 * @maxNodes: the maximum number of nodes | 6333 * @maxNodes: the maximum number of nodes |
6329 * @dict: optional dictionnary to use internally | 6334 * @dict: optional dictionnary to use internally |
6330 * | 6335 * |
6331 * Creates a new context for manipulating expressions | 6336 * Creates a new context for manipulating expressions |
6332 * | 6337 * |
6333 * Returns the context or NULL in case of error | 6338 * Returns the context or NULL in case of error |
6334 */ | 6339 */ |
6335 xmlExpCtxtPtr | 6340 xmlExpCtxtPtr |
6336 xmlExpNewCtxt(int maxNodes, xmlDictPtr dict) { | 6341 xmlExpNewCtxt(int maxNodes, xmlDictPtr dict) { |
6337 xmlExpCtxtPtr ret; | 6342 xmlExpCtxtPtr ret; |
6338 int size = 256; | 6343 int size = 256; |
6339 | 6344 |
6340 if (maxNodes <= 4096) | 6345 if (maxNodes <= 4096) |
6341 maxNodes = 4096; | 6346 maxNodes = 4096; |
6342 | 6347 |
6343 ret = (xmlExpCtxtPtr) xmlMalloc(sizeof(xmlExpCtxt)); | 6348 ret = (xmlExpCtxtPtr) xmlMalloc(sizeof(xmlExpCtxt)); |
6344 if (ret == NULL) | 6349 if (ret == NULL) |
6345 return(NULL); | 6350 return(NULL); |
6346 memset(ret, 0, sizeof(xmlExpCtxt)); | 6351 memset(ret, 0, sizeof(xmlExpCtxt)); |
6347 ret->size = size; | 6352 ret->size = size; |
6348 ret->nbElems = 0; | 6353 ret->nbElems = 0; |
| 6354 ret->maxNodes = maxNodes; |
6349 ret->table = xmlMalloc(size * sizeof(xmlExpNodePtr)); | 6355 ret->table = xmlMalloc(size * sizeof(xmlExpNodePtr)); |
6350 if (ret->table == NULL) { | 6356 if (ret->table == NULL) { |
6351 xmlFree(ret); | 6357 xmlFree(ret); |
6352 return(NULL); | 6358 return(NULL); |
6353 } | 6359 } |
6354 memset(ret->table, 0, size * sizeof(xmlExpNodePtr)); | 6360 memset(ret->table, 0, size * sizeof(xmlExpNodePtr)); |
6355 if (dict == NULL) { | 6361 if (dict == NULL) { |
6356 ret->dict = xmlDictCreate(); | 6362 ret->dict = xmlDictCreate(); |
6357 if (ret->dict == NULL) { | 6363 if (ret->dict == NULL) { |
6358 xmlFree(ret->table); | 6364 xmlFree(ret->table); |
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6924 tail: | 6930 tail: |
6925 switch (exp->type) { | 6931 switch (exp->type) { |
6926 case XML_EXP_EMPTY: | 6932 case XML_EXP_EMPTY: |
6927 return(0); | 6933 return(0); |
6928 case XML_EXP_ATOM: | 6934 case XML_EXP_ATOM: |
6929 for (tmp = 0;tmp < nb;tmp++) | 6935 for (tmp = 0;tmp < nb;tmp++) |
6930 if (list[tmp] == exp->exp_str) | 6936 if (list[tmp] == exp->exp_str) |
6931 return(0); | 6937 return(0); |
6932 if (nb >= len) | 6938 if (nb >= len) |
6933 return(-2); | 6939 return(-2); |
6934 » list[nb++] = exp->exp_str; | 6940 » list[nb] = exp->exp_str; |
6935 return(1); | 6941 return(1); |
6936 case XML_EXP_COUNT: | 6942 case XML_EXP_COUNT: |
6937 exp = exp->exp_left; | 6943 exp = exp->exp_left; |
6938 goto tail; | 6944 goto tail; |
6939 case XML_EXP_SEQ: | 6945 case XML_EXP_SEQ: |
6940 case XML_EXP_OR: | 6946 case XML_EXP_OR: |
6941 tmp = xmlExpGetLanguageInt(ctxt, exp->exp_left, list, len, nb); | 6947 tmp = xmlExpGetLanguageInt(ctxt, exp->exp_left, list, len, nb); |
6942 if (tmp < 0) | 6948 if (tmp < 0) |
6943 return(tmp); | 6949 return(tmp); |
6944 tmp2 = xmlExpGetLanguageInt(ctxt, exp->exp_right, list, len, | 6950 tmp2 = xmlExpGetLanguageInt(ctxt, exp->exp_right, list, len, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6979 case XML_EXP_FORBID: | 6985 case XML_EXP_FORBID: |
6980 return(0); | 6986 return(0); |
6981 case XML_EXP_EMPTY: | 6987 case XML_EXP_EMPTY: |
6982 return(0); | 6988 return(0); |
6983 case XML_EXP_ATOM: | 6989 case XML_EXP_ATOM: |
6984 for (tmp = 0;tmp < nb;tmp++) | 6990 for (tmp = 0;tmp < nb;tmp++) |
6985 if (list[tmp] == exp->exp_str) | 6991 if (list[tmp] == exp->exp_str) |
6986 return(0); | 6992 return(0); |
6987 if (nb >= len) | 6993 if (nb >= len) |
6988 return(-2); | 6994 return(-2); |
6989 » list[nb++] = exp->exp_str; | 6995 » list[nb] = exp->exp_str; |
6990 return(1); | 6996 return(1); |
6991 case XML_EXP_COUNT: | 6997 case XML_EXP_COUNT: |
6992 exp = exp->exp_left; | 6998 exp = exp->exp_left; |
6993 goto tail; | 6999 goto tail; |
6994 case XML_EXP_SEQ: | 7000 case XML_EXP_SEQ: |
6995 tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb); | 7001 tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb); |
6996 if (tmp < 0) | 7002 if (tmp < 0) |
6997 return(tmp); | 7003 return(tmp); |
6998 if (IS_NILLABLE(exp->exp_left)) { | 7004 if (IS_NILLABLE(exp->exp_left)) { |
6999 tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len, | 7005 tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len, |
(...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8138 xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt) { | 8144 xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt) { |
8139 if (ctxt == NULL) | 8145 if (ctxt == NULL) |
8140 return(-1); | 8146 return(-1); |
8141 return(ctxt->nb_cons); | 8147 return(ctxt->nb_cons); |
8142 } | 8148 } |
8143 | 8149 |
8144 #endif /* LIBXML_EXPR_ENABLED */ | 8150 #endif /* LIBXML_EXPR_ENABLED */ |
8145 #define bottom_xmlregexp | 8151 #define bottom_xmlregexp |
8146 #include "elfgcchack.h" | 8152 #include "elfgcchack.h" |
8147 #endif /* LIBXML_REGEXP_ENABLED */ | 8153 #endif /* LIBXML_REGEXP_ENABLED */ |
OLD | NEW |