xmlregexp.c revision 9543aee99b39f4de58641a66a5747cadd279d0b0
14255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/*
24255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * regexp.c: generic and extensible Regular Expression engine
34255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
44255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Basically designed with the purpose of compiling regexps for
54255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * the variety of validation/shemas mechanisms now available in
6ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * XML related specifications these include:
74255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *    - XML-1.0 DTD validation
84255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *    - XML Schemas structure part 1
94255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *    - XML Schemas Datatypes part 2 especially Appendix F
104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *    - RELAX-NG/TREX i.e. the counter proposal
114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * See Copyright for the status of this software.
134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Daniel Veillard <veillard@redhat.com>
154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define IN_LIBXML
184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include "libxml.h"
194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef LIBXML_REGEXP_ENABLED
214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
22cee2b3a5f124e19db46109132c22e1b8faec1c87Daniel Veillard/* #define DEBUG_ERR */
23fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <stdio.h>
254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <string.h>
26ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard#ifdef HAVE_LIMITS_H
27ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard#include <limits.h>
28ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard#endif
29ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard
304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/tree.h>
314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/parserInternals.h>
324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/xmlregexp.h>
334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/xmlautomata.h>
344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#include <libxml/xmlunicode.h>
354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
36ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard#ifndef INT_MAX
37ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard#define INT_MAX 123456789 /* easy to flag and big enough for our needs */
38ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard#endif
39ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard
40c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard/* #define DEBUG_REGEXP_GRAPH */
4110752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard/* #define DEBUG_REGEXP_EXEC */
424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/* #define DEBUG_PUSH */
4323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard/* #define DEBUG_COMPACTION */
444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard#define MAX_PUSH 10000000
4694cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard
47ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard#define ERROR(str)							\
48ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    ctxt->error = XML_REGEXP_COMPILE_ERROR;				\
49ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    xmlRegexpErrCompile(ctxt, str);
504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define NEXT ctxt->cur++
514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define CUR (*(ctxt->cur))
524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define NXT(index) (ctxt->cur[index])
534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#define NEXTL(l) ctxt->cur += l;
56c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard#define XML_REG_STRING_SEPARATOR '|'
57a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack/*
58a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack * Need PREV to check on a '-' within a Character Group. May only be used
59a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack * when it's guaranteed that cur is not at the beginning of ctxt->string!
60a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack */
61a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack#define PREV (ctxt->cur[-1])
624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
63e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
64e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * TODO:
65e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
66e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * macro to flag unimplemented blocks
67e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
68e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard#define TODO 								\
69e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    xmlGenericError(xmlGenericErrorContext,				\
70e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    "Unimplemented block at %s:%d\n",				\
71e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard            __FILE__, __LINE__);
72e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 			Datatypes and structures			*
764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
79fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard/*
80fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Note: the order of the enums below is significant, do not shuffle
81fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard */
824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef enum {
834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_EPSILON = 1,
844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_CHARVAL,
854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_RANGES,
86567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    XML_REGEXP_SUBREG,  /* used for () sub regexps */
874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_STRING,
884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_ANYCHAR, /* . */
894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_ANYSPACE, /* \s */
904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_NOTSPACE, /* \S */
914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_INITNAME, /* \l */
92567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    XML_REGEXP_NOTINITNAME, /* \L */
934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_NAMECHAR, /* \c */
944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_NOTNAMECHAR, /* \C */
954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_DECIMAL, /* \d */
96567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    XML_REGEXP_NOTDECIMAL, /* \D */
974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_REALCHAR, /* \w */
98567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    XML_REGEXP_NOTREALCHAR, /* \W */
99567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    XML_REGEXP_LETTER = 100,
1004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_LETTER_UPPERCASE,
1014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_LETTER_LOWERCASE,
1024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_LETTER_TITLECASE,
1034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_LETTER_MODIFIER,
1044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_LETTER_OTHERS,
1054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_MARK,
1064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_MARK_NONSPACING,
1074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_MARK_SPACECOMBINING,
1084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_MARK_ENCLOSING,
1094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_NUMBER,
1104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_NUMBER_DECIMAL,
1114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_NUMBER_LETTER,
1124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_NUMBER_OTHERS,
1134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_PUNCT,
1144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_PUNCT_CONNECTOR,
1154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_PUNCT_DASH,
1164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_PUNCT_OPEN,
1174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_PUNCT_CLOSE,
1184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_PUNCT_INITQUOTE,
1194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_PUNCT_FINQUOTE,
1204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_PUNCT_OTHERS,
1214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SEPAR,
1224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SEPAR_SPACE,
1234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SEPAR_LINE,
1244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SEPAR_PARA,
1254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SYMBOL,
1264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SYMBOL_MATH,
1274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SYMBOL_CURRENCY,
1284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SYMBOL_MODIFIER,
1294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_SYMBOL_OTHERS,
1304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_OTHER,
1314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_OTHER_CONTROL,
1324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_OTHER_FORMAT,
1334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_OTHER_PRIVATE,
1344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_OTHER_NA,
1354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_BLOCK_NAME
1364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard} xmlRegAtomType;
1374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef enum {
1394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_QUANT_EPSILON = 1,
1404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_QUANT_ONCE,
1414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_QUANT_OPT,
1424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_QUANT_MULT,
1434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_QUANT_PLUS,
1447646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    XML_REGEXP_QUANT_ONCEONLY,
1457646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    XML_REGEXP_QUANT_ALL,
1464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_QUANT_RANGE
1474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard} xmlRegQuantType;
1484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef enum {
1504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_START_STATE = 1,
1514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_FINAL_STATE,
152cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    XML_REGEXP_TRANS_STATE,
1530e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard    XML_REGEXP_SINK_STATE,
1540e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard    XML_REGEXP_UNREACH_STATE
1554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard} xmlRegStateType;
1564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef enum {
1584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_MARK_NORMAL = 0,
1594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_MARK_START,
1604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    XML_REGEXP_MARK_VISITED
1614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard} xmlRegMarkedType;
1624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlRegRange xmlRegRange;
1644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlRegRange *xmlRegRangePtr;
1654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlRegRange {
167f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard    int neg;		/* 0 normal, 1 not, 2 exclude */
1684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomType type;
1694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int start;
1704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int end;
1714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlChar *blockName;
1724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
1734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlRegAtom xmlRegAtom;
1754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlRegAtom *xmlRegAtomPtr;
1764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlAutomataState xmlRegState;
1784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlRegState *xmlRegStatePtr;
1794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlRegAtom {
1814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int no;
1824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomType type;
1834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegQuantType quant;
1844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int min;
1854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int max;
1864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    void *valuep;
188a646cfdb14097f72d3b0ce9b0f43126934d8efd3Daniel Veillard    void *valuep2;
1894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int neg;
1904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int codepoint;
1914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr start;
19276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    xmlRegStatePtr start0;
1934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr stop;
1944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int maxRanges;
1954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbRanges;
1964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegRangePtr *ranges;
1974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    void *data;
1984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
1994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlRegCounter xmlRegCounter;
2014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlRegCounter *xmlRegCounterPtr;
2024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlRegCounter {
2044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int min;
2054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int max;
2064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
2074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlRegTrans xmlRegTrans;
2094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlRegTrans *xmlRegTransPtr;
2104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlRegTrans {
2124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
2134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int to;
2144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int counter;
2154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int count;
216567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    int nd;
2174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
2184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlAutomataState {
2204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStateType type;
2214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegMarkedType mark;
22223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    xmlRegMarkedType reached;
2234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int no;
2244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int maxTrans;
2254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbTrans;
2264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegTrans *trans;
227db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    /*  knowing states ponting to us can speed things up */
228db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    int maxTransTo;
229db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    int nbTransTo;
230db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    int *transTo;
2314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
2324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlAutomata xmlRegParserCtxt;
2344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlRegParserCtxt *xmlRegParserCtxtPtr;
2354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2361ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard#define AM_AUTOMATA_RNG 1
2371ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
2384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlAutomata {
2394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlChar *string;
2404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlChar *cur;
2414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int error;
2434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int neg;
2444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr start;
2464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr end;
2474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr state;
2484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
2504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int maxAtoms;
2524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbAtoms;
2534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr *atoms;
2544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int maxStates;
2564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbStates;
2574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr *states;
2584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int maxCounters;
2604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbCounters;
2614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegCounter *counters;
262e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
263e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int determinist;
2646e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    int negs;
2651ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    int flags;
2664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
2674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlRegexp {
2694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlChar *string;
2704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbStates;
2714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr *states;
2724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbAtoms;
2734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr *atoms;
2744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbCounters;
2754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegCounter *counters;
276e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int determinist;
2771ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    int flags;
27823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    /*
27923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     * That's the compact form for determinists automatas
28023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     */
28123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int nbstates;
28223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int *compact;
283118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    void **transdata;
28423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int nbstrings;
28523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    xmlChar **stringMap;
2864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
2874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlRegExecRollback xmlRegExecRollback;
2894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlRegExecRollback *xmlRegExecRollbackPtr;
2904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlRegExecRollback {
2924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr state;/* the current state */
2934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int index;		/* the index in the input stack */
2944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nextbranch;	/* the next transition to explore in that state */
295ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack    int *counts;	/* save the automata state if it has some */
2964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
2974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef struct _xmlRegInputToken xmlRegInputToken;
2994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardtypedef xmlRegInputToken *xmlRegInputTokenPtr;
3004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlRegInputToken {
3024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlChar *value;
3034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    void *data;
3044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
3054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstruct _xmlRegExecCtxt {
3074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int status;		/* execution status != 0 indicate an error */
308ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack    int determinist;	/* did we find an indeterministic behaviour */
3094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegexpPtr comp;	/* the compiled regexp */
3104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegExecCallbacks callback;
3114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    void *data;
3124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr state;/* the current state */
3144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int transno;	/* the current transition on that state */
315ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack    int transcount;	/* the number of chars in char counted transitions */
3164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /*
3184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * A stack of rollback states
3194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     */
3204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int maxRollbacks;
3214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int nbRollbacks;
3224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegExecRollback *rollbacks;
3234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /*
3254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * The state of the automata if any
3264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     */
3274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int *counts;
3284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /*
3304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * The input stack
3314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     */
3324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int inputStackMax;
3334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int inputStackNr;
3344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int index;
3354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int *charStack;
3364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    const xmlChar *inputString; /* when operating on characters */
3374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegInputTokenPtr inputStack;/* when operating on strings */
3384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3397bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    /*
3407bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard     * error handling
3417bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard     */
3427bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    int errStateNo;		/* the error state number */
3437bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    xmlRegStatePtr errState;    /* the error state */
3447bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    xmlChar *errString;		/* the string raising the error */
3457bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    int *errCounts;		/* counters at the error state */
34694cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    int nbPush;
3474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard};
3484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
349441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard#define REGEXP_ALL_COUNTER	0x123456
350441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard#define REGEXP_ALL_LAX_COUNTER	0x123457
3517646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
3524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top);
35323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillardstatic void xmlRegFreeState(xmlRegStatePtr state);
35423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillardstatic void xmlRegFreeAtom(xmlRegAtomPtr atom);
3559efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillardstatic int xmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr);
356567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillardstatic int xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint);
357567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillardstatic int xmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint,
358567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard                  int neg, int start, int end, const xmlChar *blockName);
3594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3601ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillardvoid xmlAutomataSetFlags(xmlAutomataPtr am, int flags);
3611ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
3624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
363ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard *									*
364ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard * 		Regexp memory error handler				*
365ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard *									*
366ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard ************************************************************************/
367ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard/**
368ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard * xmlRegexpErrMemory:
369ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * @extra:  extra information
370ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard *
371ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard * Handle an out of memory condition
372ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard */
373ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillardstatic void
374ff46a0443e6b999297e52c160b88536b8089ec56Daniel VeillardxmlRegexpErrMemory(xmlRegParserCtxtPtr ctxt, const char *extra)
375ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard{
376ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    const char *regexp = NULL;
377ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    if (ctxt != NULL) {
378ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard        regexp = (const char *) ctxt->string;
379ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	ctxt->error = XML_ERR_NO_MEMORY;
380ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    }
381659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP,
382ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard		    XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, extra,
383ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard		    regexp, NULL, 0, 0,
384ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard		    "Memory allocation failed : %s\n", extra);
385ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard}
386ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard
387ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard/**
388ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard * xmlRegexpErrCompile:
389ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * @extra:  extra information
390ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard *
391ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Handle a compilation failure
392ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard */
393ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillardstatic void
394ff46a0443e6b999297e52c160b88536b8089ec56Daniel VeillardxmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const char *extra)
395ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard{
396ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    const char *regexp = NULL;
397ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    int idx = 0;
398ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard
399ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    if (ctxt != NULL) {
400ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard        regexp = (const char *) ctxt->string;
401ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	idx = ctxt->cur - ctxt->string;
402ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	ctxt->error = XML_REGEXP_COMPILE_ERROR;
403ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard    }
404659e71ec2476d24bfca0d6432a69ef9a49a62be4Daniel Veillard    __xmlRaiseError(NULL, NULL, NULL, NULL, NULL, XML_FROM_REGEXP,
405ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard		    XML_REGEXP_COMPILE_ERROR, XML_ERR_FATAL, NULL, 0, extra,
406ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard		    regexp, NULL, idx, 0,
407ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard		    "failed to compile: %s\n", extra);
408ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard}
409ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard
410ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard/************************************************************************
4114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
4124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 			Allocation/Deallocation				*
4134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
4144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
4154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
41623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillardstatic int xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt);
4174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
4184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegEpxFromParse:
4194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @ctxt:  the parser context used to build it
4204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
421ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Allocate a new regexp and fill it with the result from the parser
4224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
4234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the new regexp or NULL in case of error
4244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
4254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlRegexpPtr
4264255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegEpxFromParse(xmlRegParserCtxtPtr ctxt) {
4274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegexpPtr ret;
4284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
4294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp));
430a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (ret == NULL) {
431ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	xmlRegexpErrMemory(ctxt, "compiling regexp");
4324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
433a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
4344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    memset(ret, 0, sizeof(xmlRegexp));
4354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->string = ctxt->string;
4364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->nbStates = ctxt->nbStates;
4374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->states = ctxt->states;
4384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->nbAtoms = ctxt->nbAtoms;
4394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->atoms = ctxt->atoms;
4404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->nbCounters = ctxt->nbCounters;
4414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->counters = ctxt->counters;
442e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    ret->determinist = ctxt->determinist;
4431ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    ret->flags = ctxt->flags;
444567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (ret->determinist == -1) {
445567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        xmlRegexpIsDeterminist(ret);
446567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
44723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
44823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if ((ret->determinist != 0) &&
44923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	(ret->nbCounters == 0) &&
4506e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard	(ctxt->negs == 0) &&
451118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	(ret->atoms != NULL) &&
45223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	(ret->atoms[0] != NULL) &&
45323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	(ret->atoms[0]->type == XML_REGEXP_STRING)) {
45423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	int i, j, nbstates = 0, nbatoms = 0;
45523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	int *stateRemap;
45623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	int *stringRemap;
45723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	int *transitions;
458118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	void **transdata;
45923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	xmlChar **stringMap;
46023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard        xmlChar *value;
46123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
46223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	/*
46323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * Switch to a compact representation
46423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * 1/ counting the effective number of states left
465ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	 * 2/ counting the unique number of atoms, and check that
46623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 *    they are all of the string type
46723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * 3/ build a table state x atom for the transitions
46823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 */
46923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
47023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	stateRemap = xmlMalloc(ret->nbStates * sizeof(int));
471a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	if (stateRemap == NULL) {
472ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "compiling regexp");
473a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(ret);
474a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(NULL);
475a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	}
47623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	for (i = 0;i < ret->nbStates;i++) {
47723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    if (ret->states[i] != NULL) {
47823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		stateRemap[i] = nbstates;
47923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		nbstates++;
48023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    } else {
48123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		stateRemap[i] = -1;
48223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    }
48323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
48423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_COMPACTION
48523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	printf("Final: %d states\n", nbstates);
48623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
48723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *));
488a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	if (stringMap == NULL) {
489ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "compiling regexp");
490a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(stateRemap);
491a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(ret);
492a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(NULL);
493a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	}
49423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	stringRemap = xmlMalloc(ret->nbAtoms * sizeof(int));
495a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	if (stringRemap == NULL) {
496ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "compiling regexp");
497a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(stringMap);
498a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(stateRemap);
499a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(ret);
500a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(NULL);
501a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	}
50223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	for (i = 0;i < ret->nbAtoms;i++) {
50323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    if ((ret->atoms[i]->type == XML_REGEXP_STRING) &&
50423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		(ret->atoms[i]->quant == XML_REGEXP_QUANT_ONCE)) {
50523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		value = ret->atoms[i]->valuep;
50623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard                for (j = 0;j < nbatoms;j++) {
50723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    if (xmlStrEqual(stringMap[j], value)) {
50823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			stringRemap[i] = j;
50923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			break;
51023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    }
51123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		}
51223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		if (j >= nbatoms) {
51323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    stringRemap[i] = nbatoms;
51423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    stringMap[nbatoms] = xmlStrdup(value);
515a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard		    if (stringMap[nbatoms] == NULL) {
516a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			for (i = 0;i < nbatoms;i++)
517a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			    xmlFree(stringMap[i]);
518a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			xmlFree(stringRemap);
519a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			xmlFree(stringMap);
520a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			xmlFree(stateRemap);
521a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			xmlFree(ret);
522a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			return(NULL);
523a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard		    }
52423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    nbatoms++;
52523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		}
52623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    } else {
52723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		xmlFree(stateRemap);
52823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		xmlFree(stringRemap);
52923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		for (i = 0;i < nbatoms;i++)
53023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    xmlFree(stringMap[i]);
53123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		xmlFree(stringMap);
532a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard		xmlFree(ret);
533a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard		return(NULL);
53423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    }
53523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
53623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_COMPACTION
53723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	printf("Final: %d atoms\n", nbatoms);
53823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
539a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	transitions = (int *) xmlMalloc((nbstates + 1) *
540a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	                                (nbatoms + 1) * sizeof(int));
541a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	if (transitions == NULL) {
542a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(stateRemap);
543a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(stringRemap);
544a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(stringMap);
545a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    xmlFree(ret);
546a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(NULL);
547a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	}
548a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	memset(transitions, 0, (nbstates + 1) * (nbatoms + 1) * sizeof(int));
54923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
55023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	/*
55123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * Allocate the transition table. The first entry for each
552ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	 * state corresponds to the state type.
55323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 */
554118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	transdata = NULL;
55523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
55623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	for (i = 0;i < ret->nbStates;i++) {
55723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    int stateno, atomno, targetno, prev;
55823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    xmlRegStatePtr state;
55923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    xmlRegTransPtr trans;
56023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
56123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    stateno = stateRemap[i];
56223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    if (stateno == -1)
56323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		continue;
56423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    state = ret->states[i];
56523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
56623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    transitions[stateno * (nbatoms + 1)] = state->type;
56723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
56823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    for (j = 0;j < state->nbTrans;j++) {
56923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		trans = &(state->trans[j]);
57023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		if ((trans->to == -1) || (trans->atom == NULL))
57123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    continue;
57223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard                atomno = stringRemap[trans->atom->no];
573118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		if ((trans->atom->data != NULL) && (transdata == NULL)) {
574118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		    transdata = (void **) xmlMalloc(nbstates * nbatoms *
575118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			                            sizeof(void *));
576118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		    if (transdata != NULL)
577118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			memset(transdata, 0,
578118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			       nbstates * nbatoms * sizeof(void *));
579a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard		    else {
580ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard			xmlRegexpErrMemory(ctxt, "compiling regexp");
581a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			break;
582a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard		    }
583118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		}
58423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		targetno = stateRemap[trans->to];
58523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		/*
586ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack		 * if the same atom can generate transitions to 2 different
58723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		 * states then it means the automata is not determinist and
58823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		 * the compact form can't be used !
58923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		 */
59023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		prev = transitions[stateno * (nbatoms + 1) + atomno + 1];
59123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		if (prev != 0) {
59223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    if (prev != targetno + 1) {
59323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			ret->determinist = 0;
59423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_COMPACTION
59523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			printf("Indet: state %d trans %d, atom %d to %d : %d to %d\n",
59623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			       i, j, trans->atom->no, trans->to, atomno, targetno);
59723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			printf("       previous to is %d\n", prev);
59823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
599118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			if (transdata != NULL)
600118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			    xmlFree(transdata);
60123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			xmlFree(transitions);
60223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			xmlFree(stateRemap);
60323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			xmlFree(stringRemap);
60423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			for (i = 0;i < nbatoms;i++)
60523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			    xmlFree(stringMap[i]);
60623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			xmlFree(stringMap);
607a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard			goto not_determ;
60823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    }
60923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		} else {
61023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#if 0
61123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    printf("State %d trans %d: atom %d to %d : %d to %d\n",
61223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard			   i, j, trans->atom->no, trans->to, atomno, targetno);
61323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
61423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    transitions[stateno * (nbatoms + 1) + atomno + 1] =
615118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			targetno + 1; /* to avoid 0 */
616118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		    if (transdata != NULL)
617118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			transdata[stateno * nbatoms + atomno] =
618118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			    trans->atom->data;
61923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		}
62023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    }
62123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
62223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->determinist = 1;
62323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_COMPACTION
62423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	/*
62523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * Debug
62623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 */
62723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	for (i = 0;i < nbstates;i++) {
62823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    for (j = 0;j < nbatoms + 1;j++) {
62923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard                printf("%02d ", transitions[i * (nbatoms + 1) + j]);
63023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    }
63123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    printf("\n");
63223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
63323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	printf("\n");
63423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
63523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	/*
63623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * Cleanup of the old data
63723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 */
63823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	if (ret->states != NULL) {
63923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    for (i = 0;i < ret->nbStates;i++)
64023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		xmlRegFreeState(ret->states[i]);
64123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    xmlFree(ret->states);
64223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
64323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->states = NULL;
64423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->nbStates = 0;
64523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	if (ret->atoms != NULL) {
64623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    for (i = 0;i < ret->nbAtoms;i++)
64723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		xmlRegFreeAtom(ret->atoms[i]);
64823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    xmlFree(ret->atoms);
64923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
65023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->atoms = NULL;
65123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->nbAtoms = 0;
65223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
65323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->compact = transitions;
654118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	ret->transdata = transdata;
65523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->stringMap = stringMap;
65623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->nbstrings = nbatoms;
65723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	ret->nbstates = nbstates;
65823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	xmlFree(stateRemap);
65923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	xmlFree(stringRemap);
66023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
661a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillardnot_determ:
662a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    ctxt->string = NULL;
663a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    ctxt->nbStates = 0;
664a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    ctxt->states = NULL;
665a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    ctxt->nbAtoms = 0;
666a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    ctxt->atoms = NULL;
667a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    ctxt->nbCounters = 0;
668a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    ctxt->counters = NULL;
6694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
6704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
6714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
6724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
6734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegNewParserCtxt:
6744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @string:  the string to parse
6754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
6764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Allocate a new regexp parser context
6774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
6784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the new context or NULL in case of error
6794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
6804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlRegParserCtxtPtr
6814255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegNewParserCtxt(const xmlChar *string) {
6824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegParserCtxtPtr ret;
6834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
6844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = (xmlRegParserCtxtPtr) xmlMalloc(sizeof(xmlRegParserCtxt));
6854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret == NULL)
6864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
6874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    memset(ret, 0, sizeof(xmlRegParserCtxt));
6884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (string != NULL)
6894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ret->string = xmlStrdup(string);
6904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->cur = ret->string;
6914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->neg = 0;
6926e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    ret->negs = 0;
6934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->error = 0;
694e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    ret->determinist = -1;
6954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
6964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
6974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
6984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
6994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegNewRange:
7004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @ctxt:  the regexp parser context
7014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @neg:  is that negative
7024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @type:  the type of range
7034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @start:  the start codepoint
7044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @end:  the end codepoint
7054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
7064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Allocate a new regexp range
7074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
7084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the new range or NULL in case of error
7094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
7104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlRegRangePtr
7114255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegNewRange(xmlRegParserCtxtPtr ctxt,
7124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	       int neg, xmlRegAtomType type, int start, int end) {
7134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegRangePtr ret;
7144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
7154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = (xmlRegRangePtr) xmlMalloc(sizeof(xmlRegRange));
7164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret == NULL) {
717ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	xmlRegexpErrMemory(ctxt, "allocating range");
7184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
7194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
7204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->neg = neg;
7214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->type = type;
7224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->start = start;
7234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->end = end;
7244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
7254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
7264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
7274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
7284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegFreeRange:
7294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @range:  the regexp range
7304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
7314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free a regexp range
7324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
7334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
7344255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegFreeRange(xmlRegRangePtr range) {
7354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (range == NULL)
7364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
7374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
7384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (range->blockName != NULL)
7394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(range->blockName);
7404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(range);
7414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
7424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
7434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
74476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * xmlRegCopyRange:
74576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * @range:  the regexp range
74676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard *
74776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * Copy a regexp range
74876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard *
74976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * Returns the new copy or NULL in case of error.
75076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard */
75176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillardstatic xmlRegRangePtr
75276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel VeillardxmlRegCopyRange(xmlRegParserCtxtPtr ctxt, xmlRegRangePtr range) {
75376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    xmlRegRangePtr ret;
75476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
75576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    if (range == NULL)
75676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	return(NULL);
75776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
75876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    ret = xmlRegNewRange(ctxt, range->neg, range->type, range->start,
75976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard                         range->end);
76076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    if (ret == NULL)
76176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard        return(NULL);
76276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    if (range->blockName != NULL) {
76376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	ret->blockName = xmlStrdup(range->blockName);
76476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	if (ret->blockName == NULL) {
76576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	    xmlRegexpErrMemory(ctxt, "allocating range");
76676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	    xmlRegFreeRange(ret);
76776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	    return(NULL);
76876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	}
76976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    }
77076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    return(ret);
77176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard}
77276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
77376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard/**
7744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegNewAtom:
7754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @ctxt:  the regexp parser context
7764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @type:  the type of atom
7774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
77876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * Allocate a new atom
7794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
7804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the new atom or NULL in case of error
7814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
7824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlRegAtomPtr
7834255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegNewAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomType type) {
7844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr ret;
7854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
7864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom));
7874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret == NULL) {
788ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	xmlRegexpErrMemory(ctxt, "allocating atom");
7894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
7904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
7914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    memset(ret, 0, sizeof(xmlRegAtom));
7924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->type = type;
7934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->quant = XML_REGEXP_QUANT_ONCE;
7944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->min = 0;
7954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->max = 0;
7964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
7974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
7984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
7994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
8004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegFreeAtom:
8014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @atom:  the regexp atom
8024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
8034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free a regexp atom
8044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
8054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
8064255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegFreeAtom(xmlRegAtomPtr atom) {
8074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
8084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
8094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL)
8104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
8114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
8124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < atom->nbRanges;i++)
8134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegFreeRange(atom->ranges[i]);
8144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom->ranges != NULL)
8154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(atom->ranges);
816de0e498b426e8493ab9e7b22a2f88501e96db000Daniel Veillard    if ((atom->type == XML_REGEXP_STRING) && (atom->valuep != NULL))
817de0e498b426e8493ab9e7b22a2f88501e96db000Daniel Veillard	xmlFree(atom->valuep);
81877005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard    if ((atom->type == XML_REGEXP_STRING) && (atom->valuep2 != NULL))
81977005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard	xmlFree(atom->valuep2);
820de0e498b426e8493ab9e7b22a2f88501e96db000Daniel Veillard    if ((atom->type == XML_REGEXP_BLOCK_NAME) && (atom->valuep != NULL))
8214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(atom->valuep);
8224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(atom);
8234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
8244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
82576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard/**
82676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * xmlRegCopyAtom:
82776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * @ctxt:  the regexp parser context
82876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * @atom:  the oiginal atom
82976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard *
83076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * Allocate a new regexp range
83176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard *
83276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard * Returns the new atom or NULL in case of error
83376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard */
83476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillardstatic xmlRegAtomPtr
83576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel VeillardxmlRegCopyAtom(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
83676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    xmlRegAtomPtr ret;
83776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
83876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    ret = (xmlRegAtomPtr) xmlMalloc(sizeof(xmlRegAtom));
83976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    if (ret == NULL) {
84076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	xmlRegexpErrMemory(ctxt, "copying atom");
84176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	return(NULL);
84276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    }
84376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    memset(ret, 0, sizeof(xmlRegAtom));
84476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    ret->type = atom->type;
84576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    ret->quant = atom->quant;
84676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    ret->min = atom->min;
84776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    ret->max = atom->max;
84876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    if (atom->nbRanges > 0) {
84976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard        int i;
85076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
85176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard        ret->ranges = (xmlRegRangePtr *) xmlMalloc(sizeof(xmlRegRangePtr) *
85276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	                                           atom->nbRanges);
85376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	if (ret->ranges == NULL) {
85476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	    xmlRegexpErrMemory(ctxt, "copying atom");
85576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	    goto error;
85676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	}
85776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	for (i = 0;i < atom->nbRanges;i++) {
85876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	    ret->ranges[i] = xmlRegCopyRange(ctxt, atom->ranges[i]);
85976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	    if (ret->ranges[i] == NULL)
86076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	        goto error;
86176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	    ret->nbRanges = i + 1;
86276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	}
86376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    }
86476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    return(ret);
86576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
86676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillarderror:
86776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    xmlRegFreeAtom(ret);
86876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard    return(NULL);
86976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard}
87076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
8714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic xmlRegStatePtr
8724255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegNewState(xmlRegParserCtxtPtr ctxt) {
8734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr ret;
8744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
8754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = (xmlRegStatePtr) xmlMalloc(sizeof(xmlRegState));
8764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret == NULL) {
877ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	xmlRegexpErrMemory(ctxt, "allocating state");
8784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
8794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
8804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    memset(ret, 0, sizeof(xmlRegState));
8814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->type = XML_REGEXP_TRANS_STATE;
8824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret->mark = XML_REGEXP_MARK_NORMAL;
8834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
8844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
8854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
8864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
8874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegFreeState:
8884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @state:  the regexp state
8894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
8904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free a regexp state
8914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
8924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
8934255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegFreeState(xmlRegStatePtr state) {
8944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (state == NULL)
8954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
8964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
8974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (state->trans != NULL)
8984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(state->trans);
899db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    if (state->transTo != NULL)
900db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	xmlFree(state->transTo);
9014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(state);
9024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
9034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
9044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
9054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegFreeParserCtxt:
9064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @ctxt:  the regexp parser context
9074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
9084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free a regexp parser context
9094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
9104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
9114255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegFreeParserCtxt(xmlRegParserCtxtPtr ctxt) {
9124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
9134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt == NULL)
9144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
9154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
9164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->string != NULL)
9174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(ctxt->string);
9184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->states != NULL) {
9194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0;i < ctxt->nbStates;i++)
9204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegFreeState(ctxt->states[i]);
9214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(ctxt->states);
9224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
9234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->atoms != NULL) {
9244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0;i < ctxt->nbAtoms;i++)
9254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegFreeAtom(ctxt->atoms[i]);
9264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(ctxt->atoms);
9274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
9284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->counters != NULL)
9294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(ctxt->counters);
9304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(ctxt);
9314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
9324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
9334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
9344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
9354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 			Display of Data structures			*
9364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
9374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
9384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
9394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
9404255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegPrintAtomType(FILE *output, xmlRegAtomType type) {
9414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (type) {
9424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_EPSILON:
9434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "epsilon "); break;
9444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_CHARVAL:
9454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "charval "); break;
9464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_RANGES:
9474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "ranges "); break;
9484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SUBREG:
9494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "subexpr "); break;
9504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_STRING:
9514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "string "); break;
9524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYCHAR:
9534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "anychar "); break;
9544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYSPACE:
9554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "anyspace "); break;
9564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTSPACE:
9574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "notspace "); break;
9584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_INITNAME:
9594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "initname "); break;
9604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTINITNAME:
9614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "notinitname "); break;
9624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NAMECHAR:
9634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "namechar "); break;
9644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTNAMECHAR:
9654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "notnamechar "); break;
9664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_DECIMAL:
9674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "decimal "); break;
9684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTDECIMAL:
9694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "notdecimal "); break;
9704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_REALCHAR:
9714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "realchar "); break;
9724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTREALCHAR:
9734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "notrealchar "); break;
9744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER:
9754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "LETTER "); break;
9764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_UPPERCASE:
9774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "LETTER_UPPERCASE "); break;
9784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_LOWERCASE:
9794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "LETTER_LOWERCASE "); break;
9804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_TITLECASE:
9814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "LETTER_TITLECASE "); break;
9824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_MODIFIER:
9834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "LETTER_MODIFIER "); break;
9844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_OTHERS:
9854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "LETTER_OTHERS "); break;
9864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK:
9874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "MARK "); break;
9884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_NONSPACING:
9894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "MARK_NONSPACING "); break;
9904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_SPACECOMBINING:
9914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "MARK_SPACECOMBINING "); break;
9924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_ENCLOSING:
9934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "MARK_ENCLOSING "); break;
9944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER:
9954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "NUMBER "); break;
9964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_DECIMAL:
9974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "NUMBER_DECIMAL "); break;
9984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_LETTER:
9994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "NUMBER_LETTER "); break;
10004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_OTHERS:
10014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "NUMBER_OTHERS "); break;
10024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT:
10034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "PUNCT "); break;
10044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CONNECTOR:
10054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "PUNCT_CONNECTOR "); break;
10064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_DASH:
10074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "PUNCT_DASH "); break;
10084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OPEN:
10094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "PUNCT_OPEN "); break;
10104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CLOSE:
10114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "PUNCT_CLOSE "); break;
10124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_INITQUOTE:
10134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "PUNCT_INITQUOTE "); break;
10144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_FINQUOTE:
10154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "PUNCT_FINQUOTE "); break;
10164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OTHERS:
10174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "PUNCT_OTHERS "); break;
10184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR:
10194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SEPAR "); break;
10204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_SPACE:
10214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SEPAR_SPACE "); break;
10224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_LINE:
10234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SEPAR_LINE "); break;
10244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_PARA:
10254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SEPAR_PARA "); break;
10264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL:
10274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SYMBOL "); break;
10284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MATH:
10294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SYMBOL_MATH "); break;
10304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_CURRENCY:
10314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SYMBOL_CURRENCY "); break;
10324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MODIFIER:
10334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SYMBOL_MODIFIER "); break;
10344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_OTHERS:
10354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "SYMBOL_OTHERS "); break;
10364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER:
10374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "OTHER "); break;
10384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_CONTROL:
10394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "OTHER_CONTROL "); break;
10404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_FORMAT:
10414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "OTHER_FORMAT "); break;
10424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_PRIVATE:
10434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "OTHER_PRIVATE "); break;
10444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_NA:
10454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            fprintf(output, "OTHER_NA "); break;
10464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_BLOCK_NAME:
10474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "BLOCK "); break;
10484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
10494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
10504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
10514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
10524255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegPrintQuantType(FILE *output, xmlRegQuantType type) {
10534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (type) {
10544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_QUANT_EPSILON:
10554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "epsilon "); break;
10564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_QUANT_ONCE:
10574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "once "); break;
10584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_QUANT_OPT:
10594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "? "); break;
10604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_QUANT_MULT:
10614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "* "); break;
10624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_QUANT_PLUS:
10634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "+ "); break;
10644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_REGEXP_QUANT_RANGE:
10654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(output, "range "); break;
10667646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	case XML_REGEXP_QUANT_ONCEONLY:
10677646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	    fprintf(output, "onceonly "); break;
10687646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	case XML_REGEXP_QUANT_ALL:
10697646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	    fprintf(output, "all "); break;
10704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
10714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
10724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
10734255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegPrintRange(FILE *output, xmlRegRangePtr range) {
10744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "  range: ");
10754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (range->neg)
10764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "negative ");
10774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegPrintAtomType(output, range->type);
10784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%c - %c\n", range->start, range->end);
10794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
10804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
10814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
10824255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegPrintAtom(FILE *output, xmlRegAtomPtr atom) {
10834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, " atom: ");
10844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL) {
10854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "NULL\n");
10864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
10874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
10889efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if (atom->neg)
10899efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard        fprintf(output, "not ");
10904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegPrintAtomType(output, atom->type);
10914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegPrintQuantType(output, atom->quant);
10924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom->quant == XML_REGEXP_QUANT_RANGE)
10934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "%d-%d ", atom->min, atom->max);
10944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom->type == XML_REGEXP_STRING)
10954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "'%s' ", (char *) atom->valuep);
10964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom->type == XML_REGEXP_CHARVAL)
10974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "char %c\n", atom->codepoint);
10984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else if (atom->type == XML_REGEXP_RANGES) {
10994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int i;
11004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "%d entries\n", atom->nbRanges);
11014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0; i < atom->nbRanges;i++)
11024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegPrintRange(output, atom->ranges[i]);
11034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (atom->type == XML_REGEXP_SUBREG) {
11044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "start %d end %d\n", atom->start->no, atom->stop->no);
11054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
11064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "\n");
11074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
11094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
11104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
11114255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegPrintTrans(FILE *output, xmlRegTransPtr trans) {
11124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "  trans: ");
11134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (trans == NULL) {
11144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "NULL\n");
11154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
11164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (trans->to < 0) {
11184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "removed\n");
11194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
11204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
1121567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (trans->nd != 0) {
1122567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (trans->nd == 2)
1123567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    fprintf(output, "last not determinist, ");
1124567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else
1125567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    fprintf(output, "not determinist, ");
1126567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
11274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (trans->counter >= 0) {
11284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "counted %d, ", trans->counter);
11294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11308a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard    if (trans->count == REGEXP_ALL_COUNTER) {
11318a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard	fprintf(output, "all transition, ");
11328a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard    } else if (trans->count >= 0) {
11334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "count based %d, ", trans->count);
11344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (trans->atom == NULL) {
11364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "epsilon to %d\n", trans->to);
11374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
11384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (trans->atom->type == XML_REGEXP_CHARVAL)
11404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "char %c ", trans->atom->codepoint);
11414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "atom %d, to %d\n", trans->atom->no, trans->to);
11424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
11434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
11444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
11454255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegPrintState(FILE *output, xmlRegStatePtr state) {
11464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
11474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
11484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, " state: ");
11494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (state == NULL) {
11504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "NULL\n");
11514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
11524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (state->type == XML_REGEXP_START_STATE)
11544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "START ");
11554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (state->type == XML_REGEXP_FINAL_STATE)
11564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "FINAL ");
11574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
11584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d, %d transitions:\n", state->no, state->nbTrans);
11594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < state->nbTrans; i++) {
11604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegPrintTrans(output, &(state->trans[i]));
11614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
11634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
116423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
11654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
11664255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegPrintCtxt(FILE *output, xmlRegParserCtxtPtr ctxt) {
11674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
11684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
11694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, " ctxt: ");
11704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt == NULL) {
11714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "NULL\n");
11724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
11734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "'%s' ", ctxt->string);
11754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->error)
11764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "error ");
11774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->neg)
11784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "neg ");
11794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "\n");
11804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d atoms:\n", ctxt->nbAtoms);
11814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < ctxt->nbAtoms; i++) {
11824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, " %02d ", i);
11834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegPrintAtom(output, ctxt->atoms[i]);
11844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->atom != NULL) {
11864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "current atom:\n");
11874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegPrintAtom(output, ctxt->atom);
11884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d states:", ctxt->nbStates);
11904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->start != NULL)
11914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, " start: %d", ctxt->start->no);
11924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->end != NULL)
11934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, " end: %d", ctxt->end->no);
11944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "\n");
11954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < ctxt->nbStates; i++) {
11964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegPrintState(output, ctxt->states[i]);
11974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
11984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d counters:\n", ctxt->nbCounters);
11994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < ctxt->nbCounters; i++) {
12004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, " %d: min %d max %d\n", i, ctxt->counters[i].min,
12014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                                ctxt->counters[i].max);
12024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
12034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
120423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
12054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
12064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
12074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
12084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *		 Finite Automata structures manipulations		*
12094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
12104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
12114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
12124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
12134255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom,
12144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	           int neg, xmlRegAtomType type, int start, int end,
12154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   xmlChar *blockName) {
12164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegRangePtr range;
12174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
12184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL) {
12194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("add range: atom is NULL");
12204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
12214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
12224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom->type != XML_REGEXP_RANGES) {
12234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("add range: atom is not ranges");
12244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
12254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
12264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom->maxRanges == 0) {
12274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	atom->maxRanges = 4;
12284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	atom->ranges = (xmlRegRangePtr *) xmlMalloc(atom->maxRanges *
12294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegRangePtr));
12304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (atom->ranges == NULL) {
1231ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "adding ranges");
12324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom->maxRanges = 0;
12334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
12344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
12354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (atom->nbRanges >= atom->maxRanges) {
12364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegRangePtr *tmp;
12374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	atom->maxRanges *= 2;
12384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegRangePtr *) xmlRealloc(atom->ranges, atom->maxRanges *
12394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegRangePtr));
12404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
1241ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "adding ranges");
12424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom->maxRanges /= 2;
12434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
12444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
12454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	atom->ranges = tmp;
12464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
12474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    range = xmlRegNewRange(ctxt, neg, type, start, end);
12484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (range == NULL)
12494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
12504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    range->blockName = blockName;
12514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->ranges[atom->nbRanges++] = range;
12524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
12534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
12544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
12554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
12564255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegGetCounter(xmlRegParserCtxtPtr ctxt) {
12574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->maxCounters == 0) {
12584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->maxCounters = 4;
12594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->counters = (xmlRegCounter *) xmlMalloc(ctxt->maxCounters *
12604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegCounter));
12614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->counters == NULL) {
1262ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "allocating counter");
12634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->maxCounters = 0;
12644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
12654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
12664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (ctxt->nbCounters >= ctxt->maxCounters) {
12674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegCounter *tmp;
12684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->maxCounters *= 2;
12694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegCounter *) xmlRealloc(ctxt->counters, ctxt->maxCounters *
12704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                           sizeof(xmlRegCounter));
12714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
1272ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "allocating counter");
12734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->maxCounters /= 2;
12744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
12754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
12764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->counters = tmp;
12774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
12784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->counters[ctxt->nbCounters].min = -1;
12794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->counters[ctxt->nbCounters].max = -1;
12804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ctxt->nbCounters++);
12814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
12824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1283a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillardstatic int
12844255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
12854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL) {
12864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("atom push: atom is NULL");
1287a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(-1);
12884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
12894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->maxAtoms == 0) {
12904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->maxAtoms = 4;
12914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atoms = (xmlRegAtomPtr *) xmlMalloc(ctxt->maxAtoms *
12924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegAtomPtr));
12934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atoms == NULL) {
1294ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "pushing atom");
12954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->maxAtoms = 0;
1296a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(-1);
12974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
12984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (ctxt->nbAtoms >= ctxt->maxAtoms) {
12994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegAtomPtr *tmp;
13004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->maxAtoms *= 2;
13014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegAtomPtr *) xmlRealloc(ctxt->atoms, ctxt->maxAtoms *
13024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegAtomPtr));
13034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
1304ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "allocating counter");
13054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->maxAtoms /= 2;
1306a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(-1);
13074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
13084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atoms = tmp;
13094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
13104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->no = ctxt->nbAtoms;
13114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->atoms[ctxt->nbAtoms++] = atom;
1312a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    return(0);
13134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
13144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
13154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
1316db68b74dc7ec531361a736de7769a3e8ce881f79Daniel VeillardxmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target,
1317db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard                      int from) {
1318db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    if (target->maxTransTo == 0) {
1319db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	target->maxTransTo = 8;
1320db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	target->transTo = (int *) xmlMalloc(target->maxTransTo *
1321db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		                             sizeof(int));
1322db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	if (target->transTo == NULL) {
1323db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    xmlRegexpErrMemory(ctxt, "adding transition");
1324db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    target->maxTransTo = 0;
1325db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    return;
1326db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	}
1327db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    } else if (target->nbTransTo >= target->maxTransTo) {
1328db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	int *tmp;
1329db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	target->maxTransTo *= 2;
1330db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	tmp = (int *) xmlRealloc(target->transTo, target->maxTransTo *
1331db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		                             sizeof(int));
1332db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	if (tmp == NULL) {
1333db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    xmlRegexpErrMemory(ctxt, "adding transition");
1334db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    target->maxTransTo /= 2;
1335db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    return;
1336db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	}
1337db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	target->transTo = tmp;
1338db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    }
1339db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    target->transTo[target->nbTransTo] = from;
1340db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    target->nbTransTo++;
1341db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard}
1342db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard
1343db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillardstatic void
13444255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
13454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	            xmlRegAtomPtr atom, xmlRegStatePtr target,
13465de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard		    int counter, int count) {
1347f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack
1348f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack    int nrtrans;
1349f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack
13504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (state == NULL) {
13514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("add state: state is NULL");
13524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
13534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
13544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (target == NULL) {
13554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("add state: target is NULL");
13564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
13574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
1358f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack    /*
1359f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack     * Other routines follow the philosophy 'When in doubt, add a transition'
1360f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack     * so we check here whether such a transition is already present and, if
1361f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack     * so, silently ignore this request.
1362f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack     */
1363f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack
13645de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    for (nrtrans = state->nbTrans - 1; nrtrans >= 0; nrtrans--) {
13655de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	xmlRegTransPtr trans = &(state->trans[nrtrans]);
13665de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	if ((trans->atom == atom) &&
13675de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	    (trans->to == target->no) &&
13685de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	    (trans->counter == counter) &&
13695de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	    (trans->count == count)) {
1370f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack#ifdef DEBUG_REGEXP_GRAPH
13715de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	    printf("Ignoring duplicate transition from %d to %d\n",
13725de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard		    state->no, target->no);
1373f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack#endif
13745de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	    return;
1375db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	}
1376f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack    }
1377f9b5fa2dec22e88683d96d0a2782c244df2ca766William M. Brack
13784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (state->maxTrans == 0) {
1379db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	state->maxTrans = 8;
13804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	state->trans = (xmlRegTrans *) xmlMalloc(state->maxTrans *
13814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegTrans));
13824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (state->trans == NULL) {
1383ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "adding transition");
13844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    state->maxTrans = 0;
13854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
13864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
13874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (state->nbTrans >= state->maxTrans) {
13884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegTrans *tmp;
13894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	state->maxTrans *= 2;
13904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegTrans *) xmlRealloc(state->trans, state->maxTrans *
13914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegTrans));
13924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
1393ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "adding transition");
13944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    state->maxTrans /= 2;
13954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
13964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
13974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	state->trans = tmp;
13984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
13994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
14004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("Add trans from %d to %d ", state->no, target->no);
14018a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard    if (count == REGEXP_ALL_COUNTER)
14022cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	printf("all transition\n");
14034402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard    else if (count >= 0)
14042cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	printf("count based %d\n", count);
14054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else if (counter >= 0)
14062cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	printf("counted %d\n", counter);
14074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else if (atom == NULL)
14082cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	printf("epsilon transition\n");
14092cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    else if (atom != NULL)
14102cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard        xmlRegPrintAtom(stdout, atom);
14114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
14124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
14134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    state->trans[state->nbTrans].atom = atom;
14144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    state->trans[state->nbTrans].to = target->no;
14154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    state->trans[state->nbTrans].counter = counter;
14164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    state->trans[state->nbTrans].count = count;
1417567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    state->trans[state->nbTrans].nd = 0;
14184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    state->nbTrans++;
1419db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    xmlRegStateAddTransTo(ctxt, target, state->no);
14204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
14214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1422a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillardstatic int
14234255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
1424a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (state == NULL) return(-1);
14254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->maxStates == 0) {
14264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->maxStates = 4;
14274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->states = (xmlRegStatePtr *) xmlMalloc(ctxt->maxStates *
14284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegStatePtr));
14294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->states == NULL) {
1430ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "adding state");
14314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->maxStates = 0;
1432a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(-1);
14334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
14344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (ctxt->nbStates >= ctxt->maxStates) {
14354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegStatePtr *tmp;
14364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->maxStates *= 2;
14374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegStatePtr *) xmlRealloc(ctxt->states, ctxt->maxStates *
14384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegStatePtr));
14394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
1440ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(ctxt, "adding state");
14414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->maxStates /= 2;
1442a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(-1);
14434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
14444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->states = tmp;
14454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
14464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    state->no = ctxt->nbStates;
14474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->states[ctxt->nbStates++] = state;
1448a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    return(0);
14494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
14504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
14514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
14527646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * xmlFAGenerateAllTransition:
1453441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
1454441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @from:  the from state
1455441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @to:  the target state or NULL for building a new one
1456441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @lax:
14577646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
14587646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard */
14597646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillardstatic void
14607646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlFAGenerateAllTransition(xmlRegParserCtxtPtr ctxt,
1461441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			   xmlRegStatePtr from, xmlRegStatePtr to,
1462441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			   int lax) {
14637646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (to == NULL) {
14647646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	to = xmlRegNewState(ctxt);
14657646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	xmlRegStatePush(ctxt, to);
14667646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	ctxt->state = to;
14677646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    }
1468441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard    if (lax)
14695de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_LAX_COUNTER);
1470441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard    else
14715de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	xmlRegStateAddTrans(ctxt, from, NULL, to, -1, REGEXP_ALL_COUNTER);
14727646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard}
14737646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
14747646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard/**
14754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAGenerateEpsilonTransition:
1476441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
1477441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @from:  the from state
1478441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @to:  the target state or NULL for building a new one
14794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
14804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
14814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
14824255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAGenerateEpsilonTransition(xmlRegParserCtxtPtr ctxt,
14834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			       xmlRegStatePtr from, xmlRegStatePtr to) {
14844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL) {
14854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	to = xmlRegNewState(ctxt);
14864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegStatePush(ctxt, to);
14874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->state = to;
14884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
14895de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(ctxt, from, NULL, to, -1, -1);
14904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
14914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
14924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
14934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAGenerateCountedEpsilonTransition:
1494441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
1495441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @from:  the from state
1496441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @to:  the target state or NULL for building a new one
14974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * counter:  the counter for that transition
14984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
14994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
15004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
15014255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAGenerateCountedEpsilonTransition(xmlRegParserCtxtPtr ctxt,
15024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegStatePtr from, xmlRegStatePtr to, int counter) {
15034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL) {
15044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	to = xmlRegNewState(ctxt);
15054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegStatePush(ctxt, to);
15064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->state = to;
15074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
15085de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(ctxt, from, NULL, to, counter, -1);
15094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
15104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
15114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
15124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAGenerateCountedTransition:
1513441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
1514441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @from:  the from state
1515441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @to:  the target state or NULL for building a new one
15164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * counter:  the counter for that transition
15174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
15184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
15194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
15204255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAGenerateCountedTransition(xmlRegParserCtxtPtr ctxt,
15214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegStatePtr from, xmlRegStatePtr to, int counter) {
15224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL) {
15234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	to = xmlRegNewState(ctxt);
15244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegStatePush(ctxt, to);
15254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->state = to;
15264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
15275de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(ctxt, from, NULL, to, -1, counter);
15284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
15294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
15304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
15314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAGenerateTransitions:
1532441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
1533441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @from:  the from state
1534441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @to:  the target state or NULL for building a new one
1535441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @atom:  the atom generating the transition
15364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
1537ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Returns 0 if success and -1 in case of error.
15384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
1539a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillardstatic int
15404255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
15414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	                 xmlRegStatePtr to, xmlRegAtomPtr atom) {
154210bda629bf8fe279f02493f0921110c552be3171Daniel Veillard    xmlRegStatePtr end;
154310bda629bf8fe279f02493f0921110c552be3171Daniel Veillard
15444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL) {
15454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("genrate transition: atom == NULL");
1546a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(-1);
15474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
15484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom->type == XML_REGEXP_SUBREG) {
15494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	/*
15504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * this is a subexpression handling one should not need to
1551ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	 * create a new node except for XML_REGEXP_QUANT_RANGE.
15524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 */
1553a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	if (xmlRegAtomPush(ctxt, atom) < 0) {
1554a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(-1);
1555a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	}
15564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((to != NULL) && (atom->stop != to) &&
15574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    (atom->quant != XML_REGEXP_QUANT_RANGE)) {
15584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /*
15594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Generate an epsilon transition to link to the target
15604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     */
15614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to);
1562aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#ifdef DV
1563aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	} else if ((to == NULL) && (atom->quant != XML_REGEXP_QUANT_RANGE) &&
1564aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		   (atom->quant != XML_REGEXP_QUANT_ONCE)) {
1565aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	    to = xmlRegNewState(ctxt);
1566aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	    xmlRegStatePush(ctxt, to);
1567aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	    ctxt->state = to;
1568aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	    xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to);
1569aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#endif
15704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
15714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	switch (atom->quant) {
15724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case XML_REGEXP_QUANT_OPT:
15734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		atom->quant = XML_REGEXP_QUANT_ONCE;
157454eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		/*
157554eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		 * transition done to the state after end of atom.
157654eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		 *      1. set transition from atom start to new state
157754eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		 *      2. set transition from atom end to this state.
157854eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		 */
1579d80d0728bfa1b3b7412aff01e520ecc0b8e3f14fDaniel Veillard                if (to == NULL) {
1580d80d0728bfa1b3b7412aff01e520ecc0b8e3f14fDaniel Veillard                    xmlFAGenerateEpsilonTransition(ctxt, atom->start, 0);
1581d80d0728bfa1b3b7412aff01e520ecc0b8e3f14fDaniel Veillard                    xmlFAGenerateEpsilonTransition(ctxt, atom->stop,
1582d80d0728bfa1b3b7412aff01e520ecc0b8e3f14fDaniel Veillard                                                   ctxt->state);
1583d80d0728bfa1b3b7412aff01e520ecc0b8e3f14fDaniel Veillard                } else {
1584d80d0728bfa1b3b7412aff01e520ecc0b8e3f14fDaniel Veillard                    xmlFAGenerateEpsilonTransition(ctxt, atom->start, to);
1585d80d0728bfa1b3b7412aff01e520ecc0b8e3f14fDaniel Veillard                }
15864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
15874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case XML_REGEXP_QUANT_MULT:
15884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		atom->quant = XML_REGEXP_QUANT_ONCE;
15894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlFAGenerateEpsilonTransition(ctxt, atom->start, atom->stop);
15904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start);
15914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
15924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case XML_REGEXP_QUANT_PLUS:
15934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		atom->quant = XML_REGEXP_QUANT_ONCE;
15944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlFAGenerateEpsilonTransition(ctxt, atom->stop, atom->start);
15954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
15964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case XML_REGEXP_QUANT_RANGE: {
15974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		int counter;
159876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		xmlRegStatePtr inter, newstate;
15994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
16004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		/*
160176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		 * create the final state now if needed
16024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 */
160376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		if (to != NULL) {
160476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    newstate = to;
160576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		} else {
1606ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack		    newstate = xmlRegNewState(ctxt);
1607ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack		    xmlRegStatePush(ctxt, newstate);
160876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		}
160976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
161076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		/*
161176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		 * The principle here is to use counted transition
161276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		 * to avoid explosion in the number of states in the
161376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		 * graph. This is clearly more complex but should not
161476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		 * be exploitable at runtime.
161576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		 */
161676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		if ((atom->min == 0) && (atom->start0 == NULL)) {
161776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    xmlRegAtomPtr copy;
161876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    /*
161976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     * duplicate a transition based on atom to count next
162076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     * occurences after 1. We cannot loop to atom->start
162176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     * directly because we need an epsilon transition to
162276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     * newstate.
162376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     */
162476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     /* ???? For some reason it seems we never reach that
162576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		        case, I suppose this got optimized out before when
162676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard			building the automata */
1627c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    copy = xmlRegCopyAtom(ctxt, atom);
162876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    if (copy == NULL)
162976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		        return(-1);
163076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    copy->quant = XML_REGEXP_QUANT_ONCE;
163176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    copy->min = 0;
163276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    copy->max = 0;
163376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
163476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    if (xmlFAGenerateTransitions(ctxt, atom->start, NULL, copy)
163576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		        < 0)
163676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard			return(-1);
163776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    inter = ctxt->state;
163876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    counter = xmlRegGetCounter(ctxt);
163976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    ctxt->counters[counter].min = atom->min - 1;
164076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    ctxt->counters[counter].max = atom->max - 1;
164176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    /* count the number of times we see it again */
164276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    xmlFAGenerateCountedEpsilonTransition(ctxt, inter,
164376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard						   atom->stop, counter);
164476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    /* allow a way out based on the count */
164576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    xmlFAGenerateCountedTransition(ctxt, inter,
164676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard			                           newstate, counter);
164776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    /* and also allow a direct exit for 0 */
1648ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack		    xmlFAGenerateEpsilonTransition(ctxt, atom->start,
164976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		                                   newstate);
165076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		} else {
165176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    /*
165276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     * either we need the atom at least once or there
165376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     * is an atom->start0 allowing to easilly plug the
165476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     * epsilon transition.
165576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		     */
165676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    counter = xmlRegGetCounter(ctxt);
165776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    ctxt->counters[counter].min = atom->min - 1;
165876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    ctxt->counters[counter].max = atom->max - 1;
165976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    /* count the number of times we see it again */
166076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    xmlFAGenerateCountedEpsilonTransition(ctxt, atom->stop,
166176d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard						   atom->start, counter);
166276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    /* allow a way out based on the count */
166376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    xmlFAGenerateCountedTransition(ctxt, atom->stop,
166476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard			                           newstate, counter);
166576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    /* and if needed allow a direct exit for 0 */
166676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard		    if (atom->min == 0)
166776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard			xmlFAGenerateEpsilonTransition(ctxt, atom->start0,
166876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard						       newstate);
166976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard
1670ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack		}
16714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		atom->min = 0;
16724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		atom->max = 0;
16734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		atom->quant = XML_REGEXP_QUANT_ONCE;
16749a00fd2991433a6ce04075c91b3ac6b976bdd806Daniel Veillard		ctxt->state = newstate;
16754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
16764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    default:
16774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
16784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
1679a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(0);
1680567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
1681567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if ((atom->min == 0) && (atom->max == 0) &&
168299c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard               (atom->quant == XML_REGEXP_QUANT_RANGE)) {
168399c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard        /*
168499c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	 * we can discard the atom and generate an epsilon transition instead
168599c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	 */
168699c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	if (to == NULL) {
168799c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	    to = xmlRegNewState(ctxt);
168899c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	    if (to != NULL)
168999c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		xmlRegStatePush(ctxt, to);
169099c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	    else {
169199c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		return(-1);
169299c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	    }
169399c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	}
169499c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	xmlFAGenerateEpsilonTransition(ctxt, from, to);
169599c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	ctxt->state = to;
169699c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	xmlRegFreeAtom(atom);
169799c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	return(0);
1698567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
1699567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (to == NULL) {
1700567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	to = xmlRegNewState(ctxt);
1701567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (to != NULL)
1702567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    xmlRegStatePush(ctxt, to);
1703567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else {
1704a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	    return(-1);
17054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
170610bda629bf8fe279f02493f0921110c552be3171Daniel Veillard    }
170710bda629bf8fe279f02493f0921110c552be3171Daniel Veillard    end = to;
170810bda629bf8fe279f02493f0921110c552be3171Daniel Veillard    if ((atom->quant == XML_REGEXP_QUANT_MULT) ||
170910bda629bf8fe279f02493f0921110c552be3171Daniel Veillard        (atom->quant == XML_REGEXP_QUANT_PLUS)) {
171010bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	/*
171110bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	 * Do not pollute the target state by adding transitions from
171210bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	 * it as it is likely to be the shared target of multiple branches.
171310bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	 * So isolate with an epsilon transition.
171410bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	 */
171510bda629bf8fe279f02493f0921110c552be3171Daniel Veillard        xmlRegStatePtr tmp;
171610bda629bf8fe279f02493f0921110c552be3171Daniel Veillard
171710bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	tmp = xmlRegNewState(ctxt);
171810bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	if (tmp != NULL)
171910bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	    xmlRegStatePush(ctxt, tmp);
172010bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	else {
172110bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	    return(-1);
172210bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	}
172310bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	xmlFAGenerateEpsilonTransition(ctxt, tmp, to);
172410bda629bf8fe279f02493f0921110c552be3171Daniel Veillard	to = tmp;
17254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
1726567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (xmlRegAtomPush(ctxt, atom) < 0) {
1727567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	return(-1);
1728567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
1729567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    xmlRegStateAddTrans(ctxt, from, atom, to, -1, -1);
173010bda629bf8fe279f02493f0921110c552be3171Daniel Veillard    ctxt->state = end;
17314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (atom->quant) {
17324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_REGEXP_QUANT_OPT:
17334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom->quant = XML_REGEXP_QUANT_ONCE;
17344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAGenerateEpsilonTransition(ctxt, from, to);
17354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
17364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_REGEXP_QUANT_MULT:
17374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom->quant = XML_REGEXP_QUANT_ONCE;
17384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAGenerateEpsilonTransition(ctxt, from, to);
17395de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	    xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1);
17404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
17414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_REGEXP_QUANT_PLUS:
17424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom->quant = XML_REGEXP_QUANT_ONCE;
17435de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard	    xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1);
17444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
17455657837103e9938b42135cb993f197d1235221e0William M. Brack	case XML_REGEXP_QUANT_RANGE:
1746c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard#if DV_test
17475657837103e9938b42135cb993f197d1235221e0William M. Brack	    if (atom->min == 0) {
17485657837103e9938b42135cb993f197d1235221e0William M. Brack		xmlFAGenerateEpsilonTransition(ctxt, from, to);
17495657837103e9938b42135cb993f197d1235221e0William M. Brack	    }
1750c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard#endif
17515657837103e9938b42135cb993f197d1235221e0William M. Brack	    break;
17524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	default:
17534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
17544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
1755a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    return(0);
17564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
17574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
17584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
17594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAReduceEpsilonTransitions:
1760441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
17614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @fromnr:  the from state
17624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @tonr:  the to state
1763ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * @counter:  should that transition be associated to a counted
17644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
17654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
17664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
17674255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt, int fromnr,
17684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	                      int tonr, int counter) {
17694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int transnr;
17704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr from;
17714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr to;
17724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
17734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
17744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("xmlFAReduceEpsilonTransitions(%d, %d)\n", fromnr, tonr);
17754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
17764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    from = ctxt->states[fromnr];
17774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (from == NULL)
17784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
17794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    to = ctxt->states[tonr];
17804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
17814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
17824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((to->mark == XML_REGEXP_MARK_START) ||
17834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(to->mark == XML_REGEXP_MARK_VISITED))
17844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
17854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
17864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    to->mark = XML_REGEXP_MARK_VISITED;
17874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to->type == XML_REGEXP_FINAL_STATE) {
17884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
17894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf("State %d is final, so %d becomes final\n", tonr, fromnr);
17904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
17914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	from->type = XML_REGEXP_FINAL_STATE;
17924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
17934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (transnr = 0;transnr < to->nbTrans;transnr++) {
1794db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard        if (to->trans[transnr].to < 0)
1795db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    continue;
17964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (to->trans[transnr].atom == NULL) {
17974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /*
17984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Don't remove counted transitions
17994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Don't loop either
18004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     */
1801b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	    if (to->trans[transnr].to != fromnr) {
1802b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		if (to->trans[transnr].count >= 0) {
1803b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		    int newto = to->trans[transnr].to;
1804b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
1805b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		    xmlRegStateAddTrans(ctxt, from, NULL,
1806b509f1543df71549969eeac076349e05d2f78044Daniel Veillard					ctxt->states[newto],
18075de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard					-1, to->trans[transnr].count);
1808b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		} else {
18094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
1810b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		    printf("Found epsilon trans %d from %d to %d\n",
1811b509f1543df71549969eeac076349e05d2f78044Daniel Veillard			   transnr, tonr, to->trans[transnr].to);
18124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
1813b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		    if (to->trans[transnr].counter >= 0) {
1814b509f1543df71549969eeac076349e05d2f78044Daniel Veillard			xmlFAReduceEpsilonTransitions(ctxt, fromnr,
1815b509f1543df71549969eeac076349e05d2f78044Daniel Veillard					      to->trans[transnr].to,
1816b509f1543df71549969eeac076349e05d2f78044Daniel Veillard					      to->trans[transnr].counter);
1817b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		    } else {
1818b509f1543df71549969eeac076349e05d2f78044Daniel Veillard			xmlFAReduceEpsilonTransitions(ctxt, fromnr,
1819b509f1543df71549969eeac076349e05d2f78044Daniel Veillard					      to->trans[transnr].to,
1820b509f1543df71549969eeac076349e05d2f78044Daniel Veillard					      counter);
1821b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		    }
1822b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		}
18234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
18244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
18254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int newto = to->trans[transnr].to;
18264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1827b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	    if (to->trans[transnr].counter >= 0) {
1828b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom,
1829b509f1543df71549969eeac076349e05d2f78044Daniel Veillard				    ctxt->states[newto],
18305de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard				    to->trans[transnr].counter, -1);
1831b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	    } else {
1832b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom,
18335de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard				    ctxt->states[newto], counter, -1);
1834b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	    }
18354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
18364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
18374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    to->mark = XML_REGEXP_MARK_NORMAL;
18384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
18394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
18404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
1841db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * xmlFAEliminateSimpleEpsilonTransitions:
1842db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * @ctxt:  a regexp parser context
1843db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard *
1844db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * Eliminating general epsilon transitions can get costly in the general
1845db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * algorithm due to the large amount of generated new transitions and
1846db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * associated comparisons. However for simple epsilon transition used just
1847db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * to separate building blocks when generating the automata this can be
1848db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * reduced to state elimination:
1849db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard *    - if there exists an epsilon from X to Y
1850db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard *    - if there is no other transition from X
1851db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * then X and Y are semantically equivalent and X can be eliminated
1852db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * If X is the start state then make Y the start state, else replace the
1853db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard * target of all transitions to X by transitions to Y.
1854db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard */
1855db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillardstatic void
1856db68b74dc7ec531361a736de7769a3e8ce881f79Daniel VeillardxmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
1857db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    int statenr, i, j, newto;
1858db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    xmlRegStatePtr state, tmp;
1859db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard
1860db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
1861db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	state = ctxt->states[statenr];
1862db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	if (state == NULL)
1863db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    continue;
1864db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	if (state->nbTrans != 1)
1865db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    continue;
18660e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	if (state->type == XML_REGEXP_UNREACH_STATE)
18670e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	    continue;
1868db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	/* is the only transition out a basic transition */
1869db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	if ((state->trans[0].atom == NULL) &&
1870db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    (state->trans[0].to >= 0) &&
1871db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    (state->trans[0].to != statenr) &&
1872db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    (state->trans[0].counter < 0) &&
1873db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    (state->trans[0].count < 0)) {
1874db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    newto = state->trans[0].to;
1875db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard
1876db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard            if (state->type == XML_REGEXP_START_STATE) {
1877db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
1878db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		printf("Found simple epsilon trans from start %d to %d\n",
1879db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		       statenr, newto);
1880db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard#endif
1881db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard            } else {
1882db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
1883db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		printf("Found simple epsilon trans from %d to %d\n",
1884db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		       statenr, newto);
1885db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard#endif
1886db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	        for (i = 0;i < state->nbTransTo;i++) {
1887db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		    tmp = ctxt->states[state->transTo[i]];
1888db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		    for (j = 0;j < tmp->nbTrans;j++) {
1889db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard			if (tmp->trans[j].to == statenr) {
1890db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
1891db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard			    printf("Changed transition %d on %d to go to %d\n",
1892db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard				   j, tmp->no, newto);
1893db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard#endif
18940e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard			    tmp->trans[j].to = -1;
18950e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard			    xmlRegStateAddTrans(ctxt, tmp, tmp->trans[j].atom,
18960e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard			    			ctxt->states[newto],
18970e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard					        tmp->trans[j].counter,
18980e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard						tmp->trans[j].count);
1899db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard			}
1900db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		    }
1901db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		}
1902db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		if (state->type == XML_REGEXP_FINAL_STATE)
1903db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		    ctxt->states[newto]->type = XML_REGEXP_FINAL_STATE;
1904db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		/* eliminate the transition completely */
1905db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		state->nbTrans = 0;
1906db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard
19070e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard                state->type = XML_REGEXP_UNREACH_STATE;
1908db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard
1909db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    }
1910db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard
1911db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	}
1912db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    }
1913db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard}
1914db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard/**
19154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAEliminateEpsilonTransitions:
1916441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
19174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
19184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
19194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
19204255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAEliminateEpsilonTransitions(xmlRegParserCtxtPtr ctxt) {
19214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int statenr, transnr;
19224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr state;
1923db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    int has_epsilon;
19244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
1925a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (ctxt->states == NULL) return;
1926a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard
19270e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard    /*
19280e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard     * Eliminate simple epsilon transition and the associated unreachable
19290e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard     * states.
19300e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard     */
1931db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    xmlFAEliminateSimpleEpsilonTransitions(ctxt);
19320e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard    for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
19330e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	state = ctxt->states[statenr];
19340e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	if ((state != NULL) && (state->type == XML_REGEXP_UNREACH_STATE)) {
19350e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard#ifdef DEBUG_REGEXP_GRAPH
19360e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	    printf("Removed unreachable state %d\n", statenr);
19370e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard#endif
19380e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	    xmlRegFreeState(state);
19390e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	    ctxt->states[statenr] = NULL;
19400e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	}
19410e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard    }
1942db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard
1943db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    has_epsilon = 0;
1944a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard
19454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /*
1946fcd18ff8f753dd7308b619476266f1a2ddcc8859Daniel Veillard     * Build the completed transitions bypassing the epsilons
19474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * Use a marking algorithm to avoid loops
1948fcd18ff8f753dd7308b619476266f1a2ddcc8859Daniel Veillard     * Mark sink states too.
1949fcd18ff8f753dd7308b619476266f1a2ddcc8859Daniel Veillard     * Process from the latests states backward to the start when
1950fcd18ff8f753dd7308b619476266f1a2ddcc8859Daniel Veillard     * there is long cascading epsilon chains this minimize the
1951fcd18ff8f753dd7308b619476266f1a2ddcc8859Daniel Veillard     * recursions and transition compares when adding the new ones
19524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     */
1953fcd18ff8f753dd7308b619476266f1a2ddcc8859Daniel Veillard    for (statenr = ctxt->nbStates - 1;statenr >= 0;statenr--) {
19544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	state = ctxt->states[statenr];
19554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (state == NULL)
19564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    continue;
1957cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	if ((state->nbTrans == 0) &&
1958cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    (state->type != XML_REGEXP_FINAL_STATE)) {
1959cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    state->type = XML_REGEXP_SINK_STATE;
1960cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	}
19614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (transnr = 0;transnr < state->nbTrans;transnr++) {
19624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if ((state->trans[transnr].atom == NULL) &&
19634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		(state->trans[transnr].to >= 0)) {
19644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (state->trans[transnr].to == statenr) {
19654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    state->trans[transnr].to = -1;
19664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
19674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Removed loopback epsilon trans %d on %d\n",
19684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			   transnr, statenr);
19694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
19704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		} else if (state->trans[transnr].count < 0) {
19714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    int newto = state->trans[transnr].to;
19724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
19734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
19744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Found epsilon trans %d from %d to %d\n",
19754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			   transnr, statenr, newto);
19764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
1977db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		    has_epsilon = 1;
19780e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard		    state->trans[transnr].to = -2;
19790e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard		    state->mark = XML_REGEXP_MARK_START;
19804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFAReduceEpsilonTransitions(ctxt, statenr,
19814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard				      newto, state->trans[transnr].counter);
19824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    state->mark = XML_REGEXP_MARK_NORMAL;
19834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
19844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		} else {
19854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Found counted transition %d on %d\n",
19864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			   transnr, statenr);
19874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
19884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	        }
19894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
19904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
19914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
19924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /*
19934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * Eliminate the epsilon transitions
19944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     */
1995db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    if (has_epsilon) {
1996db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
1997db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    state = ctxt->states[statenr];
1998db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    if (state == NULL)
1999db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		continue;
2000db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard	    for (transnr = 0;transnr < state->nbTrans;transnr++) {
2001db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		xmlRegTransPtr trans = &(state->trans[transnr]);
2002db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		if ((trans->atom == NULL) &&
2003db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		    (trans->count < 0) &&
2004db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		    (trans->to >= 0)) {
2005db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		    trans->to = -1;
2006db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard		}
20074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
20084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
20094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
201023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
201123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    /*
201223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     * Use this pass to detect unreachable states too
201323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     */
201423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
201523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	state = ctxt->states[statenr];
201623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	if (state != NULL)
2017779af00750fa86045e94422287d67a2cf5723f65William M. Brack	    state->reached = XML_REGEXP_MARK_NORMAL;
201823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
201923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    state = ctxt->states[0];
202023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (state != NULL)
2021779af00750fa86045e94422287d67a2cf5723f65William M. Brack	state->reached = XML_REGEXP_MARK_START;
202223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    while (state != NULL) {
202323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	xmlRegStatePtr target = NULL;
2024779af00750fa86045e94422287d67a2cf5723f65William M. Brack	state->reached = XML_REGEXP_MARK_VISITED;
202523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	/*
2026ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	 * Mark all states reachable from the current reachable state
202723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 */
202823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	for (transnr = 0;transnr < state->nbTrans;transnr++) {
202923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    if ((state->trans[transnr].to >= 0) &&
203023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		((state->trans[transnr].atom != NULL) ||
203123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		 (state->trans[transnr].count >= 0))) {
203223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		int newto = state->trans[transnr].to;
203323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
203423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		if (ctxt->states[newto] == NULL)
203523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    continue;
2036779af00750fa86045e94422287d67a2cf5723f65William M. Brack		if (ctxt->states[newto]->reached == XML_REGEXP_MARK_NORMAL) {
2037779af00750fa86045e94422287d67a2cf5723f65William M. Brack		    ctxt->states[newto]->reached = XML_REGEXP_MARK_START;
203823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    target = ctxt->states[newto];
203923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		}
204023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    }
204123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
2042cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard
204323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	/*
204423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * find the next accessible state not explored
204523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 */
204623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	if (target == NULL) {
204723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    for (statenr = 1;statenr < ctxt->nbStates;statenr++) {
204823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		state = ctxt->states[statenr];
2049779af00750fa86045e94422287d67a2cf5723f65William M. Brack		if ((state != NULL) && (state->reached ==
2050779af00750fa86045e94422287d67a2cf5723f65William M. Brack			XML_REGEXP_MARK_START)) {
205123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    target = state;
205223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    break;
205323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		}
205423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    }
205523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
205623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	state = target;
205723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
205823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
205923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	state = ctxt->states[statenr];
2060779af00750fa86045e94422287d67a2cf5723f65William M. Brack	if ((state != NULL) && (state->reached == XML_REGEXP_MARK_NORMAL)) {
206123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
206223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    printf("Removed unreachable state %d\n", statenr);
206323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
206423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    xmlRegFreeState(state);
206523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    ctxt->states[statenr] = NULL;
206623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
206723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
206823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
20694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
20704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2071567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillardstatic int
2072567a45b5e931388acf850d56f937f1f66ff0f860Daniel VeillardxmlFACompareRanges(xmlRegRangePtr range1, xmlRegRangePtr range2) {
2073567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    int ret = 0;
2074567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2075567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if ((range1->type == XML_REGEXP_RANGES) ||
2076567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        (range2->type == XML_REGEXP_RANGES) ||
2077567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        (range2->type == XML_REGEXP_SUBREG) ||
2078567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        (range1->type == XML_REGEXP_SUBREG) ||
2079567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        (range1->type == XML_REGEXP_STRING) ||
2080567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        (range2->type == XML_REGEXP_STRING))
2081567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	return(-1);
2082567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2083567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    /* put them in order */
2084567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (range1->type > range2->type) {
2085567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        xmlRegRangePtr tmp;
2086567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2087567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	tmp = range1;
2088567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	range1 = range2;
2089567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	range2 = tmp;
2090567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
2091567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if ((range1->type == XML_REGEXP_ANYCHAR) ||
2092567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        (range2->type == XML_REGEXP_ANYCHAR)) {
2093567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	ret = 1;
2094567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else if ((range1->type == XML_REGEXP_EPSILON) ||
2095567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard               (range2->type == XML_REGEXP_EPSILON)) {
2096567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	return(0);
2097567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else if (range1->type == range2->type) {
20989332b48f16123cac16a207425b3a0206e5da35c1Daniel Veillard        if (range1->type != XML_REGEXP_CHARVAL)
20999332b48f16123cac16a207425b3a0206e5da35c1Daniel Veillard            ret = 1;
21009332b48f16123cac16a207425b3a0206e5da35c1Daniel Veillard        else if ((range1->end < range2->start) ||
21019332b48f16123cac16a207425b3a0206e5da35c1Daniel Veillard	         (range2->end < range1->start))
2102567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
21039332b48f16123cac16a207425b3a0206e5da35c1Daniel Veillard	else
21049332b48f16123cac16a207425b3a0206e5da35c1Daniel Veillard	    ret = 1;
2105567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else if (range1->type == XML_REGEXP_CHARVAL) {
2106567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        int codepoint;
2107567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	int neg = 0;
2108567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2109567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	/*
2110567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * just check all codepoints in the range for acceptance,
2111567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * this is usually way cheaper since done only once at
2112567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * compilation than testing over and over at runtime or
2113567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * pushing too many states when evaluating.
2114567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 */
2115567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (((range1->neg == 0) && (range2->neg != 0)) ||
2116567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ((range1->neg != 0) && (range2->neg == 0)))
2117567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    neg = 1;
2118567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2119567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	for (codepoint = range1->start;codepoint <= range1->end ;codepoint++) {
2120567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = xmlRegCheckCharacterRange(range2->type, codepoint,
2121567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard					    0, range2->start, range2->end,
2122567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard					    range2->blockName);
2123567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (ret < 0)
2124567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	        return(-1);
2125567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (((neg == 1) && (ret == 0)) ||
2126567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	        ((neg == 0) && (ret == 1)))
2127567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		return(1);
2128567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2129567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	return(0);
2130567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else if ((range1->type == XML_REGEXP_BLOCK_NAME) ||
2131567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard               (range2->type == XML_REGEXP_BLOCK_NAME)) {
2132567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (range1->type == range2->type) {
2133567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = xmlStrEqual(range1->blockName, range2->blockName);
2134567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	} else {
2135567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /*
2136567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * comparing a block range with anything else is way
2137567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * too costly, and maintining the table is like too much
2138567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * memory too, so let's force the automata to save state
2139567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * here.
2140567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     */
2141567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    return(1);
2142567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2143567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else if ((range1->type < XML_REGEXP_LETTER) ||
2144567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard               (range2->type < XML_REGEXP_LETTER)) {
2145567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if ((range1->type == XML_REGEXP_ANYSPACE) &&
2146567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    (range2->type == XML_REGEXP_NOTSPACE))
2147567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2148567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else if ((range1->type == XML_REGEXP_INITNAME) &&
2149567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         (range2->type == XML_REGEXP_NOTINITNAME))
2150567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2151567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else if ((range1->type == XML_REGEXP_NAMECHAR) &&
2152567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         (range2->type == XML_REGEXP_NOTNAMECHAR))
2153567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2154567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else if ((range1->type == XML_REGEXP_DECIMAL) &&
2155567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         (range2->type == XML_REGEXP_NOTDECIMAL))
2156567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2157567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else if ((range1->type == XML_REGEXP_REALCHAR) &&
2158567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         (range2->type == XML_REGEXP_NOTREALCHAR))
2159567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2160567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else {
2161567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /* same thing to limit complexity */
2162567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    return(1);
2163567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2164567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else {
2165567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        ret = 0;
2166567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        /* range1->type < range2->type here */
2167567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        switch (range1->type) {
2168567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_LETTER:
2169567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         /* all disjoint except in the subgroups */
2170567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_LETTER_UPPERCASE) ||
2171567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_LETTER_LOWERCASE) ||
2172567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_LETTER_TITLECASE) ||
2173567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_LETTER_MODIFIER) ||
2174567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_LETTER_OTHERS))
2175567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2176567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2177567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_MARK:
2178567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_MARK_NONSPACING) ||
2179567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_MARK_SPACECOMBINING) ||
2180567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_MARK_ENCLOSING))
2181567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2182567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2183567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_NUMBER:
2184567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_NUMBER_DECIMAL) ||
2185567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_NUMBER_LETTER) ||
2186567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_NUMBER_OTHERS))
2187567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2188567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2189567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_PUNCT:
2190567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_PUNCT_CONNECTOR) ||
2191567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_DASH) ||
2192567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_OPEN) ||
2193567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_CLOSE) ||
2194567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_INITQUOTE) ||
2195567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_FINQUOTE) ||
2196567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_OTHERS))
2197567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2198567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2199567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_SEPAR:
2200567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_SEPAR_SPACE) ||
2201567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SEPAR_LINE) ||
2202567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SEPAR_PARA))
2203567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2204567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2205567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_SYMBOL:
2206567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_SYMBOL_MATH) ||
2207567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SYMBOL_CURRENCY) ||
2208567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SYMBOL_MODIFIER) ||
2209567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SYMBOL_OTHERS))
2210567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2211567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2212567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_OTHER:
2213567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_OTHER_CONTROL) ||
2214567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_OTHER_FORMAT) ||
2215567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_OTHER_PRIVATE))
2216567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2217567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2218567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard            default:
2219567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type >= XML_REGEXP_LETTER) &&
2220567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type < XML_REGEXP_BLOCK_NAME))
2221567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 0;
2222567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 else {
2223567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     /* safety net ! */
2224567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     return(1);
2225567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 }
2226567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2227567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
2228567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (((range1->neg == 0) && (range2->neg != 0)) ||
2229567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        ((range1->neg != 0) && (range2->neg == 0)))
2230567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	ret = !ret;
2231594e5dfb48ee6fbac1b64155839063648022fc57Daniel Veillard    return(ret);
2232567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard}
2233567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2234e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
2235fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * xmlFACompareAtomTypes:
2236fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * @type1:  an atom type
2237fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * @type2:  an atom type
2238fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard *
2239fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Compares two atoms type to check whether they intersect in some ways,
2240fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * this is used by xmlFACompareAtoms only
2241fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard *
2242fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Returns 1 if they may intersect and 0 otherwise
2243fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard */
2244fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillardstatic int
2245fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel VeillardxmlFACompareAtomTypes(xmlRegAtomType type1, xmlRegAtomType type2) {
2246fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if ((type1 == XML_REGEXP_EPSILON) ||
2247fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        (type1 == XML_REGEXP_CHARVAL) ||
2248fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type1 == XML_REGEXP_RANGES) ||
2249fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type1 == XML_REGEXP_SUBREG) ||
2250fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type1 == XML_REGEXP_STRING) ||
2251fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type1 == XML_REGEXP_ANYCHAR))
2252fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(1);
2253fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if ((type2 == XML_REGEXP_EPSILON) ||
2254fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        (type2 == XML_REGEXP_CHARVAL) ||
2255fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type2 == XML_REGEXP_RANGES) ||
2256fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type2 == XML_REGEXP_SUBREG) ||
2257fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type2 == XML_REGEXP_STRING) ||
2258fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type2 == XML_REGEXP_ANYCHAR))
2259fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(1);
2260fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2261fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (type1 == type2) return(1);
2262fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2263fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    /* simplify subsequent compares by making sure type1 < type2 */
2264fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (type1 > type2) {
2265fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        xmlRegAtomType tmp = type1;
2266fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	type1 = type2;
2267fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	type2 = tmp;
2268fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    }
2269fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    switch (type1) {
2270fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_ANYSPACE: /* \s */
2271fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a letter, number, mark, pontuation, symbol */
2272fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTSPACE) ||
2273fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		((type2 >= XML_REGEXP_LETTER) &&
2274fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_LETTER_OTHERS)) ||
2275fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_NUMBER) &&
2276fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_NUMBER_OTHERS)) ||
2277fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2278fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2279fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2280fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2281fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2282fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS))
2283fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ) return(0);
2284fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2285fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTSPACE: /* \S */
2286fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2287fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_INITNAME: /* \l */
2288fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a number, mark, separator, pontuation, symbol or other */
2289fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTINITNAME) ||
2290fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_NUMBER) &&
2291fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_NUMBER_OTHERS)) ||
2292fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2293fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2294fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SEPAR) &&
2295fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2296fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2297fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2298fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2299fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2300fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_OTHER) &&
2301fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_OTHER_NA))
2302fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		) return(0);
2303fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2304fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTINITNAME: /* \L */
2305fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2306fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NAMECHAR: /* \c */
2307fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a mark, separator, pontuation, symbol or other */
2308fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTNAMECHAR) ||
2309fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2310fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2311fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2312fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2313fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SEPAR) &&
2314fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2315fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2316fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2317fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_OTHER) &&
2318fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_OTHER_NA))
2319fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		) return(0);
2320fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2321fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTNAMECHAR: /* \C */
2322fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2323fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_DECIMAL: /* \d */
2324fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a letter, mark, separator, pontuation, symbol or other */
2325fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTDECIMAL) ||
2326fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        (type2 == XML_REGEXP_REALCHAR) ||
2327fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		((type2 >= XML_REGEXP_LETTER) &&
2328fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_LETTER_OTHERS)) ||
2329fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2330fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2331fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2332fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2333fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SEPAR) &&
2334fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2335fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2336fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2337fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_OTHER) &&
2338fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_OTHER_NA))
2339fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		)return(0);
2340fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2341fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTDECIMAL: /* \D */
2342fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2343fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_REALCHAR: /* \w */
2344fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a mark, separator, pontuation, symbol or other */
2345fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTDECIMAL) ||
2346fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2347fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2348fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2349fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2350fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SEPAR) &&
2351fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2352fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2353fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2354fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_OTHER) &&
2355fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_OTHER_NA))
2356fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		)return(0);
2357fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2358fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTREALCHAR: /* \W */
2359fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2360fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	/*
2361fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	 * at that point we know both type 1 and type2 are from
2362fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	 * character categories are ordered and are different,
2363fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	 * it becomes simple because this is a partition
2364fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	 */
2365fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER:
2366fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_LETTER_OTHERS)
2367fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2368fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2369fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_UPPERCASE:
2370fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_LOWERCASE:
2371fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_TITLECASE:
2372fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_MODIFIER:
2373fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_OTHERS:
2374fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2375fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_MARK:
2376fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_MARK_ENCLOSING)
2377fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2378fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2379fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_MARK_NONSPACING:
2380fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_MARK_SPACECOMBINING:
2381fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_MARK_ENCLOSING:
2382fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2383fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NUMBER:
2384fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_NUMBER_OTHERS)
2385fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2386fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2387fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NUMBER_DECIMAL:
2388fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NUMBER_LETTER:
2389fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NUMBER_OTHERS:
2390fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2391fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT:
2392fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_PUNCT_OTHERS)
2393fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2394fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2395fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_CONNECTOR:
2396fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_DASH:
2397fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_OPEN:
2398fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_CLOSE:
2399fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_INITQUOTE:
2400fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_FINQUOTE:
2401fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_OTHERS:
2402fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2403fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SEPAR:
2404fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_SEPAR_PARA)
2405fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2406fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2407fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SEPAR_SPACE:
2408fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SEPAR_LINE:
2409fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SEPAR_PARA:
2410fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2411fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL:
2412fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_SYMBOL_OTHERS)
2413fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2414fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2415fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL_MATH:
2416fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL_CURRENCY:
2417fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL_MODIFIER:
2418fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL_OTHERS:
2419fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2420fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER:
2421fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_OTHER_NA)
2422fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2423fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2424fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER_CONTROL:
2425fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER_FORMAT:
2426fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER_PRIVATE:
2427fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER_NA:
2428fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2429fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	default:
2430fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2431fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    }
2432fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    return(1);
2433fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard}
2434fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2435fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard/**
2436fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * xmlFAEqualAtoms:
2437fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * @atom1:  an atom
2438fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * @atom2:  an atom
24391ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * @deep: if not set only compare string pointers
2440fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard *
2441fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Compares two atoms to check whether they are the same exactly
2442fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * this is used to remove equivalent transitions
2443fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard *
2444fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Returns 1 if same and 0 otherwise
2445fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard */
2446fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillardstatic int
24471ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel VeillardxmlFAEqualAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2, int deep) {
2448fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    int ret = 0;
2449fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2450fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (atom1 == atom2)
2451fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(1);
2452fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if ((atom1 == NULL) || (atom2 == NULL))
2453fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(0);
2454fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2455fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (atom1->type != atom2->type)
2456fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        return(0);
2457fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    switch (atom1->type) {
2458fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_EPSILON:
2459fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    ret = 0;
2460fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2461fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_STRING:
24621ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard            if (!deep)
24631ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                ret = (atom1->valuep == atom2->valuep);
24641ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard            else
24651ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                ret = xmlStrEqual((xmlChar *)atom1->valuep,
24661ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                                  (xmlChar *)atom2->valuep);
2467fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2468fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_CHARVAL:
2469fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    ret = (atom1->codepoint == atom2->codepoint);
2470fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2471fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	case XML_REGEXP_RANGES:
2472fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* too hard to do in the general case */
2473fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    ret = 0;
2474fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	default:
2475fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2476fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    }
2477fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    return(ret);
2478fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard}
2479fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2480fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard/**
2481e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * xmlFACompareAtoms:
2482e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @atom1:  an atom
2483e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @atom2:  an atom
24841ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * @deep: if not set only compare string pointers
2485e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2486567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard * Compares two atoms to check whether they intersect in some ways,
2487fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * this is used by xmlFAComputesDeterminism and xmlFARecurseDeterminism only
2488e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2489e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Returns 1 if yes and 0 otherwise
2490e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
2491e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardstatic int
24921ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel VeillardxmlFACompareAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2, int deep) {
2493fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    int ret = 1;
24949efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
2495e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if (atom1 == atom2)
2496e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(1);
2497e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if ((atom1 == NULL) || (atom2 == NULL))
2498e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(0);
2499e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
2500fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if ((atom1->type == XML_REGEXP_ANYCHAR) ||
2501fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        (atom2->type == XML_REGEXP_ANYCHAR))
2502fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(1);
2503fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2504fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (atom1->type > atom2->type) {
2505567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	xmlRegAtomPtr tmp;
2506567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	tmp = atom1;
2507567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	atom1 = atom2;
2508567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	atom2 = tmp;
2509fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    }
2510fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (atom1->type != atom2->type) {
2511fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        ret = xmlFACompareAtomTypes(atom1->type, atom2->type);
2512fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	/* if they can't intersect at the type level break now */
2513fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	if (ret == 0)
2514fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2515567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
2516e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    switch (atom1->type) {
2517e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard        case XML_REGEXP_STRING:
25181ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard            if (!deep)
25191ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                ret = (atom1->valuep != atom2->valuep);
25201ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard            else
25211ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                ret = xmlRegStrEqualWildcard((xmlChar *)atom1->valuep,
25221ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                                             (xmlChar *)atom2->valuep);
25239efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	    break;
2524e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard        case XML_REGEXP_EPSILON:
2525567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    goto not_determinist;
2526e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard        case XML_REGEXP_CHARVAL:
2527567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (atom2->type == XML_REGEXP_CHARVAL) {
2528fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		ret = (atom1->codepoint == atom2->codepoint);
2529567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    } else {
2530fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ret = xmlRegCheckCharacter(atom2, atom1->codepoint);
2531fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		if (ret < 0)
2532fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		    ret = 1;
2533fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    }
2534fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2535fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_RANGES:
2536fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (atom2->type == XML_REGEXP_RANGES) {
2537567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	        int i, j, res;
2538567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		xmlRegRangePtr r1, r2;
2539567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2540567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		/*
2541567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 * need to check that none of the ranges eventually matches
2542567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 */
2543567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		for (i = 0;i < atom1->nbRanges;i++) {
2544567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    for (j = 0;j < atom2->nbRanges;j++) {
2545567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			r1 = atom1->ranges[i];
2546567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			r2 = atom2->ranges[j];
2547567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			res = xmlFACompareRanges(r1, r2);
2548567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			if (res == 1) {
2549567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			    ret = 1;
2550567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			    goto done;
2551567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			}
2552567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    }
2553567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		}
2554567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		ret = 0;
2555567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2556567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    break;
2557e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	default:
2558567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    goto not_determinist;
2559e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    }
2560567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillarddone:
25616e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    if (atom1->neg != atom2->neg) {
25629efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard        ret = !ret;
25636e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    }
2564567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (ret == 0)
2565567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        return(0);
2566567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillardnot_determinist:
2567567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    return(1);
2568e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard}
2569e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
2570e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
2571e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * xmlFARecurseDeterminism:
2572e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @ctxt:  a regexp parser context
2573e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2574e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Check whether the associated regexp is determinist,
2575e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * should be called after xmlFAEliminateEpsilonTransitions()
2576e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2577e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
2578e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardstatic int
2579e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel VeillardxmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
2580e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	                 int to, xmlRegAtomPtr atom) {
2581e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int ret = 1;
2582567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    int res;
25835de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    int transnr, nbTrans;
2584e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    xmlRegTransPtr t1;
25851ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    int deep = 1;
2586e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
2587e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if (state == NULL)
2588e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(ret);
25891ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
25901ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    if (ctxt->flags & AM_AUTOMATA_RNG)
25911ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard        deep = 0;
25921ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
25935de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    /*
25945de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard     * don't recurse on transitions potentially added in the course of
25955de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard     * the elimination.
25965de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard     */
25975de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    nbTrans = state->nbTrans;
25985de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    for (transnr = 0;transnr < nbTrans;transnr++) {
2599e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	t1 = &(state->trans[transnr]);
2600e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	/*
2601e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	 * check transitions conflicting with the one looked at
2602e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	 */
2603e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	if (t1->atom == NULL) {
26040e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	    if (t1->to < 0)
2605e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		continue;
2606567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
2607e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		                           to, atom);
2608567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (res == 0) {
2609567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	        ret = 0;
2610aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		/* t1->nd = 1; */
2611567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2612e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    continue;
2613e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	}
2614e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	if (t1->to != to)
2615e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    continue;
26161ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard	if (xmlFACompareAtoms(t1->atom, atom, deep)) {
2617567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2618567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /* mark the transition as non-deterministic */
2619567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    t1->nd = 1;
2620567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2621e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    }
2622e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    return(ret);
2623e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard}
2624e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
2625e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
2626e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * xmlFAComputesDeterminism:
2627e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @ctxt:  a regexp parser context
2628e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2629e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Check whether the associated regexp is determinist,
2630e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * should be called after xmlFAEliminateEpsilonTransitions()
2631e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2632e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
2633e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardstatic int
2634e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel VeillardxmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
2635e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int statenr, transnr;
2636e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    xmlRegStatePtr state;
2637567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    xmlRegTransPtr t1, t2, last;
2638e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int i;
2639e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int ret = 1;
26401ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    int deep = 1;
2641e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
26424402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard#ifdef DEBUG_REGEXP_GRAPH
26434402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard    printf("xmlFAComputesDeterminism\n");
26444402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard    xmlRegPrintCtxt(stdout, ctxt);
26454402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard#endif
2646e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if (ctxt->determinist != -1)
2647e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(ctxt->determinist);
2648e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
26491ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    if (ctxt->flags & AM_AUTOMATA_RNG)
26501ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard        deep = 0;
26511ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
2652e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    /*
2653567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard     * First cleanup the automata removing cancelled transitions
2654e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard     */
2655e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
2656e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	state = ctxt->states[statenr];
2657e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	if (state == NULL)
2658e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    continue;
26594f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	if (state->nbTrans < 2)
26604f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	    continue;
2661e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	for (transnr = 0;transnr < state->nbTrans;transnr++) {
2662e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    t1 = &(state->trans[transnr]);
2663e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    /*
2664e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	     * Determinism checks in case of counted or all transitions
2665e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	     * will have to be handled separately
2666e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	     */
2667567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (t1->atom == NULL) {
2668aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		/* t1->nd = 1; */
2669e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		continue;
2670567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2671e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    if (t1->to == -1) /* eliminated */
2672e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		continue;
2673e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    for (i = 0;i < transnr;i++) {
2674e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		t2 = &(state->trans[i]);
2675e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		if (t2->to == -1) /* eliminated */
2676e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    continue;
2677e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		if (t2->atom != NULL) {
2678e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    if (t1->to == t2->to) {
26791ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                        /*
26801ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                         * Here we use deep because we want to keep the
26811ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                         * transitions which indicate a conflict
26821ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                         */
26831ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard			if (xmlFAEqualAtoms(t1->atom, t2->atom, deep) &&
268411e28e4dfb84804474a3d7a4bfb08bae8f00bc0aDaniel Veillard                            (t1->counter == t2->counter) &&
268511e28e4dfb84804474a3d7a4bfb08bae8f00bc0aDaniel Veillard                            (t1->count == t2->count))
2686ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack			    t2->to = -1; /* eliminated */
2687567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    }
2688567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		}
2689567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2690567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2691567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
2692567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2693567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    /*
2694567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard     * Check for all states that there aren't 2 transitions
2695567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard     * with the same atom and a different target.
2696567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard     */
2697567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
2698567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	state = ctxt->states[statenr];
2699567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (state == NULL)
2700567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    continue;
2701567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (state->nbTrans < 2)
2702567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    continue;
2703567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	last = NULL;
2704567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	for (transnr = 0;transnr < state->nbTrans;transnr++) {
2705567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    t1 = &(state->trans[transnr]);
2706567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /*
2707567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * Determinism checks in case of counted or all transitions
2708567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * will have to be handled separately
2709567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     */
2710567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (t1->atom == NULL) {
2711567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		continue;
2712567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2713567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (t1->to == -1) /* eliminated */
2714567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		continue;
2715567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    for (i = 0;i < transnr;i++) {
2716567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		t2 = &(state->trans[i]);
2717567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		if (t2->to == -1) /* eliminated */
2718567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    continue;
2719567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		if (t2->atom != NULL) {
27201ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                    /*
27211ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                     * But here we don't use deep because we want to
27221ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                     * find transitions which indicate a conflict
27231ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                     */
27241ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard		    if (xmlFACompareAtoms(t1->atom, t2->atom, 1)) {
2725567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			ret = 0;
2726567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			/* mark the transitions as non-deterministic ones */
2727567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			t1->nd = 1;
2728567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			t2->nd = 1;
2729567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			last = t1;
2730e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    }
2731e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		} else if (t1->to != -1) {
2732e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    /*
2733e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		     * do the closure in case of remaining specific
2734e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		     * epsilon transitions like choices or all
2735e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		     */
2736e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    ret = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
2737e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard						   t2->to, t2->atom);
2738567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    /* don't shortcut the computation so all non deterministic
2739567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		       transition get marked down
2740e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    if (ret == 0)
2741aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard			return(0);
2742aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		     */
2743567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    if (ret == 0) {
2744567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			t1->nd = 1;
2745aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard			/* t2->nd = 1; */
2746567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			last = t1;
2747567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    }
2748e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		}
2749e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    }
2750567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /* don't shortcut the computation so all non deterministic
2751567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	       transition get marked down
2752e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    if (ret == 0)
2753567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		break; */
2754e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	}
2755567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2756567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	/*
2757567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * mark specifically the last non-deterministic transition
2758567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * from a state since there is no need to set-up rollback
2759567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * from it
2760567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 */
2761567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (last != NULL) {
2762567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    last->nd = 2;
2763567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2764567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2765567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	/* don't shortcut the computation so all non deterministic
2766567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	   transition get marked down
2767e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	if (ret == 0)
2768567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    break; */
2769e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    }
2770567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2771e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    ctxt->determinist = ret;
2772e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    return(ret);
2773e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard}
2774e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
27754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
27764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
27774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *	Routines to check input against transition atoms		*
27784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
27794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
27804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
27814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
27824255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint, int neg,
27834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	                  int start, int end, const xmlChar *blockName) {
27844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret = 0;
27854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
27864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (type) {
27874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_STRING:
27884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SUBREG:
27894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_RANGES:
27904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_EPSILON:
27914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
27924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYCHAR:
27934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = ((codepoint != '\n') && (codepoint != '\r'));
27944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
27954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_CHARVAL:
27964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = ((codepoint >= start) && (codepoint <= end));
27974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
27984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTSPACE:
27994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYSPACE:
28014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = ((codepoint == '\n') || (codepoint == '\r') ||
28024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   (codepoint == '\t') || (codepoint == ' '));
28034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTINITNAME:
28054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_INITNAME:
2807871611bb0325095b30559ff1edc1fdaa2ad5fd2fWilliam M. Brack	    ret = (IS_LETTER(codepoint) ||
28084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   (codepoint == '_') || (codepoint == ':'));
28094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTNAMECHAR:
28114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NAMECHAR:
2813871611bb0325095b30559ff1edc1fdaa2ad5fd2fWilliam M. Brack	    ret = (IS_LETTER(codepoint) || IS_DIGIT(codepoint) ||
28144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   (codepoint == '.') || (codepoint == '-') ||
28154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   (codepoint == '_') || (codepoint == ':') ||
2816871611bb0325095b30559ff1edc1fdaa2ad5fd2fWilliam M. Brack		   IS_COMBINING(codepoint) || IS_EXTENDER(codepoint));
28174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTDECIMAL:
28194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_DECIMAL:
28214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatNd(codepoint);
28224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_REALCHAR:
28244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTREALCHAR:
28264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatP(codepoint);
28274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 0)
28284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = xmlUCSIsCatZ(codepoint);
28294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 0)
28304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = xmlUCSIsCatC(codepoint);
28314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER:
28334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatL(codepoint);
28344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_UPPERCASE:
28364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLu(codepoint);
28374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_LOWERCASE:
28394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLl(codepoint);
28404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_TITLECASE:
28424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLt(codepoint);
28434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_MODIFIER:
28454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLm(codepoint);
28464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_OTHERS:
28484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLo(codepoint);
28494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK:
28514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatM(codepoint);
28524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_NONSPACING:
28544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatMn(codepoint);
28554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_SPACECOMBINING:
28574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatMc(codepoint);
28584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_ENCLOSING:
28604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatMe(codepoint);
28614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER:
28634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatN(codepoint);
28644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_DECIMAL:
28664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatNd(codepoint);
28674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_LETTER:
28694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatNl(codepoint);
28704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_OTHERS:
28724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatNo(codepoint);
28734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT:
28754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatP(codepoint);
28764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CONNECTOR:
28784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPc(codepoint);
28794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_DASH:
28814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPd(codepoint);
28824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OPEN:
28844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPs(codepoint);
28854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CLOSE:
28874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPe(codepoint);
28884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_INITQUOTE:
28904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPi(codepoint);
28914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_FINQUOTE:
28934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPf(codepoint);
28944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OTHERS:
28964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPo(codepoint);
28974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR:
28994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatZ(codepoint);
29004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_SPACE:
29024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatZs(codepoint);
29034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_LINE:
29054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatZl(codepoint);
29064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_PARA:
29084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatZp(codepoint);
29094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL:
29114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatS(codepoint);
29124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MATH:
29144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatSm(codepoint);
29154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_CURRENCY:
29174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatSc(codepoint);
29184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MODIFIER:
29204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatSk(codepoint);
29214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_OTHERS:
29234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatSo(codepoint);
29244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER:
29264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatC(codepoint);
29274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_CONTROL:
29294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatCc(codepoint);
29304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_FORMAT:
29324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatCf(codepoint);
29334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_PRIVATE:
29354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatCo(codepoint);
29364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_NA:
29384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* ret = xmlUCSIsCatCn(codepoint); */
29394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* Seems it doesn't exist anymore in recent Unicode releases */
29404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = 0;
29414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_BLOCK_NAME:
29434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsBlock(codepoint, (const char *) blockName);
29444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
29464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (neg)
29474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(!ret);
29484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
29494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
29504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
29514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
29524255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint) {
29534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i, ret = 0;
29544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegRangePtr range;
29554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2956871611bb0325095b30559ff1edc1fdaa2ad5fd2fWilliam M. Brack    if ((atom == NULL) || (!IS_CHAR(codepoint)))
29574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
29584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
29594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (atom->type) {
29604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SUBREG:
29614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_EPSILON:
29624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
29634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_CHARVAL:
29644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            return(codepoint == atom->codepoint);
29654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_RANGES: {
29664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int accept = 0;
2967f2a1283564df8ded1942b231c60c3a7ae4ff748aDaniel Veillard
29684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    for (i = 0;i < atom->nbRanges;i++) {
29694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		range = atom->ranges[i];
2970f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		if (range->neg == 2) {
29714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
29724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard						0, range->start, range->end,
29734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard						range->blockName);
29744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret != 0)
29754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			return(0); /* excluded char */
2976f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		} else if (range->neg) {
2977f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
2978f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard						0, range->start, range->end,
2979f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard						range->blockName);
2980f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		    if (ret == 0)
2981f2a1283564df8ded1942b231c60c3a7ae4ff748aDaniel Veillard		        accept = 1;
2982f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		    else
2983f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		        return(0);
29844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		} else {
29854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
29864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard						0, range->start, range->end,
29874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard						range->blockName);
29884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret != 0)
29894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			accept = 1; /* might still be excluded */
29904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
29914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
29924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(accept);
29934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
29944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_STRING:
29954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    printf("TODO: XML_REGEXP_STRING\n");
29964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
29974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYCHAR:
29984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYSPACE:
29994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTSPACE:
30004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_INITNAME:
30014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTINITNAME:
30024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NAMECHAR:
30034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTNAMECHAR:
30044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_DECIMAL:
30054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTDECIMAL:
30064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_REALCHAR:
30074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTREALCHAR:
30084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER:
30094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_UPPERCASE:
30104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_LOWERCASE:
30114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_TITLECASE:
30124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_MODIFIER:
30134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_OTHERS:
30144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK:
30154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_NONSPACING:
30164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_SPACECOMBINING:
30174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_ENCLOSING:
30184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER:
30194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_DECIMAL:
30204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_LETTER:
30214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_OTHERS:
30224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT:
30234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CONNECTOR:
30244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_DASH:
30254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OPEN:
30264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CLOSE:
30274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_INITQUOTE:
30284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_FINQUOTE:
30294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OTHERS:
30304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR:
30314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_SPACE:
30324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_LINE:
30334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_PARA:
30344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL:
30354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MATH:
30364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_CURRENCY:
30374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MODIFIER:
30384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_OTHERS:
30394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER:
30404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_CONTROL:
30414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_FORMAT:
30424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_PRIVATE:
30434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_NA:
30444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_REGEXP_BLOCK_NAME:
30454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlRegCheckCharacterRange(atom->type, codepoint, 0, 0, 0,
30464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                            (const xmlChar *)atom->valuep);
30474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (atom->neg)
30484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = !ret;
30494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
30504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
30514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
30524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
30534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
30544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
30554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
3056ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack *	Saving and restoring state of an execution context		*
30574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
30584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
30594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
30604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
30614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
30624255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegDebugExec(xmlRegExecCtxtPtr exec) {
30634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("state: %d:%d:idx %d", exec->state->no, exec->transno, exec->index);
30644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->inputStack != NULL) {
30654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int i;
30664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf(": ");
30674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0;(i < 3) && (i < exec->inputStackNr);i++)
30680e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	    printf("%s ", (const char *)
30690e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	           exec->inputStack[exec->inputStackNr - (i + 1)].value);
30704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
30714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf(": %s", &(exec->inputString[exec->index]));
30724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
30734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("\n");
30744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
30754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
30764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
30774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
30784255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegExecSave(xmlRegExecCtxtPtr exec) {
30794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
30804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("saving ");
30814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno++;
30824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFARegDebugExec(exec);
30834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno--;
30844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
308594cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard#ifdef MAX_PUSH
308694cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    if (exec->nbPush > MAX_PUSH) {
308794cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard        return;
308894cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    }
308994cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    exec->nbPush++;
309094cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard#endif
30914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
30924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->maxRollbacks == 0) {
30934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->maxRollbacks = 4;
30944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->rollbacks = (xmlRegExecRollback *) xmlMalloc(exec->maxRollbacks *
30954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegExecRollback));
30964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->rollbacks == NULL) {
3097ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "saving regexp");
30984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->maxRollbacks = 0;
30994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
31004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
31014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	memset(exec->rollbacks, 0,
31024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	       exec->maxRollbacks * sizeof(xmlRegExecRollback));
31034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (exec->nbRollbacks >= exec->maxRollbacks) {
31044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegExecRollback *tmp;
31054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int len = exec->maxRollbacks;
31064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->maxRollbacks *= 2;
31084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegExecRollback *) xmlRealloc(exec->rollbacks,
31094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->maxRollbacks * sizeof(xmlRegExecRollback));
31104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
3111ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "saving regexp");
31124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->maxRollbacks /= 2;
31134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
31144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
31154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->rollbacks = tmp;
31164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = &exec->rollbacks[len];
31174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	memset(tmp, 0, (exec->maxRollbacks - len) * sizeof(xmlRegExecRollback));
31184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
31194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks[exec->nbRollbacks].state = exec->state;
31204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks[exec->nbRollbacks].index = exec->index;
31214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks[exec->nbRollbacks].nextbranch = exec->transno + 1;
31224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->comp->nbCounters > 0) {
31234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
31244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->rollbacks[exec->nbRollbacks].counts = (int *)
31254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlMalloc(exec->comp->nbCounters * sizeof(int));
31264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
3127ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard		xmlRegexpErrMemory(NULL, "saving regexp");
31284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -5;
31294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return;
31304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
31314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
31324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	memcpy(exec->rollbacks[exec->nbRollbacks].counts, exec->counts,
31334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	       exec->comp->nbCounters * sizeof(int));
31344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
31354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->nbRollbacks++;
31364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
31374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
31394255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegExecRollBack(xmlRegExecCtxtPtr exec) {
31404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->nbRollbacks <= 0) {
31414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->status = -1;
31424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
31434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf("rollback failed on empty stack\n");
31444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
31454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
31464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
31474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->nbRollbacks--;
31484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->state = exec->rollbacks[exec->nbRollbacks].state;
31494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->index = exec->rollbacks[exec->nbRollbacks].index;
31504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno = exec->rollbacks[exec->nbRollbacks].nextbranch;
31514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->comp->nbCounters > 0) {
31524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
31534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(stderr, "exec save: allocation failed");
31544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->status = -6;
31554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
31564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
31574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	memcpy(exec->counts, exec->rollbacks[exec->nbRollbacks].counts,
31584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	       exec->comp->nbCounters * sizeof(int));
31594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
31604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
31624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("restored ");
31634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFARegDebugExec(exec);
31644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
31654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
31664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
31684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
3169ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack *	Verifier, running an input against a compiled regexp		*
31704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
31714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
31724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
31744255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
31754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegExecCtxt execval;
31764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegExecCtxtPtr exec = &execval;
3177567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    int ret, codepoint = 0, len, deter;
31784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputString = content;
31804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->index = 0;
318194cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    exec->nbPush = 0;
31824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->determinist = 1;
31834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->maxRollbacks = 0;
31844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->nbRollbacks = 0;
31854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks = NULL;
31864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->status = 0;
31874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->comp = comp;
31884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->state = comp->states[0];
31894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno = 0;
31904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transcount = 0;
3191f2a1283564df8ded1942b231c60c3a7ae4ff748aDaniel Veillard    exec->inputStack = NULL;
3192f2a1283564df8ded1942b231c60c3a7ae4ff748aDaniel Veillard    exec->inputStackMax = 0;
31934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (comp->nbCounters > 0) {
31944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int));
3195ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	if (exec->counts == NULL) {
3196ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "running regexp");
31974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
3198ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	}
31994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        memset(exec->counts, 0, comp->nbCounters * sizeof(int));
32004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else
32014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->counts = NULL;
32024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((exec->status == 0) &&
32034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	   ((exec->inputString[exec->index] != 0) ||
3204ad55998f74ab7f89cc5ed454589fb8f528873a02Daniel Veillard	    ((exec->state != NULL) &&
3205ad55998f74ab7f89cc5ed454589fb8f528873a02Daniel Veillard	     (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
32064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegTransPtr trans;
32074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegAtomPtr atom;
32084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
32094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	/*
32100e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	 * If end of input on non-terminal state, rollback, however we may
32114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * still have epsilon like transition for counted transitions
32120e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	 * on counters, in that case don't break too early.  Additionally,
32130e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	 * if we are working on a range like "AB{0,2}", where B is not present,
32140e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	 * we don't want to break.
32154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 */
321611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard	len = 1;
32170e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	if ((exec->inputString[exec->index] == 0) && (exec->counts == NULL)) {
3218ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	    /*
3219ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	     * if there is a transition, we must check if
3220ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	     *  atom allows minOccurs of 0
3221ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	     */
3222ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	    if (exec->transno < exec->state->nbTrans) {
32230e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	        trans = &exec->state->trans[exec->transno];
32240e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		if (trans->to >=0) {
32250e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    atom = trans->atom;
32260e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    if (!((atom->min == 0) && (atom->max > 0)))
32270e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		        goto rollback;
32280e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		}
32290e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	    } else
32300e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	        goto rollback;
32310e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	}
32324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
32334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->transcount = 0;
32344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (;exec->transno < exec->state->nbTrans;exec->transno++) {
32354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    trans = &exec->state->trans[exec->transno];
32364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->to < 0)
32374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		continue;
32384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom = trans->atom;
32394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = 0;
3240567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    deter = 1;
32414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->count >= 0) {
32424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		int count;
32434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlRegCounterPtr counter;
32444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
324511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		if (exec->counts == NULL) {
324611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    exec->status = -1;
324711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    goto error;
324811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		}
32494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		/*
32504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 * A counted transition.
32514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 */
32524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
32534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		count = exec->counts[trans->count];
32544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		counter = &exec->comp->counters[trans->count];
32554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
32564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("testing count %d: val %d, min %d, max %d\n",
32574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		       trans->count, count, counter->min,  counter->max);
32584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
32594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = ((count >= counter->min) && (count <= counter->max));
3260567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		if ((ret) && (counter->min != counter->max))
3261567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    deter = 0;
32624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (atom == NULL) {
32634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		fprintf(stderr, "epsilon transition left at runtime\n");
32644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -2;
32654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
32664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (exec->inputString[exec->index] != 0) {
32674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard                codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len);
32684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = xmlRegCheckCharacter(atom, codepoint);
32690e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		if ((ret == 1) && (atom->min >= 0) && (atom->max > 0)) {
32704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlRegStatePtr to = comp->states[trans->to];
32714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
32724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
32734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * this is a multiple input sequence
3274fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		     * If there is a counter associated increment it now.
3275fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		     * before potentially saving and rollback
3276c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		     * do not increment if the counter is already over the
3277c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		     * maximum limit in which case get to next transition
32784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
3279fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		    if (trans->counter >= 0) {
3280c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			xmlRegCounterPtr counter;
3281c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard
3282c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			if ((exec->counts == NULL) ||
3283c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			    (exec->comp == NULL) ||
3284c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			    (exec->comp->counters == NULL)) {
328511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    exec->status = -1;
328611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    goto error;
328711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			}
3288c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			counter = &exec->comp->counters[trans->counter];
3289c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			if (exec->counts[trans->counter] >= counter->max)
3290c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			    continue; /* for loop on transitions */
3291c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard
3292fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard#ifdef DEBUG_REGEXP_EXEC
3293fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard			printf("Increasing count %d\n", trans->counter);
3294fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard#endif
3295fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard			exec->counts[trans->counter]++;
3296fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		    }
32974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->state->nbTrans > exec->transno + 1) {
32984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			xmlFARegExecSave(exec);
32994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
33004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->transcount = 1;
33014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    do {
33024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
33034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * Try to progress as much as possible on the input
33044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
33054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount == atom->max) {
33064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
33074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
33084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->index += len;
33094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
33104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * End of input: stop here
33114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
33124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->inputString[exec->index] == 0) {
33134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->index -= len;
33144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
33154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
33164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount >= atom->min) {
33174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    int transno = exec->transno;
33184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlRegStatePtr state = exec->state;
33194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
33204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    /*
33214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     * The transition is acceptable save it
33224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     */
33234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = -1; /* trick */
33244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = to;
33254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlFARegExecSave(exec);
33264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = transno;
33274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = state;
33284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
33294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			codepoint = CUR_SCHAR(&(exec->inputString[exec->index]),
33304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard				              len);
33314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = xmlRegCheckCharacter(atom, codepoint);
33324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->transcount++;
33334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    } while (ret == 1);
33344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->transcount < atom->min)
33354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
33364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
33374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
33384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * If the last check failed but one transition was found
33394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * possible, rollback
33404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
33414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret < 0)
33424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
33434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret == 0) {
33444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			goto rollback;
33454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
3346fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		    if (trans->counter >= 0) {
334711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			if (exec->counts == NULL) {
334811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    exec->status = -1;
334911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    goto error;
335011ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			}
3351fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard#ifdef DEBUG_REGEXP_EXEC
3352fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard			printf("Decreasing count %d\n", trans->counter);
3353fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard#endif
3354fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard			exec->counts[trans->counter]--;
3355fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		    }
33560e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		} else if ((ret == 0) && (atom->min == 0) && (atom->max > 0)) {
33570e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    /*
33580e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		     * we don't match on the codepoint, but minOccurs of 0
33590e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		     * says that's ok.  Setting len to 0 inhibits stepping
33600e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		     * over the codepoint.
33610e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		     */
33620e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    exec->transcount = 1;
33630e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    len = 0;
33640e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    ret = 1;
33654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
33660e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	    } else if ((atom->min == 0) && (atom->max > 0)) {
33670e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	        /* another spot to match when minOccurs is 0 */
33680e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		exec->transcount = 1;
33690e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		len = 0;
33700e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		ret = 1;
33714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
33724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 1) {
3373567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		if ((trans->nd == 1) ||
3374567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    ((trans->count >= 0) && (deter == 0) &&
3375567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (exec->state->nbTrans > exec->transno + 1))) {
3376aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
3377aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		    if (trans->nd == 1)
3378aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		        printf("Saving on nd transition atom %d for %c at %d\n",
3379aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard			       trans->atom->no, codepoint, exec->index);
3380aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		    else
3381aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		        printf("Saving on counted transition count %d for %c at %d\n",
3382aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard			       trans->count, codepoint, exec->index);
3383aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#endif
33844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFARegExecSave(exec);
33854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
33864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->counter >= 0) {
3387c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    xmlRegCounterPtr counter;
3388c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard
3389c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard                    /* make sure we don't go over the counter maximum value */
3390c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    if ((exec->counts == NULL) ||
3391c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			(exec->comp == NULL) ||
3392c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			(exec->comp->counters == NULL)) {
3393c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			exec->status = -1;
339411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			goto error;
339511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    }
3396c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    counter = &exec->comp->counters[trans->counter];
3397c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    if (exec->counts[trans->counter] >= counter->max)
3398c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			continue; /* for loop on transitions */
33994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
34004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Increasing count %d\n", trans->counter);
34014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
34024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->counts[trans->counter]++;
34034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
340410752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		if ((trans->count >= 0) &&
340510752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    (trans->count < REGEXP_ALL_COUNTER)) {
340611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    if (exec->counts == NULL) {
340711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		        exec->status = -1;
340811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			goto error;
340911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    }
341010752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard#ifdef DEBUG_REGEXP_EXEC
341110752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    printf("resetting count %d on transition\n",
341210752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		           trans->count);
341310752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard#endif
341410752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    exec->counts[trans->count] = 0;
341510752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		}
34164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
34174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("entering state %d\n", trans->to);
34184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
34194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->state = comp->states[trans->to];
34204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->transno = 0;
34214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->atom != NULL) {
34224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->index += len;
34234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
34244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		goto progress;
34254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (ret < 0) {
34264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -4;
34274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
34284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
34294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
34304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((exec->transno != 0) || (exec->state->nbTrans == 0)) {
34314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardrollback:
34324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /*
34334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Failed to find a way out
34344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     */
34354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->determinist = 0;
3436aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
3437aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	    printf("rollback from state %d on %d:%c\n", exec->state->no,
3438aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	           codepoint,codepoint);
3439aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#endif
34404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFARegExecRollBack(exec);
34414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
34424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardprogress:
34434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	continue;
34444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
344511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillarderror:
34464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->rollbacks != NULL) {
34474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->counts != NULL) {
34484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int i;
34494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
34504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    for (i = 0;i < exec->maxRollbacks;i++)
34514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (exec->rollbacks[i].counts != NULL)
34524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFree(exec->rollbacks[i].counts);
34534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
34544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->rollbacks);
34554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
34564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->counts != NULL)
34574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->counts);
34584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->status == 0)
34594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
346094cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    if (exec->status == -1) {
346194cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard	if (exec->nbPush > MAX_PUSH)
346294cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard	    return(-1);
34634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
346494cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    }
34654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(exec->status);
34664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
34674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
34684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
34694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
3470ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack *	Progressive interface to the verifier one atom at a time	*
34714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
34724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
34737bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#ifdef DEBUG_ERR
34747bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillardstatic void testerr(xmlRegExecCtxtPtr exec);
34757bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#endif
34764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
34774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
347801c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlRegNewExecCtxt:
34794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @comp: a precompiled regular expression
34804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @callback: a callback function used for handling progresses in the
34814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *            automata matching phase
34824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @data: the context data associated to the callback in this context
34834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
34844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Build a context used for progressive evaluation of a regexp.
348501c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard *
348601c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * Returns the new context
34874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
34884255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegExecCtxtPtr
34894255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) {
34904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegExecCtxtPtr exec;
34914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
34924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (comp == NULL)
34934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
3494a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if ((comp->compact == NULL) && (comp->states == NULL))
3495a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        return(NULL);
34964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt));
34974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec == NULL) {
3498ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	xmlRegexpErrMemory(NULL, "creating execution context");
34994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
35004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
35014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    memset(exec, 0, sizeof(xmlRegExecCtxt));
35024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputString = NULL;
35034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->index = 0;
35044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->determinist = 1;
35054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->maxRollbacks = 0;
35064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->nbRollbacks = 0;
35074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks = NULL;
35084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->status = 0;
35094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->comp = comp;
351023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (comp->compact == NULL)
351123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	exec->state = comp->states[0];
35124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno = 0;
35134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transcount = 0;
35144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->callback = callback;
35154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->data = data;
35164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (comp->nbCounters > 0) {
35177bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        /*
35187bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	 * For error handling, exec->counts is allocated twice the size
35197bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	 * the second half is used to store the data in case of rollback
35207bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	 */
35217bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)
35227bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	                                 * 2);
35234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->counts == NULL) {
3524ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "creating execution context");
35254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFree(exec);
35264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(NULL);
35274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
35287bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        memset(exec->counts, 0, comp->nbCounters * sizeof(int) * 2);
35297bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	exec->errCounts = &exec->counts[comp->nbCounters];
35307bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    } else {
35314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->counts = NULL;
35327bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	exec->errCounts = NULL;
35337bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    }
35344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStackMax = 0;
35354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStackNr = 0;
35364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack = NULL;
35377bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    exec->errStateNo = -1;
35387bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    exec->errString = NULL;
353994cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    exec->nbPush = 0;
35404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(exec);
35414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
35424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
35444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegFreeExecCtxt:
35454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @exec: a regular expression evaulation context
35464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
35474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free the structures associated to a regular expression evaulation context.
35484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
35494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
35504255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegFreeExecCtxt(xmlRegExecCtxtPtr exec) {
35514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec == NULL)
35524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
35534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->rollbacks != NULL) {
35554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->counts != NULL) {
35564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int i;
35574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    for (i = 0;i < exec->maxRollbacks;i++)
35594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (exec->rollbacks[i].counts != NULL)
35604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFree(exec->rollbacks[i].counts);
35614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
35624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->rollbacks);
35634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
35644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->counts != NULL)
35654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->counts);
35664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->inputStack != NULL) {
35674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int i;
35684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35693237023d6a8036dff817c3d46485ce6495d8ae21Daniel Veillard	for (i = 0;i < exec->inputStackNr;i++) {
35703237023d6a8036dff817c3d46485ce6495d8ae21Daniel Veillard	    if (exec->inputStack[i].value != NULL)
35713237023d6a8036dff817c3d46485ce6495d8ae21Daniel Veillard		xmlFree(exec->inputStack[i].value);
35723237023d6a8036dff817c3d46485ce6495d8ae21Daniel Veillard	}
35734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->inputStack);
35744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
35757bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    if (exec->errString != NULL)
35767bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        xmlFree(exec->errString);
35774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(exec);
35784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
35794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
35814255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value,
35824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	                    void *data) {
35834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
35844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("saving value: %d:%s\n", exec->inputStackNr, value);
35854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
35864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->inputStackMax == 0) {
35874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->inputStackMax = 4;
35884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->inputStack = (xmlRegInputTokenPtr)
35894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken));
35904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->inputStack == NULL) {
3591ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "pushing input string");
35924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->inputStackMax = 0;
35934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
35944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
35954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (exec->inputStackNr + 1 >= exec->inputStackMax) {
35964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegInputTokenPtr tmp;
35974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->inputStackMax *= 2;
35994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegInputTokenPtr) xmlRealloc(exec->inputStack,
36004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->inputStackMax * sizeof(xmlRegInputToken));
36014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
3602ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "pushing input string");
36034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->inputStackMax /= 2;
36044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
36054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
36064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->inputStack = tmp;
36074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
36084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack[exec->inputStackNr].value = xmlStrdup(value);
36094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack[exec->inputStackNr].data = data;
36104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStackNr++;
36114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack[exec->inputStackNr].value = NULL;
36124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack[exec->inputStackNr].data = NULL;
36134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
36144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3615c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard/**
3616c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * xmlRegStrEqualWildcard:
3617c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * @expStr:  the string to be evaluated
3618c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * @valStr:  the validation string
3619c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard *
3620c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * Checks if both strings are equal or have the same content. "*"
3621c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * can be used as a wildcard in @valStr; "|" is used as a seperator of
3622c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * substrings in both @expStr and @valStr.
3623c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard *
3624c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * Returns 1 if the comparison is satisfied and the number of substrings
3625c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * is equal, 0 otherwise.
3626c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard */
3627c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard
3628c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillardstatic int
3629c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel VeillardxmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr) {
3630c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    if (expStr == valStr) return(1);
3631c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    if (expStr == NULL) return(0);
3632c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    if (valStr == NULL) return(0);
3633c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    do {
3634c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	/*
3635c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	* Eval if we have a wildcard for the current item.
3636c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	*/
3637c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard        if (*expStr != *valStr) {
36384f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	    /* if one of them starts with a wildcard make valStr be it */
36394f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	    if (*valStr == '*') {
36404f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	        const xmlChar *tmp;
36414f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard
36424f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard		tmp = valStr;
36434f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard		valStr = expStr;
36444f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard		expStr = tmp;
36454f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	    }
3646c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	    if ((*valStr != 0) && (*expStr != 0) && (*expStr++ == '*')) {
3647c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		do {
3648c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		    if (*valStr == XML_REG_STRING_SEPARATOR)
3649c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard			break;
3650c0e833f0024d46f50772620f24e6cf9d93748017Kasimier T. Buchcik		    valStr++;
3651c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		} while (*valStr != 0);
3652c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		continue;
3653c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	    } else
3654c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		return(0);
3655c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	}
3656c0e833f0024d46f50772620f24e6cf9d93748017Kasimier T. Buchcik	expStr++;
3657c0e833f0024d46f50772620f24e6cf9d93748017Kasimier T. Buchcik	valStr++;
3658c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    } while (*valStr != 0);
3659c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    if (*expStr != 0)
3660c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	return (0);
3661c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    else
3662c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	return (1);
3663c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard}
36644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
36654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
366623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * xmlRegCompactPushString:
366723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @exec: a regexp execution context
366823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @comp:  the precompiled exec with a compact table
366923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @value: a string token input
367023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @data: data associated to the token to reuse in callbacks
367123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *
367223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * Push one input token in the execution context
367323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *
367423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * Returns: 1 if the regexp reached a final state, 0 if non-final, and
367523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *     a negative value in case of error.
367623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard */
367723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillardstatic int
367823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel VeillardxmlRegCompactPushString(xmlRegExecCtxtPtr exec,
367923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	                xmlRegexpPtr comp,
368023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	                const xmlChar *value,
368123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	                void *data) {
368223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int state = exec->index;
368323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int i, target;
368423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
368523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if ((comp == NULL) || (comp->compact == NULL) || (comp->stringMap == NULL))
368623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(-1);
368723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
368823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (value == NULL) {
368923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	/*
369023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * are we at a final state ?
369123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 */
369223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	if (comp->compact[state * (comp->nbstrings + 1)] ==
369323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard            XML_REGEXP_FINAL_STATE)
369423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    return(1);
369523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(0);
369623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
369723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
369823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_PUSH
369923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    printf("value pushed: %s\n", value);
370023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
370123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
370223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    /*
3703ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack     * Examine all outside transitions from current state
370423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     */
370523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    for (i = 0;i < comp->nbstrings;i++) {
370623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
370723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	if ((target > 0) && (target <= comp->nbstates)) {
3708c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	    target--; /* to avoid 0 */
3709c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	    if (xmlRegStrEqualWildcard(comp->stringMap[i], value)) {
3710c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		exec->index = target;
3711118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		if ((exec->callback != NULL) && (comp->transdata != NULL)) {
3712118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		    exec->callback(exec->data, value,
3713118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			  comp->transdata[state * comp->nbstrings + i], data);
3714118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		}
371523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_PUSH
371623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		printf("entering state %d\n", target);
371723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
371823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		if (comp->compact[target * (comp->nbstrings + 1)] ==
3719cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    XML_REGEXP_SINK_STATE)
3720cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    goto error;
3721cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard
3722cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		if (comp->compact[target * (comp->nbstrings + 1)] ==
372323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    XML_REGEXP_FINAL_STATE)
372423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    return(1);
372523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		return(0);
372623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    }
372723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
372823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
372923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    /*
373023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     * Failed to find an exit transition out from current state for the
373123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     * current token
373223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     */
373323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_PUSH
373423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    printf("failed to find a transition for %s on state %d\n", value, state);
373523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
3736cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillarderror:
37377bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    if (exec->errString != NULL)
37387bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        xmlFree(exec->errString);
37397bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    exec->errString = xmlStrdup(value);
37407bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    exec->errStateNo = state;
374123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    exec->status = -1;
37427bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#ifdef DEBUG_ERR
37437bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    testerr(exec);
37447bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#endif
374523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    return(-1);
374623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard}
374723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
374823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard/**
37496e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * xmlRegExecPushStringInternal:
3750ea7751d53bf497e873dca39b2c305e300e2574f9Daniel Veillard * @exec: a regexp execution context or NULL to indicate the end
37514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @value: a string token input
37524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @data: data associated to the token to reuse in callbacks
37536e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * @compound: value was assembled from 2 strings
37544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
37554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Push one input token in the execution context
37564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
37574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns: 1 if the regexp reached a final state, 0 if non-final, and
37584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *     a negative value in case of error.
37594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
37606e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillardstatic int
37616e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel VeillardxmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
37626e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard	                     void *data, int compound) {
37634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegTransPtr trans;
37644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
37654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
37664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int final = 0;
37679070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard    int progress = 1;
37684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
37694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec == NULL)
37704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
377123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (exec->comp == NULL)
377223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(-1);
37734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->status != 0)
37744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(exec->status);
37754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
377623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (exec->comp->compact != NULL)
377723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(xmlRegCompactPushString(exec, exec->comp, value, data));
377823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
37794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (value == NULL) {
37804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        if (exec->state->type == XML_REGEXP_FINAL_STATE)
37814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
37824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	final = 1;
37834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
37844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
37854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
37864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("value pushed: %s\n", value);
37874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
37884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /*
37894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * If we have an active rollback stack push the new value there
37904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * and get back to where we were left
37914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     */
37924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((value != NULL) && (exec->inputStackNr > 0)) {
37934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFARegExecSaveInputString(exec, value, data);
37944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	value = exec->inputStack[exec->index].value;
37954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	data = exec->inputStack[exec->index].data;
37964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
37974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf("value loaded: %s\n", value);
37984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
37994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
38004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((exec->status == 0) &&
38024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	   ((value != NULL) ||
38034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ((final == 1) &&
38044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
38054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	/*
38074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * End of input on non-terminal state, rollback, however we may
38084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * still have epsilon like transition for counted transitions
38094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * on counters, in that case don't break too early.
38104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 */
3811b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	if ((value == NULL) && (exec->counts == NULL))
38124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    goto rollback;
38134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->transcount = 0;
38154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (;exec->transno < exec->state->nbTrans;exec->transno++) {
38164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    trans = &exec->state->trans[exec->transno];
38174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->to < 0)
38184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		continue;
38194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom = trans->atom;
38204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = 0;
3821441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
3822441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		int i;
3823441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		int count;
3824441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		xmlRegTransPtr t;
3825441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		xmlRegCounterPtr counter;
3826441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard
3827441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		ret = 0;
3828441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard
3829441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard#ifdef DEBUG_PUSH
3830441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		printf("testing all lax %d\n", trans->count);
3831441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard#endif
3832441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		/*
3833441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		 * Check all counted transitions from the current state
3834441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		 */
3835441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		if ((value == NULL) && (final)) {
3836441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    ret = 1;
3837441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		} else if (value != NULL) {
3838441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    for (i = 0;i < exec->state->nbTrans;i++) {
3839441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			t = &exec->state->trans[i];
3840441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			if ((t->counter < 0) || (t == trans))
3841441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    continue;
3842441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			counter = &exec->comp->counters[t->counter];
3843441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			count = exec->counts[t->counter];
3844441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			if ((count < counter->max) &&
3845441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		            (t->atom != NULL) &&
3846441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    (xmlStrEqual(value, t->atom->valuep))) {
3847441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    ret = 0;
3848441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    break;
3849441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			}
3850441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			if ((count >= counter->min) &&
3851441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    (count < counter->max) &&
385211ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    (t->atom != NULL) &&
3853441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    (xmlStrEqual(value, t->atom->valuep))) {
3854441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    ret = 1;
3855441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    break;
3856441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			}
3857441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    }
3858441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		}
3859441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard	    } else if (trans->count == REGEXP_ALL_COUNTER) {
38608a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		int i;
38618a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		int count;
38628a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		xmlRegTransPtr t;
38638a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		xmlRegCounterPtr counter;
38648a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard
38658a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		ret = 1;
38668a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard
38678a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard#ifdef DEBUG_PUSH
38688a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		printf("testing all %d\n", trans->count);
38698a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard#endif
38708a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		/*
38718a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		 * Check all counted transitions from the current state
38728a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		 */
38738a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		for (i = 0;i < exec->state->nbTrans;i++) {
38748a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard                    t = &exec->state->trans[i];
38758a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		    if ((t->counter < 0) || (t == trans))
38768a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard			continue;
38778a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard                    counter = &exec->comp->counters[t->counter];
38788a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		    count = exec->counts[t->counter];
38798a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		    if ((count < counter->min) || (count > counter->max)) {
38808a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard			ret = 0;
38818a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard			break;
38828a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		    }
38838a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		}
38848a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard	    } else if (trans->count >= 0) {
38854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		int count;
38864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlRegCounterPtr counter;
38874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		/*
38894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 * A counted transition.
38904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 */
38914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		count = exec->counts[trans->count];
38934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		counter = &exec->comp->counters[trans->count];
38944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
38954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("testing count %d: val %d, min %d, max %d\n",
38964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		       trans->count, count, counter->min,  counter->max);
38974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
38984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = ((count >= counter->min) && (count <= counter->max));
38994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (atom == NULL) {
39004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		fprintf(stderr, "epsilon transition left at runtime\n");
39014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -2;
39024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
39034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (value != NULL) {
3904c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		ret = xmlRegStrEqualWildcard(atom->valuep, value);
39056e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard		if (atom->neg) {
39069efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard		    ret = !ret;
39076e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard		    if (!compound)
39086e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard		        ret = 0;
39096e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard		}
3910441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		if ((ret == 1) && (trans->counter >= 0)) {
3911441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    xmlRegCounterPtr counter;
3912441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    int count;
3913441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard
3914441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    count = exec->counts[trans->counter];
3915441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    counter = &exec->comp->counters[trans->counter];
3916441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    if (count >= counter->max)
3917441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			ret = 0;
3918441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		}
3919441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard
39204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if ((ret == 1) && (atom->min > 0) && (atom->max > 0)) {
39214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlRegStatePtr to = exec->comp->states[trans->to];
39224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
39234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
39244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * this is a multiple input sequence
39254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
39264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->state->nbTrans > exec->transno + 1) {
39274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->inputStackNr <= 0) {
39284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlFARegExecSaveInputString(exec, value, data);
39294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
39304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			xmlFARegExecSave(exec);
39314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
39324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->transcount = 1;
39334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    do {
39344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
39354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * Try to progress as much as possible on the input
39364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
39374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount == atom->max) {
39384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
39394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
39404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->index++;
39414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			value = exec->inputStack[exec->index].value;
39424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			data = exec->inputStack[exec->index].data;
39434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
39444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			printf("value loaded: %s\n", value);
39454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
39464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
39474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
39484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * End of input: stop here
39494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
39504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (value == NULL) {
39514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->index --;
39524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
39534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
39544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount >= atom->min) {
39554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    int transno = exec->transno;
39564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlRegStatePtr state = exec->state;
39574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
39584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    /*
39594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     * The transition is acceptable save it
39604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     */
39614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = -1; /* trick */
39624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = to;
39634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    if (exec->inputStackNr <= 0) {
39644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard				xmlFARegExecSaveInputString(exec, value, data);
39654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    }
39664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlFARegExecSave(exec);
39674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = transno;
39684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = state;
39694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
39704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = xmlStrEqual(value, atom->valuep);
39714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->transcount++;
39724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    } while (ret == 1);
39734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->transcount < atom->min)
39744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
39754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
39764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
39774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * If the last check failed but one transition was found
39784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * possible, rollback
39794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
39804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret < 0)
39814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
39824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret == 0) {
39834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			goto rollback;
39844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
39854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
39864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
39874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 1) {
39889887395b556af391306245b52487c215337c4054William M. Brack		if ((exec->callback != NULL) && (atom != NULL) &&
39899887395b556af391306245b52487c215337c4054William M. Brack			(data != NULL)) {
39904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->callback(exec->data, atom->valuep,
39914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			           atom->data, data);
39924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
39934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (exec->state->nbTrans > exec->transno + 1) {
39944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->inputStackNr <= 0) {
39954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			xmlFARegExecSaveInputString(exec, value, data);
39964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
39974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFARegExecSave(exec);
39984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
39994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->counter >= 0) {
40004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Increasing count %d\n", trans->counter);
40024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->counts[trans->counter]++;
40044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
400510752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		if ((trans->count >= 0) &&
400610752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    (trans->count < REGEXP_ALL_COUNTER)) {
400710752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard#ifdef DEBUG_REGEXP_EXEC
400810752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    printf("resetting count %d on transition\n",
400910752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		           trans->count);
401010752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard#endif
401110752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    exec->counts[trans->count] = 0;
401210752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		}
40134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("entering state %d\n", trans->to);
40154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
4016cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                if ((exec->comp->states[trans->to] != NULL) &&
4017cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (exec->comp->states[trans->to]->type ==
4018cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     XML_REGEXP_SINK_STATE)) {
4019cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    /*
4020cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     * entering a sink state, save the current state as error
4021cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     * state.
4022cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     */
4023cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    if (exec->errString != NULL)
4024cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard			xmlFree(exec->errString);
4025cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    exec->errString = xmlStrdup(value);
4026cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    exec->errState = exec->state;
4027cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    memcpy(exec->errCounts, exec->counts,
4028cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard			   exec->comp->nbCounters * sizeof(int));
4029cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		}
40304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->state = exec->comp->states[trans->to];
40314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->transno = 0;
40324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->atom != NULL) {
40334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->inputStack != NULL) {
40344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->index++;
40354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->index < exec->inputStackNr) {
40364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    value = exec->inputStack[exec->index].value;
40374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    data = exec->inputStack[exec->index].data;
40384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    printf("value loaded: %s\n", value);
40404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			} else {
40424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    value = NULL;
40434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    data = NULL;
40444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    printf("end of input\n");
40464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
40484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    } else {
40494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			value = NULL;
40504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			data = NULL;
40514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			printf("end of input\n");
40534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
40554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
40564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		goto progress;
40574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (ret < 0) {
40584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -4;
40594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
40604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
40614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
40624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((exec->transno != 0) || (exec->state->nbTrans == 0)) {
40634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardrollback:
40649070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard            /*
4065cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     * if we didn't yet rollback on the current input
4066cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     * store the current state as the error state.
40679070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard	     */
4068cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if ((progress) && (exec->state != NULL) &&
4069cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        (exec->state->type != XML_REGEXP_SINK_STATE)) {
40709070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard	        progress = 0;
40719070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		if (exec->errString != NULL)
40729070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		    xmlFree(exec->errString);
40739070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		exec->errString = xmlStrdup(value);
40749070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		exec->errState = exec->state;
40759070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		memcpy(exec->errCounts, exec->counts,
40769070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		       exec->comp->nbCounters * sizeof(int));
40779070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard	    }
40789070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard
40794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /*
40804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Failed to find a way out
40814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     */
40824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->determinist = 0;
40834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFARegExecRollBack(exec);
40844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (exec->status == 0) {
40854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		value = exec->inputStack[exec->index].value;
40864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		data = exec->inputStack[exec->index].data;
40874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("value loaded: %s\n", value);
40894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
40914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
40929070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard	continue;
40934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardprogress:
40949070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard        progress = 1;
40954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	continue;
40964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
40974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->status == 0) {
40984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return(exec->state->type == XML_REGEXP_FINAL_STATE);
40994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
41007bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#ifdef DEBUG_ERR
41019070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard    if (exec->status < 0) {
41027bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	testerr(exec);
41037bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    }
41049070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard#endif
41054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(exec->status);
41064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
41074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
410852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard/**
41096e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * xmlRegExecPushString:
41106e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * @exec: a regexp execution context or NULL to indicate the end
41116e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * @value: a string token input
41126e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * @data: data associated to the token to reuse in callbacks
41136e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard *
41146e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * Push one input token in the execution context
41156e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard *
41166e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * Returns: 1 if the regexp reached a final state, 0 if non-final, and
41176e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard *     a negative value in case of error.
41186e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard */
41196e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillardint
41206e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel VeillardxmlRegExecPushString(xmlRegExecCtxtPtr exec, const xmlChar *value,
41216e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard	             void *data) {
41226e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    return(xmlRegExecPushStringInternal(exec, value, data, 0));
41236e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard}
41246e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard
41256e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard/**
412652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * xmlRegExecPushString2:
412752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @exec: a regexp execution context or NULL to indicate the end
412852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @value: the first string token input
412952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @value2: the second string token input
413052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @data: data associated to the token to reuse in callbacks
413152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *
413252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * Push one input token in the execution context
413352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *
413452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * Returns: 1 if the regexp reached a final state, 0 if non-final, and
413552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *     a negative value in case of error.
413652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard */
413752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillardint
413852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel VeillardxmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value,
413952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard                      const xmlChar *value2, void *data) {
414052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    xmlChar buf[150];
414152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    int lenn, lenp, ret;
414252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    xmlChar *str;
414352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
414452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (exec == NULL)
414552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(-1);
414652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (exec->comp == NULL)
414752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(-1);
414852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (exec->status != 0)
414952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(exec->status);
415052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
415152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (value2 == NULL)
415252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard        return(xmlRegExecPushString(exec, value, data));
415352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
415452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    lenn = strlen((char *) value2);
415552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    lenp = strlen((char *) value);
415652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
415752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (150 < lenn + lenp + 2) {
41583c908dca479ed50dca24b8593bca90e40dbde6b8Daniel Veillard	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
415952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	if (str == NULL) {
416052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	    exec->status = -1;
416152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	    return(-1);
416252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	}
416352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    } else {
416452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	str = buf;
416552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    }
416652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    memcpy(&str[0], value, lenp);
4167c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    str[lenp] = XML_REG_STRING_SEPARATOR;
416852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    memcpy(&str[lenp + 1], value2, lenn);
416952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    str[lenn + lenp + 1] = 0;
417052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
417152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (exec->comp->compact != NULL)
417252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	ret = xmlRegCompactPushString(exec, exec->comp, str, data);
417352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    else
41746e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard        ret = xmlRegExecPushStringInternal(exec, str, data, 1);
417552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
417652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (str != buf)
41770b1ff14bd0c7c50f8cdce96478615570e1435c4fDaniel Veillard        xmlFree(str);
417852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    return(ret);
417952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard}
418052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
41817bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard/**
418277005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard * xmlRegExecGetValues:
4183fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @exec: a regexp execution context
4184fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @err: error extraction or normal one
41857bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard * @nbval: pointer to the number of accepted values IN/OUT
4186cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard * @nbneg: return number of negative transitions
41877bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard * @values: pointer to the array of acceptable values
4188fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @terminal: return value if this was a terminal state
41897bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard *
4190fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Extract informations from the regexp execution, internal routine to
4191fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * implement xmlRegExecNextValues() and xmlRegExecErrInfo()
41927bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard *
41937bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard * Returns: 0 in case of success or -1 in case of error.
41947bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard */
4195fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillardstatic int
4196fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel VeillardxmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
4197cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                    int *nbval, int *nbneg,
4198cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    xmlChar **values, int *terminal) {
41997bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    int maxval;
4200cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    int nb = 0;
42017bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
4202cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    if ((exec == NULL) || (nbval == NULL) || (nbneg == NULL) ||
4203cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard        (values == NULL) || (*nbval <= 0))
42047bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        return(-1);
4205fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
42067bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    maxval = *nbval;
42077bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    *nbval = 0;
4208cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    *nbneg = 0;
42097bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    if ((exec->comp != NULL) && (exec->comp->compact != NULL)) {
42107bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        xmlRegexpPtr comp;
42117bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	int target, i, state;
42127bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
42137bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        comp = exec->comp;
4214fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
4215fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	if (err) {
4216fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (exec->errStateNo == -1) return(-1);
4217fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    state = exec->errStateNo;
4218fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	} else {
4219fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    state = exec->index;
4220fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	}
4221fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	if (terminal != NULL) {
4222fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (comp->compact[state * (comp->nbstrings + 1)] ==
4223fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	        XML_REGEXP_FINAL_STATE)
4224fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		*terminal = 1;
4225fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    else
4226fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		*terminal = 0;
4227fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	}
4228cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	for (i = 0;(i < comp->nbstrings) && (nb < maxval);i++) {
42297bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
4230cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if ((target > 0) && (target <= comp->nbstates) &&
4231cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        (comp->compact[(target - 1) * (comp->nbstrings + 1)] !=
4232cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		 XML_REGEXP_SINK_STATE)) {
4233cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        values[nb++] = comp->stringMap[i];
42347bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		(*nbval)++;
42357bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    }
42367bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	}
4237cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	for (i = 0;(i < comp->nbstrings) && (nb < maxval);i++) {
4238cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
4239cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if ((target > 0) && (target <= comp->nbstates) &&
4240cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        (comp->compact[(target - 1) * (comp->nbstrings + 1)] ==
4241cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		 XML_REGEXP_SINK_STATE)) {
4242cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        values[nb++] = comp->stringMap[i];
4243cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		(*nbneg)++;
4244cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    }
4245cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	}
42467bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    } else {
42477bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        int transno;
42487bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	xmlRegTransPtr trans;
42497bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	xmlRegAtomPtr atom;
4250fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	xmlRegStatePtr state;
4251fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
4252fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	if (terminal != NULL) {
4253fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (exec->state->type == XML_REGEXP_FINAL_STATE)
4254fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		*terminal = 1;
4255fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    else
4256fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		*terminal = 0;
4257fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	}
42587bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
4259fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	if (err) {
4260fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (exec->errState == NULL) return(-1);
4261fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    state = exec->errState;
4262fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	} else {
4263fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (exec->state == NULL) return(-1);
4264fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    state = exec->state;
4265fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	}
42667bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	for (transno = 0;
4267cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     (transno < state->nbTrans) && (nb < maxval);
42687bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	     transno++) {
4269fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    trans = &state->trans[transno];
42707bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    if (trans->to < 0)
42717bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		continue;
42727bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    atom = trans->atom;
42737bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    if ((atom == NULL) || (atom->valuep == NULL))
42747bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		continue;
42757bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
4276cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        /* this should not be reached but ... */
42777bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	        TODO;
42787bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    } else if (trans->count == REGEXP_ALL_COUNTER) {
4279cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        /* this should not be reached but ... */
42807bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	        TODO;
42817bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    } else if (trans->counter >= 0) {
428211ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		xmlRegCounterPtr counter = NULL;
42837bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		int count;
42847bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
4285fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		if (err)
4286fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		    count = exec->errCounts[trans->counter];
4287fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		else
4288fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		    count = exec->counts[trans->counter];
428911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		if (exec->comp != NULL)
429011ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    counter = &exec->comp->counters[trans->counter];
429111ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		if ((counter == NULL) || (count < counter->max)) {
429277005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    if (atom->neg)
429377005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep2;
429477005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    else
429577005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep;
42967bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		    (*nbval)++;
42977bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		}
42987bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    } else {
4299cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                if ((exec->comp->states[trans->to] != NULL) &&
4300cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (exec->comp->states[trans->to]->type !=
4301cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     XML_REGEXP_SINK_STATE)) {
430277005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    if (atom->neg)
430377005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep2;
430477005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    else
430577005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep;
4306cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (*nbval)++;
4307cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		}
4308cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    }
4309cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	}
4310cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	for (transno = 0;
4311cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     (transno < state->nbTrans) && (nb < maxval);
4312cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     transno++) {
4313cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    trans = &state->trans[transno];
4314cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if (trans->to < 0)
4315cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		continue;
4316cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    atom = trans->atom;
4317cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if ((atom == NULL) || (atom->valuep == NULL))
4318cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		continue;
4319cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
4320cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        continue;
4321cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    } else if (trans->count == REGEXP_ALL_COUNTER) {
4322cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        continue;
4323cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    } else if (trans->counter >= 0) {
4324cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        continue;
4325cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    } else {
4326cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                if ((exec->comp->states[trans->to] != NULL) &&
4327cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (exec->comp->states[trans->to]->type ==
4328cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     XML_REGEXP_SINK_STATE)) {
432977005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    if (atom->neg)
433077005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep2;
433177005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    else
433277005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep;
4333cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (*nbneg)++;
4334cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		}
43357bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    }
43367bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	}
43377bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    }
43387bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    return(0);
43397bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard}
43407bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
4341fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard/**
4342fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * xmlRegExecNextValues:
4343fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @exec: a regexp execution context
4344fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @nbval: pointer to the number of accepted values IN/OUT
4345cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard * @nbneg: return number of negative transitions
4346fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @values: pointer to the array of acceptable values
4347fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @terminal: return value if this was a terminal state
4348fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard *
4349fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Extract informations from the regexp execution,
4350fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * the parameter @values must point to an array of @nbval string pointers
4351fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * on return nbval will contain the number of possible strings in that
4352fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * state and the @values array will be updated with them. The string values
4353fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * returned will be freed with the @exec context and don't need to be
4354fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * deallocated.
4355fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard *
4356fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Returns: 0 in case of success or -1 in case of error.
4357fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard */
4358fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillardint
4359cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel VeillardxmlRegExecNextValues(xmlRegExecCtxtPtr exec, int *nbval, int *nbneg,
4360cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                     xmlChar **values, int *terminal) {
4361cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    return(xmlRegExecGetValues(exec, 0, nbval, nbneg, values, terminal));
4362fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard}
4363fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
4364fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard/**
4365fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * xmlRegExecErrInfo:
4366fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @exec: a regexp execution context generating an error
4367fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @string: return value for the error string
4368fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @nbval: pointer to the number of accepted values IN/OUT
4369cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard * @nbneg: return number of negative transitions
4370fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @values: pointer to the array of acceptable values
4371fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @terminal: return value if this was a terminal state
4372fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard *
4373fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Extract error informations from the regexp execution, the parameter
4374fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @string will be updated with the value pushed and not accepted,
4375fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * the parameter @values must point to an array of @nbval string pointers
4376fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * on return nbval will contain the number of possible strings in that
4377fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * state and the @values array will be updated with them. The string values
4378fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * returned will be freed with the @exec context and don't need to be
4379fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * deallocated.
4380fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard *
4381fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Returns: 0 in case of success or -1 in case of error.
4382fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard */
4383fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillardint
4384fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel VeillardxmlRegExecErrInfo(xmlRegExecCtxtPtr exec, const xmlChar **string,
4385cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                  int *nbval, int *nbneg, xmlChar **values, int *terminal) {
4386fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard    if (exec == NULL)
4387fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard        return(-1);
4388fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard    if (string != NULL) {
4389fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard        if (exec->status != 0)
4390fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    *string = exec->errString;
4391fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	else
4392fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    *string = NULL;
4393fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard    }
4394cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    return(xmlRegExecGetValues(exec, 1, nbval, nbneg, values, terminal));
4395fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard}
4396fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
43977bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#ifdef DEBUG_ERR
43987bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillardstatic void testerr(xmlRegExecCtxtPtr exec) {
43997bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    const xmlChar *string;
4400cee2b3a5f124e19db46109132c22e1b8faec1c87Daniel Veillard    xmlChar *values[5];
44017bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    int nb = 5;
4402cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    int nbneg;
4403fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard    int terminal;
4404cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    xmlRegExecErrInfo(exec, &string, &nb, &nbneg, &values[0], &terminal);
44057bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard}
44067bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#endif
44077bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
44084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#if 0
44094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
44104255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
44114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegTransPtr trans;
44124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
44134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
44144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int codepoint, len;
44154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec == NULL)
44174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
44184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->status != 0)
44194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(exec->status);
44204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((exec->status == 0) &&
44224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	   ((exec->inputString[exec->index] != 0) ||
44234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    (exec->state->type != XML_REGEXP_FINAL_STATE))) {
44244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	/*
44264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * End of input on non-terminal state, rollback, however we may
44274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * still have epsilon like transition for counted transitions
44284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * on counters, in that case don't break too early.
44294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 */
44304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((exec->inputString[exec->index] == 0) && (exec->counts == NULL))
44314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    goto rollback;
44324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->transcount = 0;
44344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (;exec->transno < exec->state->nbTrans;exec->transno++) {
44354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    trans = &exec->state->trans[exec->transno];
44364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->to < 0)
44374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		continue;
44384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom = trans->atom;
44394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = 0;
44404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->count >= 0) {
44414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		int count;
44424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlRegCounterPtr counter;
44434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		/*
44454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 * A counted transition.
44464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 */
44474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		count = exec->counts[trans->count];
44494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		counter = &exec->comp->counters[trans->count];
44504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
44514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("testing count %d: val %d, min %d, max %d\n",
44524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		       trans->count, count, counter->min,  counter->max);
44534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
44544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = ((count >= counter->min) && (count <= counter->max));
44554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (atom == NULL) {
44564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		fprintf(stderr, "epsilon transition left at runtime\n");
44574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -2;
44584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
44594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (exec->inputString[exec->index] != 0) {
44604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard                codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len);
44614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = xmlRegCheckCharacter(atom, codepoint);
44624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if ((ret == 1) && (atom->min > 0) && (atom->max > 0)) {
44634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlRegStatePtr to = exec->comp->states[trans->to];
44644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
44664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * this is a multiple input sequence
44674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
44684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->state->nbTrans > exec->transno + 1) {
44694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			xmlFARegExecSave(exec);
44704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
44714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->transcount = 1;
44724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    do {
44734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
44744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * Try to progress as much as possible on the input
44754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
44764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount == atom->max) {
44774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
44784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
44794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->index += len;
44804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
44814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * End of input: stop here
44824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
44834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->inputString[exec->index] == 0) {
44844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->index -= len;
44854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
44864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
44874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount >= atom->min) {
44884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    int transno = exec->transno;
44894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlRegStatePtr state = exec->state;
44904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    /*
44924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     * The transition is acceptable save it
44934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     */
44944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = -1; /* trick */
44954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = to;
44964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlFARegExecSave(exec);
44974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = transno;
44984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = state;
44994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
45004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			codepoint = CUR_SCHAR(&(exec->inputString[exec->index]),
45014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard				              len);
45024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = xmlRegCheckCharacter(atom, codepoint);
45034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->transcount++;
45044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    } while (ret == 1);
45054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->transcount < atom->min)
45064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
45074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
45094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * If the last check failed but one transition was found
45104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * possible, rollback
45114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
45124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret < 0)
45134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
45144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret == 0) {
45154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			goto rollback;
45164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
45174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
45184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
45194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 1) {
45204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (exec->state->nbTrans > exec->transno + 1) {
45214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFARegExecSave(exec);
45224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
452354eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		/*
452454eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		 * restart count for expressions like this ((abc){2})*
452554eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		 */
452654eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		if (trans->count >= 0) {
452754eb0243c442292953b4a3df39568735039ebc82Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
452854eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		    printf("Reset count %d\n", trans->count);
452954eb0243c442292953b4a3df39568735039ebc82Daniel Veillard#endif
453054eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		    exec->counts[trans->count] = 0;
453154eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		}
45324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->counter >= 0) {
45334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
45344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Increasing count %d\n", trans->counter);
45354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
45364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->counts[trans->counter]++;
45374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
45384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
45394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("entering state %d\n", trans->to);
45404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
45414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->state = exec->comp->states[trans->to];
45424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->transno = 0;
45434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->atom != NULL) {
45444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->index += len;
45454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
45464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		goto progress;
45474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (ret < 0) {
45484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -4;
45494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
45504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
45514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
45524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((exec->transno != 0) || (exec->state->nbTrans == 0)) {
45534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardrollback:
45544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /*
45554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Failed to find a way out
45564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     */
45574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->determinist = 0;
45584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFARegExecRollBack(exec);
45594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
45604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardprogress:
45614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	continue;
45624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
45634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
45644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
45654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
45664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
4567ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack *	Parser for the Schemas Datatype Regular Expressions		*
45684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *	http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#regexs	*
45694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
45704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
45714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
45734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAIsChar:
4574441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
45754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
45764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [10]   Char   ::=   [^.\?*+()|#x5B#x5D]
45774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
45784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
45794255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAIsChar(xmlRegParserCtxtPtr ctxt) {
45804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int cur;
45814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int len;
45824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR_SCHAR(ctxt->cur, len);
45844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((cur == '.') || (cur == '\\') || (cur == '?') ||
45854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == '*') || (cur == '+') || (cur == '(') ||
45864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == ')') || (cur == '|') || (cur == 0x5B) ||
45874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == 0x5D) || (cur == 0))
45884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
45894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(cur);
45904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
45914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
45934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharProp:
4594441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
45954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
45964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [27]   charProp   ::=   IsCategory | IsBlock
45974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [28]   IsCategory ::= Letters | Marks | Numbers | Punctuation |
45984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *                       Separators | Symbols | Others
45994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [29]   Letters   ::=   'L' [ultmo]?
46004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [30]   Marks   ::=   'M' [nce]?
46014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [31]   Numbers   ::=   'N' [dlo]?
46024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [32]   Punctuation   ::=   'P' [cdseifo]?
46034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [33]   Separators   ::=   'Z' [slp]?
46044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [34]   Symbols   ::=   'S' [mcko]?
46054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [35]   Others   ::=   'C' [cfon]?
46064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [36]   IsBlock   ::=   'Is' [a-zA-Z0-9#x2D]+
46074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
46084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
46094255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
46104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int cur;
4611779af00750fa86045e94422287d67a2cf5723f65William M. Brack    xmlRegAtomType type = (xmlRegAtomType) 0;
46124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlChar *blockName = NULL;
46134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
46144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
46154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == 'L') {
46164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
46174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
46184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'u') {
46194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_UPPERCASE;
46214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'l') {
46224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_LOWERCASE;
46244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 't') {
46254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_TITLECASE;
46274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'm') {
46284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_MODIFIER;
46304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
46314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_OTHERS;
46334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
46344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER;
46354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
46364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'M') {
46374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
46384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
46394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'n') {
46404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* nonspacing */
46424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_MARK_NONSPACING;
46434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'c') {
46444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* spacing combining */
46464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_MARK_SPACECOMBINING;
46474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'e') {
46484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* enclosing */
46504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_MARK_ENCLOSING;
46514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
46524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all marks */
46534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_MARK;
46544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
46554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'N') {
46564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
46574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
46584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'd') {
46594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* digital */
46614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_NUMBER_DECIMAL;
46624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'l') {
46634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* letter */
46654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_NUMBER_LETTER;
46664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
46674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* other */
46694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_NUMBER_OTHERS;
46704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
46714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all numbers */
46724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_NUMBER;
46734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
46744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'P') {
46754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
46764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
46774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'c') {
46784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* connector */
46804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_CONNECTOR;
46814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'd') {
46824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* dash */
46844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_DASH;
46854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 's') {
46864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* open */
46884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_OPEN;
46894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'e') {
46904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* close */
46924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_CLOSE;
46934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'i') {
46944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* initial quote */
46964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_INITQUOTE;
46974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'f') {
46984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* final quote */
47004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_FINQUOTE;
47014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
47024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* other */
47044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_OTHERS;
47054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
47064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all punctuation */
47074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT;
47084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'Z') {
47104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 's') {
47134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* space */
47154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SEPAR_SPACE;
47164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'l') {
47174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* line */
47194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SEPAR_LINE;
47204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'p') {
47214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* paragraph */
47234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SEPAR_PARA;
47244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
47254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all separators */
47264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SEPAR;
47274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'S') {
47294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'm') {
47324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL_MATH;
47344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* math */
47354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'c') {
47364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL_CURRENCY;
47384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* currency */
47394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'k') {
47404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL_MODIFIER;
47424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* modifiers */
47434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
47444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL_OTHERS;
47464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* other */
47474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
47484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all symbols */
47494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL;
47504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'C') {
47524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'c') {
47554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* control */
47574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER_CONTROL;
47584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'f') {
47594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* format */
47614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER_FORMAT;
47624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
47634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* private use */
47654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER_PRIVATE;
47664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'n') {
47674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* not assigned */
47694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER_NA;
47704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
47714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all others */
47724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER;
47734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'I') {
47754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	const xmlChar *start;
47764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur != 's') {
47794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("IsXXXX expected");
47804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
47814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	start = ctxt->cur;
47844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (((cur >= 'a') && (cur <= 'z')) ||
47864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ((cur >= 'A') && (cur <= 'Z')) ||
47874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ((cur >= '0') && (cur <= '9')) ||
47884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    (cur == 0x2D)) {
47894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur = CUR;
47914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    while (((cur >= 'a') && (cur <= 'z')) ||
47924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		((cur >= 'A') && (cur <= 'Z')) ||
47934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		((cur >= '0') && (cur <= '9')) ||
47944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		(cur == 0x2D)) {
47954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		NEXT;
47964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		cur = CUR;
47974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
47984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	type = XML_REGEXP_BLOCK_NAME;
48004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	blockName = xmlStrndup(start, ctxt->cur - start);
48014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
48024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("Unknown char property");
48034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
48044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
48054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->atom == NULL) {
48064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = xmlRegNewAtom(ctxt, type);
48074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom != NULL)
48084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom->valuep = blockName;
48094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (ctxt->atom->type == XML_REGEXP_RANGES) {
48104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
48114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		           type, 0, 0, blockName);
48124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
48134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
48144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
48154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
48164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharClassEsc:
4817441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
48184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
48194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [23] charClassEsc ::= ( SingleCharEsc | MultiCharEsc | catEsc | complEsc )
48204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [24] SingleCharEsc ::= '\' [nrt\|.?*+(){}#x2D#x5B#x5D#x5E]
48214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [25] catEsc   ::=   '\p{' charProp '}'
48224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [26] complEsc ::=   '\P{' charProp '}'
48234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [37] MultiCharEsc ::= '.' | ('\' [sSiIcCdDwW])
48244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
48254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
48264255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) {
48274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int cur;
48284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
48294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR == '.') {
48304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL) {
48314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_ANYCHAR);
48324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
48334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
48344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			       XML_REGEXP_ANYCHAR, 0, 0, NULL);
48354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
48384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
48394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR != '\\') {
48404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("Escaped sequence: expecting \\");
48414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
48424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
48434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    NEXT;
48444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
48454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == 'p') {
48464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR != '{') {
48484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Expecting '{'");
48494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
48504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharProp(ctxt);
48534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR != '}') {
48544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Expecting '}'");
48554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
48564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'P') {
48594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR != '{') {
48614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Expecting '{'");
48624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
48634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharProp(ctxt);
48664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom->neg = 1;
48674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR != '}') {
48684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Expecting '}'");
48694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
48704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((cur == 'n') || (cur == 'r') || (cur == 't') || (cur == '\\') ||
48734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == '|') || (cur == '.') || (cur == '?') || (cur == '*') ||
48744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == '+') || (cur == '(') || (cur == ')') || (cur == '{') ||
48754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == '}') || (cur == 0x2D) || (cur == 0x5B) || (cur == 0x5D) ||
48764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == 0x5E)) {
48774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL) {
48784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL);
487999c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	    if (ctxt->atom != NULL) {
488099c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	        switch (cur) {
488199c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		    case 'n':
488299c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		        ctxt->atom->codepoint = '\n';
488399c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard			break;
488499c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		    case 'r':
488599c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		        ctxt->atom->codepoint = '\r';
488699c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard			break;
488799c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		    case 't':
488899c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		        ctxt->atom->codepoint = '\t';
488999c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard			break;
489099c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		    default:
489199c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard			ctxt->atom->codepoint = cur;
489299c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		}
489399c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	    }
48944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
48959543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard            switch (cur) {
48969543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                case 'n':
48979543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                    cur = '\n';
48989543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                    break;
48999543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                case 'r':
49009543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                    cur = '\r';
49019543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                    break;
49029543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                case 't':
49039543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                    cur = '\t';
49049543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard                    break;
49059543aee99b39f4de58641a66a5747cadd279d0b0Daniel Veillard            }
49064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
49074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			       XML_REGEXP_CHARVAL, cur, cur, NULL);
49084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
49094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
49104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((cur == 's') || (cur == 'S') || (cur == 'i') || (cur == 'I') ||
49114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == 'c') || (cur == 'C') || (cur == 'd') || (cur == 'D') ||
49124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == 'w') || (cur == 'W')) {
4913b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	xmlRegAtomType type = XML_REGEXP_ANYSPACE;
49144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
49154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	switch (cur) {
49164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 's':
49174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_ANYSPACE;
49184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'S':
49204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTSPACE;
49214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'i':
49234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_INITNAME;
49244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'I':
49264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTINITNAME;
49274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'c':
49294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NAMECHAR;
49304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'C':
49324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTNAMECHAR;
49334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'd':
49354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_DECIMAL;
49364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'D':
49384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTDECIMAL;
49394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'w':
49414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_REALCHAR;
49424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'W':
49444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTREALCHAR;
49454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
49474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
49484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL) {
49494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom = xmlRegNewAtom(ctxt, type);
49504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
49514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
49524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			       type, 0, 0, NULL);
49534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
4954cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard    } else {
4955cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard	ERROR("Wrong escape sequence, misuse of character '\\'");
49564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
49574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
49584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
49594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
49604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharRange:
4961441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
49624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
49634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [17]   charRange   ::=     seRange | XmlCharRef | XmlCharIncDash
49644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [18]   seRange   ::=   charOrEsc '-' charOrEsc
49654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [20]   charOrEsc   ::=   XmlChar | SingleCharEsc
49664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [21]   XmlChar   ::=   [^\#x2D#x5B#x5D]
49674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [22]   XmlCharIncDash   ::=   [^\#x5B#x5D]
49684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
49694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
49704255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) {
4971dc99df936c74b6ced82904086544fec365d1f219William M. Brack    int cur, len;
49724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int start = -1;
49734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int end = -1;
49744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
4975777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard    if (CUR == '\0') {
4976777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard        ERROR("Expecting ']'");
4977777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard	return;
4978777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard    }
4979777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard
49804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
49814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == '\\') {
49824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
49834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
49844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	switch (cur) {
49854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'n': start = 0xA; break;
49864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'r': start = 0xD; break;
49874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 't': start = 0x9; break;
49884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '\\': case '|': case '.': case '-': case '^': case '?':
49894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '*': case '+': case '{': case '}': case '(': case ')':
49904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '[': case ']':
49914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		start = cur; break;
49924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    default:
49934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ERROR("Invalid escape value");
49944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return;
49954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
49964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	end = start;
4997dc99df936c74b6ced82904086544fec365d1f219William M. Brack        len = 1;
49984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((cur != 0x5B) && (cur != 0x5D)) {
4999dc99df936c74b6ced82904086544fec365d1f219William M. Brack        end = start = CUR_SCHAR(ctxt->cur, len);
50004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
50014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("Expecting a char range");
50024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
50034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5004a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack    /*
5005a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack     * Since we are "inside" a range, we can assume ctxt->cur is past
5006a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack     * the start of ctxt->string, and PREV should be safe
5007a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack     */
5008a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack    if ((start == '-') && (NXT(1) != ']') && (PREV != '[') && (PREV != '^')) {
5009a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack	NEXTL(len);
50104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
50114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5012a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack    NEXTL(len);
50134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
501410f1ef4ce875d6affb467f33ab653cd8072e5888William M. Brack    if ((cur != '-') || (NXT(1) == ']')) {
50154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
50164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		              XML_REGEXP_CHARVAL, start, end, NULL);
50174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
50184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
50194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    NEXT;
50204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
50214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == '\\') {
50224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
50234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
50244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	switch (cur) {
50254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'n': end = 0xA; break;
50264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'r': end = 0xD; break;
50274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 't': end = 0x9; break;
50284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '\\': case '|': case '.': case '-': case '^': case '?':
50294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '*': case '+': case '{': case '}': case '(': case ')':
50304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '[': case ']':
50314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		end = cur; break;
50324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    default:
50334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ERROR("Invalid escape value");
50344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return;
50354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
5036dc99df936c74b6ced82904086544fec365d1f219William M. Brack        len = 1;
50374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((cur != 0x5B) && (cur != 0x5D)) {
5038dc99df936c74b6ced82904086544fec365d1f219William M. Brack        end = CUR_SCHAR(ctxt->cur, len);
50394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
50404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("Expecting the end of a char range");
50414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
50424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5043dc99df936c74b6ced82904086544fec365d1f219William M. Brack    NEXTL(len);
50444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* TODO check that the values are acceptable character ranges for XML */
50454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (end < start) {
50464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("End of range is before start of range");
50474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
50484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
50494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		           XML_REGEXP_CHARVAL, start, end, NULL);
50504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
50514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return;
50524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
50534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
50544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
50554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParsePosCharGroup:
5056441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
50574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
50584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [14]   posCharGroup ::= ( charRange | charClassEsc  )+
50594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
50604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
50614255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) {
50624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    do {
5063041b687e93cc4d5806b902ed3b445a47669dc2adDaniel Veillard	if (CUR == '\\') {
50644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParseCharClassEsc(ctxt);
50654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
50664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParseCharRange(ctxt);
50674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
50684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } while ((CUR != ']') && (CUR != '^') && (CUR != '-') &&
5069777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard             (CUR != 0) && (ctxt->error == 0));
50704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
50714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
50724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
50734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharGroup:
5074441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
50754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
50764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [13]   charGroup    ::= posCharGroup | negCharGroup | charClassSub
50774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [15]   negCharGroup ::= '^' posCharGroup
50784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [16]   charClassSub ::= ( posCharGroup | negCharGroup ) '-' charClassExpr
50794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [12]   charClassExpr ::= '[' charGroup ']'
50804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
50814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
50824255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharGroup(xmlRegParserCtxtPtr ctxt) {
50834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int n = ctxt->neg;
50844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((CUR != ']') && (ctxt->error == 0)) {
50854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == '^') {
50864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int neg = ctxt->neg;
50874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
50884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
50894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->neg = !ctxt->neg;
50904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParsePosCharGroup(ctxt);
50914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->neg = neg;
509210f1ef4ce875d6affb467f33ab653cd8072e5888William M. Brack	} else if ((CUR == '-') && (NXT(1) == '[')) {
5093f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard	    int neg = ctxt->neg;
5094f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard	    ctxt->neg = 2;
509510f1ef4ce875d6affb467f33ab653cd8072e5888William M. Brack	    NEXT;	/* eat the '-' */
509610f1ef4ce875d6affb467f33ab653cd8072e5888William M. Brack	    NEXT;	/* eat the '[' */
50974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParseCharGroup(ctxt);
50984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (CUR == ']') {
50994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		NEXT;
51004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else {
51014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ERROR("charClassExpr: ']' expected");
51024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
51034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
5104f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard	    ctxt->neg = neg;
51054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
51064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (CUR != ']') {
51074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParsePosCharGroup(ctxt);
51084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
51094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->neg = n;
51114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
51124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
51144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharClass:
5115441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
51164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
51174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [11]   charClass   ::=     charClassEsc | charClassExpr
51184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [12]   charClassExpr   ::=   '[' charGroup ']'
51194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
51204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
51214255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharClass(xmlRegParserCtxtPtr ctxt) {
51224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR == '[') {
51234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
51244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_RANGES);
51254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL)
51264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
51274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharGroup(ctxt);
51284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == ']') {
51294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
51304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
51314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("xmlFAParseCharClass: ']' expected");
51324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
51334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
51344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharClassEsc(ctxt);
51354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
51374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
51394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseQuantExact:
5140441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
51414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
51424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [8]   QuantExact   ::=   [0-9]+
5143a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard *
5144a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard * Returns 0 if success or -1 in case of error
51454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
51464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
51474255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
51484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret = 0;
51494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ok = 0;
51504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((CUR >= '0') && (CUR <= '9')) {
51524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ret = ret * 10 + (CUR - '0');
51534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ok = 1;
51544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
51554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ok != 1) {
51574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
51584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
51604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
51614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
51634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseQuantifier:
5164441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
51654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
51664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [4]   quantifier   ::=   [?*+] | ( '{' quantity '}' )
51674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [5]   quantity   ::=   quantRange | quantMin | QuantExact
51684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [6]   quantRange   ::=   QuantExact ',' QuantExact
51694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [7]   quantMin   ::=   QuantExact ','
51704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [8]   QuantExact   ::=   [0-9]+
51714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
51724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
51734255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseQuantifier(xmlRegParserCtxtPtr ctxt) {
51744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int cur;
51754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
51774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((cur == '?') || (cur == '*') || (cur == '+')) {
51784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom != NULL) {
51794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (cur == '?')
51804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ctxt->atom->quant = XML_REGEXP_QUANT_OPT;
51814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    else if (cur == '*')
51824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ctxt->atom->quant = XML_REGEXP_QUANT_MULT;
51834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    else if (cur == '+')
51844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ctxt->atom->quant = XML_REGEXP_QUANT_PLUS;
51854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
51864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
51874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
51884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == '{') {
51904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int min = 0, max = 0;
51914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
51934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = xmlFAParseQuantExact(ctxt);
51944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur >= 0)
51954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    min = cur;
51964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == ',') {
51974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
5198ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	    if (CUR == '}')
5199ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	        max = INT_MAX;
5200ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	    else {
5201ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	        cur = xmlFAParseQuantExact(ctxt);
5202ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	        if (cur >= 0)
5203ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard		    max = cur;
5204ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard		else {
5205ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard		    ERROR("Improper quantifier");
5206ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard		}
5207ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	    }
52084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
52094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == '}') {
52104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
52114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
52124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Unterminated quantifier");
52134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
52144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (max == 0)
52154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    max = min;
52164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom != NULL) {
52174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom->quant = XML_REGEXP_QUANT_RANGE;
52184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom->min = min;
52194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom->max = max;
52204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
52214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
52224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
52234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
52244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
52254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
52274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseAtom:
5228441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
52294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
52304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [9]   atom   ::=   Char | charClass | ( '(' regExp ')' )
52314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
52324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
52334255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseAtom(xmlRegParserCtxtPtr ctxt) {
52344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int codepoint, len;
52354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    codepoint = xmlFAIsChar(ctxt);
52374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (codepoint > 0) {
52384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL);
52394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL)
52404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
52414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	codepoint = CUR_SCHAR(ctxt->cur, len);
52424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom->codepoint = codepoint;
52434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXTL(len);
52444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
52454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (CUR == '|') {
52464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
52474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (CUR == 0) {
52484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
52494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (CUR == ')') {
52504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
52514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (CUR == '(') {
525276d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	xmlRegStatePtr start, oldend, start0;
52534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
525576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	/*
525676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	 * this extra Epsilon transition is needed if we count with 0 allowed
525776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	 * unfortunately this can't be known at that point
525876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	 */
525976d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	xmlFAGenerateEpsilonTransition(ctxt, ctxt->state, NULL);
526076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	start0 = ctxt->state;
52614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAGenerateEpsilonTransition(ctxt, ctxt->state, NULL);
52624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	start = ctxt->state;
52634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	oldend = ctxt->end;
52644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->end = NULL;
52654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = NULL;
52664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseRegExp(ctxt, 0);
52674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == ')') {
52684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
52694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
52704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("xmlFAParseAtom: expecting ')'");
52714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
52724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_SUBREG);
52734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL)
52744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
52754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom->start = start;
527676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	ctxt->atom->start0 = start0;
52774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom->stop = ctxt->state;
52784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->end = oldend;
52794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
52804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((CUR == '[') || (CUR == '\\') || (CUR == '.')) {
52814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharClass(ctxt);
52824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
52834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
52844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
52854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
52864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
52884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParsePiece:
5289441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
52904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
52914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [3]   piece   ::=   atom quantifier?
52924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
52934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
52944255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParsePiece(xmlRegParserCtxtPtr ctxt) {
52954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
52964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->atom = NULL;
52984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlFAParseAtom(ctxt);
52994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret == 0)
53004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
53014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->atom == NULL) {
53024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("internal: no atom generated");
53034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
53044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAParseQuantifier(ctxt);
53054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(1);
53064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
53074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
53094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseBranch:
5310441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
531154eb0243c442292953b4a3df39568735039ebc82Daniel Veillard * @to: optional target to the end of the branch
531254eb0243c442292953b4a3df39568735039ebc82Daniel Veillard *
531354eb0243c442292953b4a3df39568735039ebc82Daniel Veillard * @to is used to optimize by removing duplicate path in automata
531454eb0243c442292953b4a3df39568735039ebc82Daniel Veillard * in expressions like (a|b)(c|d)
53154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
53164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [2]   branch   ::=   piece*
53174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
5318a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillardstatic int
531954eb0243c442292953b4a3df39568735039ebc82Daniel VeillardxmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) {
53204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr previous;
53214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
53224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    previous = ctxt->state;
53244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlFAParsePiece(ctxt);
53254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret != 0) {
532654eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	if (xmlFAGenerateTransitions(ctxt, previous,
532754eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	        (CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0)
53282cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	    return(-1);
53292cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	previous = ctxt->state;
53304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = NULL;
53314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
53324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((ret != 0) && (ctxt->error == 0)) {
53334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ret = xmlFAParsePiece(ctxt);
53344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ret != 0) {
533554eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	    if (xmlFAGenerateTransitions(ctxt, previous,
533654eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	            (CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0)
5337a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard		    return(-1);
53384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    previous = ctxt->state;
53394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom = NULL;
53404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
53414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5342a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    return(0);
53434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
53444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
53464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseRegExp:
5347441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
5348ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * @top:  is this the top-level expression ?
53494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
53504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [1]   regExp   ::=     branch  ( '|' branch )*
53514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
53524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
53534255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
5354c7e3cc49bade82dba0cda4ae7c07ffcd1e32fe25Daniel Veillard    xmlRegStatePtr start, end;
53554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53562cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    /* if not top start should have been generated by an epsilon trans */
53574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    start = ctxt->state;
53582cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    ctxt->end = NULL;
535954eb0243c442292953b4a3df39568735039ebc82Daniel Veillard    xmlFAParseBranch(ctxt, NULL);
53602cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    if (top) {
53612cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
53622cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	printf("State %d is final\n", ctxt->state->no);
53632cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard#endif
53642cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	ctxt->state->type = XML_REGEXP_FINAL_STATE;
53652cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    }
53664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR != '|') {
53674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->end = ctxt->state;
53684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
53694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
53704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    end = ctxt->state;
53714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((CUR == '|') && (ctxt->error == 0)) {
53724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
53734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->state = start;
53742cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	ctxt->end = NULL;
537554eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	xmlFAParseBranch(ctxt, end);
53762cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    }
53772cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    if (!top) {
53782cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	ctxt->state = end;
53794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->end = end;
53804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
53814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
53824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
53844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
53854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 			The basic API					*
53864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
53874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
53884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
53904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegexpPrint:
53914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @output: the file for the output debug
53924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @regexp: the compiled regexp
53934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
53944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Print the content of the compiled regular expression
53954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
53964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
53974255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpPrint(FILE *output, xmlRegexpPtr regexp) {
53984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
53994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
5400a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (output == NULL)
5401a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard        return;
54024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, " regexp: ");
54034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp == NULL) {
54044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "NULL\n");
54054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
54064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "'%s' ", regexp->string);
54084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "\n");
54094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d atoms:\n", regexp->nbAtoms);
54104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < regexp->nbAtoms; i++) {
54114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, " %02d ", i);
54124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegPrintAtom(output, regexp->atoms[i]);
54134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d states:", regexp->nbStates);
54154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "\n");
54164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < regexp->nbStates; i++) {
54174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegPrintState(output, regexp->states[i]);
54184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d counters:\n", regexp->nbCounters);
54204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < regexp->nbCounters; i++) {
54214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, " %d: min %d max %d\n", i, regexp->counters[i].min,
54224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                                regexp->counters[i].max);
54234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
54254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
54274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegexpCompile:
54284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @regexp:  a regular expression string
54294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
54304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Parses a regular expression conforming to XML Schemas Part 2 Datatype
5431ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Appendix F and builds an automata suitable for testing strings against
54324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * that regular expression
54334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
54344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the compiled expression or NULL in case of error
54354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
54364255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpPtr
54374255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpCompile(const xmlChar *regexp) {
54384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegexpPtr ret;
54394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegParserCtxtPtr ctxt;
54404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt = xmlRegNewParserCtxt(regexp);
54424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt == NULL)
54434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
54444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* initialize the parser */
54464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->end = NULL;
54474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->start = ctxt->state = xmlRegNewState(ctxt);
54484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePush(ctxt, ctxt->start);
54494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* parse the expression building an automata */
54514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAParseRegExp(ctxt, 1);
54524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR != 0) {
54534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("xmlFAParseRegExp: extra characters");
54544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5455cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard    if (ctxt->error != 0) {
5456cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard	xmlRegFreeParserCtxt(ctxt);
5457cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard	return(NULL);
5458cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard    }
54594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->end = ctxt->state;
54604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->start->type = XML_REGEXP_START_STATE;
54614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->end->type = XML_REGEXP_FINAL_STATE;
54624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* remove the Epsilon except for counted transitions */
54644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAEliminateEpsilonTransitions(ctxt);
54654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->error != 0) {
54684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegFreeParserCtxt(ctxt);
54694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
54704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlRegEpxFromParse(ctxt);
54724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegFreeParserCtxt(ctxt);
54734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
54744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
54754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
54774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegexpExec:
54784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @comp:  the compiled regular expression
54794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @content:  the value to check against the regular expression
54804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5481ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Check if the regular expression generates the value
54824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5483ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Returns 1 if it matches, 0 if not and a negative value in case of error
54844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
54854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardint
54864255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpExec(xmlRegexpPtr comp, const xmlChar *content) {
54874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((comp == NULL) || (content == NULL))
54884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
54894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(xmlFARegExec(comp, content));
54904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
54914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
549323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * xmlRegexpIsDeterminist:
549423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @comp:  the compiled regular expression
549523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *
549623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * Check if the regular expression is determinist
549723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *
5498ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Returns 1 if it yes, 0 if not and a negative value in case of error
549923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard */
550023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillardint
550123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel VeillardxmlRegexpIsDeterminist(xmlRegexpPtr comp) {
550223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    xmlAutomataPtr am;
550323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int ret;
550423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
550523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (comp == NULL)
550623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(-1);
550723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (comp->determinist != -1)
550823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(comp->determinist);
550923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
551023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am = xmlNewAutomata();
5511bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard    if (am->states != NULL) {
5512bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard	int i;
5513bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard
5514bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard	for (i = 0;i < am->nbStates;i++)
5515bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard	    xmlRegFreeState(am->states[i]);
5516bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard	xmlFree(am->states);
5517bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard    }
551823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->nbAtoms = comp->nbAtoms;
551923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->atoms = comp->atoms;
552023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->nbStates = comp->nbStates;
552123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->states = comp->states;
552223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->determinist = -1;
55231ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    am->flags = comp->flags;
552423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    ret = xmlFAComputesDeterminism(am);
552523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->atoms = NULL;
552623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->states = NULL;
552723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    xmlFreeAutomata(am);
55281ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    comp->determinist = ret;
552923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    return(ret);
553023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard}
553123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
553223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard/**
55334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegFreeRegexp:
55344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @regexp:  the regexp
55354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
55364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free a regexp
55374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
55384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
55394255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegFreeRegexp(xmlRegexpPtr regexp) {
55404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
55414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp == NULL)
55424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
55434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp->string != NULL)
55454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(regexp->string);
55464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp->states != NULL) {
55474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0;i < regexp->nbStates;i++)
55484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegFreeState(regexp->states[i]);
55494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(regexp->states);
55504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
55514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp->atoms != NULL) {
55524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0;i < regexp->nbAtoms;i++)
55534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegFreeAtom(regexp->atoms[i]);
55544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(regexp->atoms);
55554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
55564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp->counters != NULL)
55574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(regexp->counters);
555823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (regexp->compact != NULL)
555923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	xmlFree(regexp->compact);
5560118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    if (regexp->transdata != NULL)
5561118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	xmlFree(regexp->transdata);
556223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (regexp->stringMap != NULL) {
556323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	for (i = 0; i < regexp->nbstrings;i++)
556423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    xmlFree(regexp->stringMap[i]);
556523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	xmlFree(regexp->stringMap);
556623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
556723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
55684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(regexp);
55694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
55704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef LIBXML_AUTOMATA_ENABLED
55724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
55734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
55744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 			The Automata interface				*
55754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
55764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
55774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
55794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlNewAutomata:
55804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
55814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Create a new automata
55824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
55834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the new object or NULL in case of failure
55844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
55854255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataPtr
55864255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlNewAutomata(void) {
55874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlAutomataPtr ctxt;
55884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt = xmlRegNewParserCtxt(NULL);
55904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt == NULL)
55914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
55924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* initialize the parser */
55944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->end = NULL;
55954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->start = ctxt->state = xmlRegNewState(ctxt);
5596a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (ctxt->start == NULL) {
5597a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	xmlFreeAutomata(ctxt);
5598a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(NULL);
5599a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
5600d0271473abc7ca82a22e9a953ec525a6f4b504d5Daniel Veillard    ctxt->start->type = XML_REGEXP_START_STATE;
5601a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (xmlRegStatePush(ctxt, ctxt->start) < 0) {
5602a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        xmlRegFreeState(ctxt->start);
5603a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	xmlFreeAutomata(ctxt);
5604a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(NULL);
5605a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
56061ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    ctxt->flags = 0;
56074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ctxt);
56094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
56104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
56124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFreeAutomata:
56134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
56144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
56154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free an automata
56164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
56174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
56184255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFreeAutomata(xmlAutomataPtr am) {
56194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (am == NULL)
56204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
56214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegFreeParserCtxt(am);
56224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
56234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
5625293416828e1467f877d9dd928f174dcf81b103bcDaniel Veillard * xmlAutomataSetFlags:
56261ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * @am: an automata
56271ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * @flags:  a set of internal flags
56281ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard *
56291ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * Set some flags on the automata
56301ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard */
56311ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillardvoid
56321ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel VeillardxmlAutomataSetFlags(xmlAutomataPtr am, int flags) {
56331ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    if (am == NULL)
56341ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard	return;
56351ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    am->flags |= flags;
56361ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard}
56371ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
56381ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard/**
56394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataGetInitState:
56404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
56414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5642a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * Initial state lookup
5643a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard *
56444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the initial state of the automata
56454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
56464255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
56474255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataGetInitState(xmlAutomataPtr am) {
56484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (am == NULL)
56494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
56504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(am->start);
56514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
56524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
56544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataSetFinalState:
56554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
56564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @state: a state in this automata
56574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
56584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Makes that state a final state
56594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
56604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns 0 or -1 in case of error
56614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
56624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardint
56634255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataSetFinalState(xmlAutomataPtr am, xmlAutomataStatePtr state) {
56644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((am == NULL) || (state == NULL))
56654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
56664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    state->type = XML_REGEXP_FINAL_STATE;
56674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
56684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
56694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
56714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataNewTransition:
56724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
56734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @from: the starting point of the transition
56744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @to: the target point of the transition or NULL
56754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @token: the input string associated to that transition
56764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @data: data passed to the callback function if the transition is activated
56774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5678ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
56794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * and then adds a transition from the @from state to the target state
56804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * activated by the value of @token
56814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
56824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the target state or NULL in case of error
56834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
56844255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
56854255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataNewTransition(xmlAutomataPtr am, xmlAutomataStatePtr from,
56864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 xmlAutomataStatePtr to, const xmlChar *token,
56874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 void *data) {
56884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
56894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
56914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
56924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5693a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (atom == NULL)
5694a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        return(NULL);
56954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->data = data;
56964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL)
56974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
56984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->valuep = xmlStrdup(token);
56994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
5700a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
5701a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        xmlRegFreeAtom(atom);
5702a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(NULL);
5703a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
57044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
570552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(am->state);
570652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    return(to);
570752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard}
570852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
570952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard/**
571052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * xmlAutomataNewTransition2:
571152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @am: an automata
571252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @from: the starting point of the transition
571352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @to: the target point of the transition or NULL
571452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @token: the first input string associated to that transition
571552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @token2: the second input string associated to that transition
571652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @data: data passed to the callback function if the transition is activated
571752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *
5718ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
571952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * and then adds a transition from the @from state to the target state
572052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * activated by the value of @token
572152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *
572252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * Returns the target state or NULL in case of error
572352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard */
572452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel VeillardxmlAutomataStatePtr
572552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel VeillardxmlAutomataNewTransition2(xmlAutomataPtr am, xmlAutomataStatePtr from,
572652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard			  xmlAutomataStatePtr to, const xmlChar *token,
572752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard			  const xmlChar *token2, void *data) {
572852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    xmlRegAtomPtr atom;
572952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
573052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
573152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(NULL);
573252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
573352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (atom == NULL)
573452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(NULL);
573511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    atom->data = data;
573652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if ((token2 == NULL) || (*token2 == 0)) {
573752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	atom->valuep = xmlStrdup(token);
573852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    } else {
573952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	int lenn, lenp;
574052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	xmlChar *str;
574152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
574252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	lenn = strlen((char *) token2);
574352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	lenp = strlen((char *) token);
574452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
57453c908dca479ed50dca24b8593bca90e40dbde6b8Daniel Veillard	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
574652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	if (str == NULL) {
574752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	    xmlRegFreeAtom(atom);
574852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	    return(NULL);
574952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	}
575052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	memcpy(&str[0], token, lenp);
575152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	str[lenp] = '|';
575252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	memcpy(&str[lenp + 1], token2, lenn);
575352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	str[lenn + lenp + 1] = 0;
575452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
575552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	atom->valuep = str;
575652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    }
575752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
5758a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
5759a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        xmlRegFreeAtom(atom);
5760a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(NULL);
5761a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
576252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (to == NULL)
57634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(am->state);
57649efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    return(to);
57659efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard}
57669efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
57679efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard/**
57689efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * xmlAutomataNewNegTrans:
57699efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @am: an automata
57709efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @from: the starting point of the transition
57719efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @to: the target point of the transition or NULL
57729efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @token: the first input string associated to that transition
57739efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @token2: the second input string associated to that transition
57749efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @data: data passed to the callback function if the transition is activated
57759efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard *
57769efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * If @to is NULL, this creates first a new target state in the automata
57779efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * and then adds a transition from the @from state to the target state
57789efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * activated by any value except (@token,@token2)
57796e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * Note that if @token2 is not NULL, then (X, NULL) won't match to follow
57806e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard # the semantic of XSD ##other
57819efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard *
57829efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * Returns the target state or NULL in case of error
57839efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard */
57849efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel VeillardxmlAutomataStatePtr
57859efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel VeillardxmlAutomataNewNegTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
57869efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard		       xmlAutomataStatePtr to, const xmlChar *token,
57879efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard		       const xmlChar *token2, void *data) {
57889efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    xmlRegAtomPtr atom;
578977005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard    xmlChar err_msg[200];
57909efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
57919efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
57929efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	return(NULL);
57939efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
57949efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if (atom == NULL)
57959efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	return(NULL);
57969efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    atom->data = data;
57979efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    atom->neg = 1;
57989efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if ((token2 == NULL) || (*token2 == 0)) {
57999efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	atom->valuep = xmlStrdup(token);
58009efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    } else {
58019efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	int lenn, lenp;
58029efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	xmlChar *str;
58039efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
58049efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	lenn = strlen((char *) token2);
58059efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	lenp = strlen((char *) token);
58069efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
58079efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
58089efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	if (str == NULL) {
58099efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	    xmlRegFreeAtom(atom);
58109efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	    return(NULL);
58119efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	}
58129efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	memcpy(&str[0], token, lenp);
58139efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	str[lenp] = '|';
58149efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	memcpy(&str[lenp + 1], token2, lenn);
58159efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	str[lenn + lenp + 1] = 0;
58169efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
58179efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	atom->valuep = str;
58189efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    }
5819db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    snprintf((char *) err_msg, 199, "not %s", (const char *) atom->valuep);
582077005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard    err_msg[199] = 0;
582177005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard    atom->valuep2 = xmlStrdup(err_msg);
58229efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
58239efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
58249efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard        xmlRegFreeAtom(atom);
58259efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	return(NULL);
58269efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    }
58276e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    am->negs++;
58289efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if (to == NULL)
58299efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	return(am->state);
58304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(to);
58314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
58324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
58334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
583487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * xmlAutomataNewCountTrans2:
583587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @am: an automata
583687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @from: the starting point of the transition
583787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @to: the target point of the transition or NULL
583887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @token: the input string associated to that transition
583987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @token2: the second input string associated to that transition
584087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @min:  the minimum successive occurences of token
584187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @max:  the maximum successive occurences of token
584287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @data:  data associated to the transition
584387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik *
584487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * If @to is NULL, this creates first a new target state in the automata
584587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * and then adds a transition from the @from state to the target state
584687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * activated by a succession of input of value @token and @token2 and
584787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * whose number is between @min and @max
584887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik *
584987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * Returns the target state or NULL in case of error
585087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik */
585187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. BuchcikxmlAutomataStatePtr
585287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. BuchcikxmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
585387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 xmlAutomataStatePtr to, const xmlChar *token,
585487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 const xmlChar *token2,
585587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 int min, int max, void *data) {
585687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    xmlRegAtomPtr atom;
585787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    int counter;
585887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
585987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((am == NULL) || (from == NULL) || (token == NULL))
586087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
586187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (min < 0)
586287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
586387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((max < min) || (max < 1))
586487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
586587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
586687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (atom == NULL)
586787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
586887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((token2 == NULL) || (*token2 == 0)) {
586987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->valuep = xmlStrdup(token);
587087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    } else {
587187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	int lenn, lenp;
587287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlChar *str;
587387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
587487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	lenn = strlen((char *) token2);
587587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	lenp = strlen((char *) token);
587687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
587787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
587887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	if (str == NULL) {
587987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	    xmlRegFreeAtom(atom);
588087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	    return(NULL);
588187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	}
588287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	memcpy(&str[0], token, lenp);
588387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str[lenp] = '|';
588487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	memcpy(&str[lenp + 1], token2, lenn);
588587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str[lenn + lenp + 1] = 0;
588687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
588787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->valuep = str;
588887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    }
588987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->data = data;
589087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (min == 0)
589187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->min = 1;
589287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    else
589387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->min = min;
589487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->max = max;
589587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
589687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    /*
589787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik     * associate a counter to the transition.
589887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik     */
589987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    counter = xmlRegGetCounter(am);
590087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->counters[counter].min = min;
590187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->counters[counter].max = max;
590287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
590387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    /* xmlFAGenerateTransitions(am, from, to, atom); */
590487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (to == NULL) {
590587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik        to = xmlRegNewState(am);
590687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlRegStatePush(am, to);
590787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    }
59085de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(am, from, atom, to, counter, -1);
590987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    xmlRegAtomPush(am, atom);
591087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->state = to;
591187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
591287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (to == NULL)
591387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	to = am->state;
591487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (to == NULL)
591587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
591687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (min == 0)
591787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlFAGenerateEpsilonTransition(am, from, to);
591887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    return(to);
591987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik}
592087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
592187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik/**
59224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataNewCountTrans:
59234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
59244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @from: the starting point of the transition
59254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @to: the target point of the transition or NULL
59264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @token: the input string associated to that transition
59274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @min:  the minimum successive occurences of token
5928a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @max:  the maximum successive occurences of token
5929a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @data:  data associated to the transition
59304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5931ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
59324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * and then adds a transition from the @from state to the target state
59334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * activated by a succession of input of value @token and whose number
59344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * is between @min and @max
59354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
59364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the target state or NULL in case of error
59374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
59384255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
59394255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
59404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 xmlAutomataStatePtr to, const xmlChar *token,
59414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 int min, int max, void *data) {
59424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
59430ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    int counter;
59444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
59454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
59464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (min < 0)
59484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((max < min) || (max < 1))
59504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
59524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL)
59534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->valuep = xmlStrdup(token);
59554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->data = data;
59564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (min == 0)
59574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	atom->min = 1;
59584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else
59594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	atom->min = min;
59604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->max = max;
59614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
59620ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    /*
59630ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard     * associate a counter to the transition.
59640ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard     */
59650ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    counter = xmlRegGetCounter(am);
59660ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    am->counters[counter].min = min;
59670ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    am->counters[counter].max = max;
59680ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard
59690ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    /* xmlFAGenerateTransitions(am, from, to, atom); */
59700ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    if (to == NULL) {
59710ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard        to = xmlRegNewState(am);
59720ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard	xmlRegStatePush(am, to);
5973a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
59745de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(am, from, atom, to, counter, -1);
59750ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    xmlRegAtomPush(am, atom);
59760ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    am->state = to;
59770ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard
59784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
59794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	to = am->state;
59804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
59814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (min == 0)
59834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAGenerateEpsilonTransition(am, from, to);
59844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(to);
59854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
59864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
59874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
598887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * xmlAutomataNewOnceTrans2:
598987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @am: an automata
599087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @from: the starting point of the transition
599187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @to: the target point of the transition or NULL
599287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @token: the input string associated to that transition
599387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @token2: the second input string associated to that transition
599487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @min:  the minimum successive occurences of token
599587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @max:  the maximum successive occurences of token
599687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @data:  data associated to the transition
599787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik *
599887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * If @to is NULL, this creates first a new target state in the automata
599987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * and then adds a transition from the @from state to the target state
600087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * activated by a succession of input of value @token and @token2 and whose
600187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * number is between @min and @max, moreover that transition can only be
600287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * crossed once.
600387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik *
600487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * Returns the target state or NULL in case of error
600587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik */
600687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. BuchcikxmlAutomataStatePtr
600787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. BuchcikxmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
600887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 xmlAutomataStatePtr to, const xmlChar *token,
600987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 const xmlChar *token2,
601087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 int min, int max, void *data) {
601187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    xmlRegAtomPtr atom;
601287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    int counter;
601387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
601487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((am == NULL) || (from == NULL) || (token == NULL))
601587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
601687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (min < 1)
601787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
601887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((max < min) || (max < 1))
601987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
602087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
602187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (atom == NULL)
602287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
602387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((token2 == NULL) || (*token2 == 0)) {
602487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->valuep = xmlStrdup(token);
602587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    } else {
602687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	int lenn, lenp;
602787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlChar *str;
602887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
602987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	lenn = strlen((char *) token2);
603087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	lenp = strlen((char *) token);
603187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
603287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
603387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	if (str == NULL) {
603487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	    xmlRegFreeAtom(atom);
603587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	    return(NULL);
603687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	}
603787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	memcpy(&str[0], token, lenp);
603887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str[lenp] = '|';
603987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	memcpy(&str[lenp + 1], token2, lenn);
604087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str[lenn + lenp + 1] = 0;
604187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
604287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->valuep = str;
604387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    }
604487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->data = data;
604587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->quant = XML_REGEXP_QUANT_ONCEONLY;
604611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    atom->min = min;
604787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->max = max;
604887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    /*
604987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik     * associate a counter to the transition.
605087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik     */
605187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    counter = xmlRegGetCounter(am);
605287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->counters[counter].min = 1;
605387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->counters[counter].max = 1;
605487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
605587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    /* xmlFAGenerateTransitions(am, from, to, atom); */
605687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (to == NULL) {
605787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	to = xmlRegNewState(am);
605887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlRegStatePush(am, to);
605987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    }
60605de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(am, from, atom, to, counter, -1);
606187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    xmlRegAtomPush(am, atom);
606287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->state = to;
606387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    return(to);
606487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik}
606587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
606687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
606787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
606887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik/**
60697646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * xmlAutomataNewOnceTrans:
60707646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @am: an automata
60717646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @from: the starting point of the transition
60727646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @to: the target point of the transition or NULL
60737646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @token: the input string associated to that transition
60747646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @min:  the minimum successive occurences of token
6075a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @max:  the maximum successive occurences of token
6076a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @data:  data associated to the transition
60777646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
6078ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
60797646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * and then adds a transition from the @from state to the target state
60807646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * activated by a succession of input of value @token and whose number
6081ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * is between @min and @max, moreover that transition can only be crossed
60827646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * once.
60837646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
60847646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * Returns the target state or NULL in case of error
60857646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard */
60867646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlAutomataStatePtr
60877646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
60887646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard			 xmlAutomataStatePtr to, const xmlChar *token,
60897646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard			 int min, int max, void *data) {
60907646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    xmlRegAtomPtr atom;
60917646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    int counter;
60927646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
60937646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
60947646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
60957646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (min < 1)
60967646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
60977646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if ((max < min) || (max < 1))
60987646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
60997646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
61007646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (atom == NULL)
61017646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
61027646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom->valuep = xmlStrdup(token);
61037646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom->data = data;
61047646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom->quant = XML_REGEXP_QUANT_ONCEONLY;
610511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    atom->min = min;
61067646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom->max = max;
61077646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    /*
61087646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard     * associate a counter to the transition.
61097646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard     */
61107646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    counter = xmlRegGetCounter(am);
61117646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    am->counters[counter].min = 1;
61127646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    am->counters[counter].max = 1;
61137646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
61147646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    /* xmlFAGenerateTransitions(am, from, to, atom); */
61157646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (to == NULL) {
61167646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	to = xmlRegNewState(am);
61177646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	xmlRegStatePush(am, to);
61187646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    }
61195de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(am, from, atom, to, counter, -1);
61207646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    xmlRegAtomPush(am, atom);
61217646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    am->state = to;
61227646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    return(to);
61237646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard}
61247646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
61257646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard/**
61264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataNewState:
61274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
61284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
61294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Create a new disconnected state in the automata
61304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
61314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the new state or NULL in case of error
61324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
61334255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
61344255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataNewState(xmlAutomataPtr am) {
61354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlAutomataStatePtr to;
61364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
61374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (am == NULL)
61384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
61394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    to = xmlRegNewState(am);
61404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePush(am, to);
61414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(to);
61424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
61434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
61444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
6145a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * xmlAutomataNewEpsilon:
61464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
61474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @from: the starting point of the transition
61484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @to: the target point of the transition or NULL
61494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
6150ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
6151ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * and then adds an epsilon transition from the @from state to the
61524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * target state
61534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
61544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the target state or NULL in case of error
61554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
61564255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
61574255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataNewEpsilon(xmlAutomataPtr am, xmlAutomataStatePtr from,
61584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		      xmlAutomataStatePtr to) {
61594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((am == NULL) || (from == NULL))
61604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
61614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAGenerateEpsilonTransition(am, from, to);
61624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
61634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(am->state);
61644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(to);
61654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
61664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
6167b509f1543df71549969eeac076349e05d2f78044Daniel Veillard/**
61687646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * xmlAutomataNewAllTrans:
61697646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @am: an automata
61707646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @from: the starting point of the transition
61717646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @to: the target point of the transition or NULL
6172a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @lax: allow to transition if not all all transitions have been activated
61737646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
6174ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
61757646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * and then adds a an ALL transition from the @from state to the
61767646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * target state. That transition is an epsilon transition allowed only when
61777646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * all transitions from the @from node have been activated.
61787646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
61797646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * Returns the target state or NULL in case of error
61807646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard */
61817646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlAutomataStatePtr
61827646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlAutomataNewAllTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6183441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		       xmlAutomataStatePtr to, int lax) {
61847646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if ((am == NULL) || (from == NULL))
61857646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
6186441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard    xmlFAGenerateAllTransition(am, from, to, lax);
61877646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (to == NULL)
61887646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(am->state);
61897646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    return(to);
61907646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard}
61917646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
61927646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard/**
6193b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * xmlAutomataNewCounter:
6194b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @am: an automata
6195b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @min:  the minimal value on the counter
6196b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @max:  the maximal value on the counter
6197b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6198b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * Create a new counter
6199b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6200b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * Returns the counter number or -1 in case of error
6201b509f1543df71549969eeac076349e05d2f78044Daniel Veillard */
6202b509f1543df71549969eeac076349e05d2f78044Daniel Veillardint
6203b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataNewCounter(xmlAutomataPtr am, int min, int max) {
6204b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    int ret;
6205b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
6206b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if (am == NULL)
6207b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(-1);
6208b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
6209b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    ret = xmlRegGetCounter(am);
6210b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if (ret < 0)
6211b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(-1);
6212b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    am->counters[ret].min = min;
6213b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    am->counters[ret].max = max;
6214b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    return(ret);
6215b509f1543df71549969eeac076349e05d2f78044Daniel Veillard}
6216b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
6217b509f1543df71549969eeac076349e05d2f78044Daniel Veillard/**
6218b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * xmlAutomataNewCountedTrans:
6219b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @am: an automata
6220b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @from: the starting point of the transition
6221b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @to: the target point of the transition or NULL
6222b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @counter: the counter associated to that transition
6223b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6224ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
6225b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * and then adds an epsilon transition from the @from state to the target state
6226b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * which will increment the counter provided
6227b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6228b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * Returns the target state or NULL in case of error
6229b509f1543df71549969eeac076349e05d2f78044Daniel Veillard */
6230b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataStatePtr
6231b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataNewCountedTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6232b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		xmlAutomataStatePtr to, int counter) {
6233b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if ((am == NULL) || (from == NULL) || (counter < 0))
6234b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(NULL);
6235b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    xmlFAGenerateCountedEpsilonTransition(am, from, to, counter);
6236b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if (to == NULL)
6237b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(am->state);
6238b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    return(to);
6239b509f1543df71549969eeac076349e05d2f78044Daniel Veillard}
6240b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
6241b509f1543df71549969eeac076349e05d2f78044Daniel Veillard/**
6242b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * xmlAutomataNewCounterTrans:
6243b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @am: an automata
6244b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @from: the starting point of the transition
6245b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @to: the target point of the transition or NULL
6246b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @counter: the counter associated to that transition
6247b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6248ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
6249b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * and then adds an epsilon transition from the @from state to the target state
6250b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * which will be allowed only if the counter is within the right range.
6251b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6252b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * Returns the target state or NULL in case of error
6253b509f1543df71549969eeac076349e05d2f78044Daniel Veillard */
6254b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataStatePtr
6255b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataNewCounterTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6256b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		xmlAutomataStatePtr to, int counter) {
6257b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if ((am == NULL) || (from == NULL) || (counter < 0))
6258b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(NULL);
6259b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    xmlFAGenerateCountedTransition(am, from, to, counter);
6260b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if (to == NULL)
6261b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(am->state);
6262b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    return(to);
6263b509f1543df71549969eeac076349e05d2f78044Daniel Veillard}
62644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
62654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
62664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataCompile:
62674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
62684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
62694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Compile the automata into a Reg Exp ready for being executed.
62704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * The automata should be free after this point.
62714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
62724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the compiled regexp or NULL in case of error
62734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
62744255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpPtr
62754255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataCompile(xmlAutomataPtr am) {
62764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegexpPtr ret;
62774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
6278a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if ((am == NULL) || (am->error != 0)) return(NULL);
62794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAEliminateEpsilonTransitions(am);
628023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    /* xmlFAComputesDeterminism(am); */
62814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlRegEpxFromParse(am);
62824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
62834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
62844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
6285e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
6286e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
6287e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * xmlAutomataIsDeterminist:
6288e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @am: an automata
6289e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
6290e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Checks if an automata is determinist.
6291e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
6292e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Returns 1 if true, 0 if not, and -1 in case of error
6293e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
6294e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardint
6295e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel VeillardxmlAutomataIsDeterminist(xmlAutomataPtr am) {
6296e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int ret;
6297e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
6298e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if (am == NULL)
6299e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(-1);
6300e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
6301e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    ret = xmlFAComputesDeterminism(am);
6302e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    return(ret);
6303e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard}
63044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif /* LIBXML_AUTOMATA_ENABLED */
630581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
630681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
630781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
630881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
630981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *		Formal Expression handling code				*
631081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
631181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
631281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
631381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
631481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *		Expression handling context				*
631581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
631681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
631781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
631881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstruct _xmlExpCtxt {
631981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlDictPtr dict;
632081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr *table;
632181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int size;
632281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int nbElems;
632381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int nb_nodes;
6324594e5dfb48ee6fbac1b64155839063648022fc57Daniel Veillard    int maxNodes;
632581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    const char *expr;
632681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    const char *cur;
632781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int nb_cons;
632881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int tabSize;
632981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard};
633081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
633181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
633281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpNewCtxt:
633381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @maxNodes:  the maximum number of nodes
633481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @dict:  optional dictionnary to use internally
633581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
633681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Creates a new context for manipulating expressions
633781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
633881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the context or NULL in case of error
633981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
634081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpCtxtPtr
634181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNewCtxt(int maxNodes, xmlDictPtr dict) {
634281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpCtxtPtr ret;
634381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int size = 256;
634481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
634581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (maxNodes <= 4096)
634681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        maxNodes = 4096;
634781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
634881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret = (xmlExpCtxtPtr) xmlMalloc(sizeof(xmlExpCtxt));
634981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ret == NULL)
635081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
635181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    memset(ret, 0, sizeof(xmlExpCtxt));
635281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->size = size;
635381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->nbElems = 0;
6354594e5dfb48ee6fbac1b64155839063648022fc57Daniel Veillard    ret->maxNodes = maxNodes;
635581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->table = xmlMalloc(size * sizeof(xmlExpNodePtr));
635681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ret->table == NULL) {
635781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        xmlFree(ret);
635881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(NULL);
635981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
636081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    memset(ret->table, 0, size * sizeof(xmlExpNodePtr));
636181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (dict == NULL) {
636281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ret->dict = xmlDictCreate();
636381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (ret->dict == NULL) {
636481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlFree(ret->table);
636581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlFree(ret);
636681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(NULL);
636781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
636881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else {
636981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ret->dict = dict;
637081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlDictReference(ret->dict);
637181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
637281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
637381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
637481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
637581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
637681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpFreeCtxt:
637781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt:  an expression context
637881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
637981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Free an expression context
638081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
638181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardvoid
638281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpFreeCtxt(xmlExpCtxtPtr ctxt) {
638381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt == NULL)
638481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return;
638581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlDictFree(ctxt->dict);
638681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->table != NULL)
638781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlFree(ctxt->table);
638881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlFree(ctxt);
638981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
639081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
639181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
639281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
639381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *		Structure associated to an expression node		*
639481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
639581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
6396465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define MAX_NODES 10000
6397465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
6398465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/* #define DEBUG_DERIV */
6399465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
6400465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/*
6401465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * TODO:
6402465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - Wildcards
6403465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - public API for creation
6404465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
6405465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Started
6406465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - regression testing
6407465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
6408465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Done
6409465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - split into module and test tool
6410465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - memleaks
6411465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
641281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
641381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardtypedef enum {
641481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    XML_EXP_NILABLE = (1 << 0)
641581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard} xmlExpNodeInfo;
641681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
641781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define IS_NILLABLE(node) ((node)->info & XML_EXP_NILABLE)
641881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
641981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstruct _xmlExpNode {
642081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned char type;/* xmlExpNodeType */
642181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned char info;/* OR of xmlExpNodeInfo */
642281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned short key;	/* the hash key */
642381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned int ref;	/* The number of references */
642481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int c_max;		/* the maximum length it can consume */
642581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr exp_left;
642681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr next;/* the next node in the hash table or free list */
642781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    union {
642881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	struct {
642981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    int f_min;
643081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    int f_max;
643181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} count;
643281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	struct {
643381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr f_right;
643481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} children;
643581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        const xmlChar *f_str;
643681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } field;
643781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard};
643881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
643981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define exp_min field.count.f_min
644081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define exp_max field.count.f_max
644181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/* #define exp_left field.children.f_left */
644281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define exp_right field.children.f_right
644381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define exp_str field.f_str
644481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
644581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr xmlExpNewNode(xmlExpCtxtPtr ctxt, xmlExpNodeType type);
644681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNode forbiddenExpNode = {
644781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    XML_EXP_FORBID, 0, 0, 0, 0, NULL, NULL, {{ 0, 0}}
644881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard};
644981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNodePtr forbiddenExp = &forbiddenExpNode;
645081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNode emptyExpNode = {
645181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    XML_EXP_EMPTY, 1, 0, 0, 0, NULL, NULL, {{ 0, 0}}
645281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard};
645381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNodePtr emptyExp = &emptyExpNode;
645481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
645581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
645681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
645781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *  The custom hash table for unicity and canonicalization		*
645881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *  of sub-expressions pointers						*
645981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
646081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
646181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/*
646281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpHashNameComputeKey:
646381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Calculate the hash key for a token
646481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
646581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic unsigned short
646681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpHashNameComputeKey(const xmlChar *name) {
646781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned short value = 0L;
646881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    char ch;
646981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
647081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (name != NULL) {
647181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	value += 30 * (*name);
647281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	while ((ch = *name++) != 0) {
647381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
647481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
647581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
647681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return (value);
647781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
647881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
647981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/*
648081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpHashComputeKey:
648181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Calculate the hash key for a compound expression
648281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
648381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic unsigned short
648481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpHashComputeKey(xmlExpNodeType type, xmlExpNodePtr left,
648581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                     xmlExpNodePtr right) {
648681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned long value;
648781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned short ret;
648881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
648981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (type) {
649081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_SEQ:
649181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value = left->key;
649281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value += right->key;
649381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value *= 3;
649481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = (unsigned short) value;
649581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    break;
649681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_OR:
649781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value = left->key;
649881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value += right->key;
649981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value *= 7;
650081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = (unsigned short) value;
650181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    break;
650281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_COUNT:
650381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value = left->key;
650481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value += right->key;
650581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = (unsigned short) value;
650681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    break;
650781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	default:
650881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = 0;
650981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
651081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
651181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
651281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
651381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
651481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr
651581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNewNode(xmlExpCtxtPtr ctxt, xmlExpNodeType type) {
651681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr ret;
651781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
651881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->nb_nodes >= MAX_NODES)
651981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
652081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret = (xmlExpNodePtr) xmlMalloc(sizeof(xmlExpNode));
652181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ret == NULL)
652281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
652381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    memset(ret, 0, sizeof(xmlExpNode));
652481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->type = type;
652581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->next = NULL;
652681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ctxt->nb_nodes++;
652781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ctxt->nb_cons++;
652881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
652981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
653081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
653181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
653281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpHashGetEntry:
653381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @table: the hash table
653481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
653581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Get the unique entry from the hash table. The entry is created if
653681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * needed. @left and @right are consumed, i.e. their ref count will
653781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * be decremented by the operation.
653881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
653981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the pointer or NULL in case of error
654081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
654181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr
654281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpHashGetEntry(xmlExpCtxtPtr ctxt, xmlExpNodeType type,
654381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                   xmlExpNodePtr left, xmlExpNodePtr right,
654481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		   const xmlChar *name, int min, int max) {
654581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned short kbase, key;
654681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr entry;
654781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr insert;
654881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
654981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt == NULL)
655081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(NULL);
655181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
655281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
655381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * Check for duplicate and insertion location.
655481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
655581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (type == XML_EXP_ATOM) {
655681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	kbase = xmlExpHashNameComputeKey(name);
655781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if (type == XML_EXP_COUNT) {
655881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* COUNT reduction rule 1 */
655981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* a{1} -> a */
656081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (min == max) {
656181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (min == 1) {
656281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(left);
656381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
656481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (min == 0) {
656581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, left);
656681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(emptyExp);
656781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
656881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
656981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (min < 0) {
657081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, left);
657181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
657281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
657381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (max == -1)
657481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    kbase = min + 79;
657581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	else
657681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    kbase = max - min;
657781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	kbase += left->key;
657881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if (type == XML_EXP_OR) {
657981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* Forbid reduction rules */
658081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left->type == XML_EXP_FORBID) {
658181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, left);
658281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(right);
658381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
658481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (right->type == XML_EXP_FORBID) {
658581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, right);
658681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(left);
658781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
658881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
658981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* OR reduction rule 1 */
659081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* a | a reduced to a */
659181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left == right) {
659281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    left->ref--;
659381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(left);
659481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
659581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* OR canonicalization rule 1 */
659681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* linearize (a | b) | c into a | (b | c) */
659781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if ((left->type == XML_EXP_OR) && (right->type != XML_EXP_OR)) {
659881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp = left;
659981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            left = right;
660081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    right = tmp;
660181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
660281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* OR reduction rule 2 */
660381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* a | (a | b) and b | (a | b) are reduced to a | b */
660481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (right->type == XML_EXP_OR) {
660581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((left == right->exp_left) ||
660681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (left == right->exp_right)) {
660781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, left);
660881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(right);
660981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
661081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
661181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* OR canonicalization rule 2 */
661281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* linearize (a | b) | c into a | (b | c) */
661381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left->type == XML_EXP_OR) {
661481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp;
661581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
661681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* OR canonicalization rule 2 */
661781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((left->exp_right->type != XML_EXP_OR) &&
661881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (left->exp_right->key < left->exp_left->key)) {
661981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        tmp = left->exp_right;
662081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		left->exp_right = left->exp_left;
662181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		left->exp_left = tmp;
662281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
662381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    left->exp_right->ref++;
662481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_right, right,
662581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                             NULL, 0, 0);
662681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    left->exp_left->ref++;
662781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_left, tmp,
662881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                             NULL, 0, 0);
662981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
663081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, left);
663181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
663281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
663381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (right->type == XML_EXP_OR) {
663481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* Ordering in the tree */
663581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* C | (A | B) -> A | (B | C) */
663681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (left->key > right->exp_right->key) {
663781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpNodePtr tmp;
663881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		right->exp_right->ref++;
663981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_right,
664081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         left, NULL, 0, 0);
664181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		right->exp_left->ref++;
664281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_left,
664381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         tmp, NULL, 0, 0);
664481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, right);
664581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(tmp);
664681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
664781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* Ordering in the tree */
664881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* B | (A | C) -> A | (B | C) */
664981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (left->key > right->exp_left->key) {
665081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpNodePtr tmp;
665181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		right->exp_right->ref++;
665281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left,
665381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         right->exp_right, NULL, 0, 0);
665481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		right->exp_left->ref++;
665581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_left,
665681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         tmp, NULL, 0, 0);
665781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, right);
665881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(tmp);
665981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
666081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
666181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* we know both types are != XML_EXP_OR here */
666281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        else if (left->key > right->key) {
666381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp = left;
666481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            left = right;
666581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    right = tmp;
666681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
666781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	kbase = xmlExpHashComputeKey(type, left, right);
666881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if (type == XML_EXP_SEQ) {
666981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* Forbid reduction rules */
667081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left->type == XML_EXP_FORBID) {
667181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, right);
667281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(left);
667381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
667481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (right->type == XML_EXP_FORBID) {
667581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, left);
667681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(right);
667781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
667881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* Empty reduction rules */
667981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (right->type == XML_EXP_EMPTY) {
668081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(left);
668181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
668281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left->type == XML_EXP_EMPTY) {
668381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(right);
668481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
668581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	kbase = xmlExpHashComputeKey(type, left, right);
668681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else
668781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
668881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
668981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    key = kbase % ctxt->size;
669081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->table[key] != NULL) {
669181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	for (insert = ctxt->table[key]; insert != NULL;
669281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	     insert = insert->next) {
669381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((insert->key == kbase) &&
669481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (insert->type == type)) {
669581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (type == XML_EXP_ATOM) {
669681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (name == insert->exp_str) {
669781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			insert->ref++;
669881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			return(insert);
669981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
670081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else if (type == XML_EXP_COUNT) {
670181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if ((insert->exp_min == min) && (insert->exp_max == max) &&
670281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        (insert->exp_left == left)) {
670381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			insert->ref++;
670481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			left->ref--;
670581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			return(insert);
670681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
670781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else if ((insert->exp_left == left) &&
670881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			   (insert->exp_right == right)) {
670981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    insert->ref++;
671081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    left->ref--;
671181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    right->ref--;
671281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(insert);
671381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
671481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
671581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
671681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
671781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
671881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    entry = xmlExpNewNode(ctxt, type);
671981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (entry == NULL)
672081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
672181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    entry->key = kbase;
672281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (type == XML_EXP_ATOM) {
672381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->exp_str = name;
672481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->c_max = 1;
672581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if (type == XML_EXP_COUNT) {
672681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        entry->exp_min = min;
672781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        entry->exp_max = max;
672881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->exp_left = left;
672981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((min == 0) || (IS_NILLABLE(left)))
673081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    entry->info |= XML_EXP_NILABLE;
673181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (max < 0)
673281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    entry->c_max = -1;
673381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	else
673481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    entry->c_max = max * entry->exp_left->c_max;
673581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else {
673681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->exp_left = left;
673781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->exp_right = right;
673881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (type == XML_EXP_OR) {
673981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((IS_NILLABLE(left)) || (IS_NILLABLE(right)))
674081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		entry->info |= XML_EXP_NILABLE;
674181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((entry->exp_left->c_max == -1) ||
674281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (entry->exp_right->c_max == -1))
674381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		entry->c_max = -1;
674481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else if (entry->exp_left->c_max > entry->exp_right->c_max)
674581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        entry->c_max = entry->exp_left->c_max;
674681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
674781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        entry->c_max = entry->exp_right->c_max;
674881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} else {
674981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((IS_NILLABLE(left)) && (IS_NILLABLE(right)))
675081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		entry->info |= XML_EXP_NILABLE;
675181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((entry->exp_left->c_max == -1) ||
675281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (entry->exp_right->c_max == -1))
675381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		entry->c_max = -1;
675481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
675581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        entry->c_max = entry->exp_left->c_max + entry->exp_right->c_max;
675681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
675781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
675881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    entry->ref = 1;
675981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->table[key] != NULL)
676081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        entry->next = ctxt->table[key];
676181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
676281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ctxt->table[key] = entry;
676381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ctxt->nbElems++;
676481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
676581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(entry);
676681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
676781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
676881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
676981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpFree:
677081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expression context
677181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
677281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
677381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Dereference the expression
677481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
677581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardvoid
677681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpFree(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp) {
677781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((exp == NULL) || (exp == forbiddenExp) || (exp == emptyExp))
677881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return;
677981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    exp->ref--;
678081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (exp->ref == 0) {
678181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        unsigned short key;
678281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
678381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* Unlink it first from the hash table */
678481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	key = exp->key % ctxt->size;
678581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (ctxt->table[key] == exp) {
678681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ctxt->table[key] = exp->next;
678781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} else {
678881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp;
678981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
679081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = ctxt->table[key];
679181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    while (tmp != NULL) {
679281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (tmp->next == exp) {
679381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    tmp->next = exp->next;
679481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    break;
679581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
679681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        tmp = tmp->next;
679781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
679881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
679981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
680081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if ((exp->type == XML_EXP_SEQ) || (exp->type == XML_EXP_OR)) {
680181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, exp->exp_left);
680281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, exp->exp_right);
680381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} else if (exp->type == XML_EXP_COUNT) {
680481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, exp->exp_left);
680581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
680681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        xmlFree(exp);
680781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	ctxt->nb_nodes--;
680881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
680981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
681081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
681181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
681281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpRef:
681381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
681481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
681581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Increase the reference count of the expression
681681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
681781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardvoid
681881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpRef(xmlExpNodePtr exp) {
681981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (exp != NULL)
682081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        exp->ref++;
682181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
682281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
6823ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard/**
6824ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * xmlExpNewAtom:
6825ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @ctxt: the expression context
6826ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @name: the atom name
6827ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @len: the atom name lenght in byte (or -1);
6828ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6829ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Get the atom associated to this name from that context
6830ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6831ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Returns the node or NULL in case of error
6832ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard */
6833ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNodePtr
6834ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNewAtom(xmlExpCtxtPtr ctxt, const xmlChar *name, int len) {
6835ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    if ((ctxt == NULL) || (name == NULL))
6836ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6837ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    name = xmlDictLookup(ctxt->dict, name, len);
6838ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    if (name == NULL)
6839ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6840ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    return(xmlExpHashGetEntry(ctxt, XML_EXP_ATOM, NULL, NULL, name, 0, 0));
6841ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard}
6842ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard
6843ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard/**
6844ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * xmlExpNewOr:
6845ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @ctxt: the expression context
6846ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @left: left expression
6847ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @right: right expression
6848ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6849ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Get the atom associated to the choice @left | @right
6850ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Note that @left and @right are consumed in the operation, to keep
6851ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * an handle on them use xmlExpRef() and use xmlExpFree() to release them,
6852ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * this is true even in case of failure (unless ctxt == NULL).
6853ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6854ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Returns the node or NULL in case of error
6855ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard */
6856ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNodePtr
6857ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNewOr(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) {
685811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if (ctxt == NULL)
685911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard        return(NULL);
686011ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if ((left == NULL) || (right == NULL)) {
6861ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        xmlExpFree(ctxt, left);
6862ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        xmlExpFree(ctxt, right);
6863ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6864ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    }
6865ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, left, right, NULL, 0, 0));
6866ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard}
6867ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard
6868ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard/**
6869ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * xmlExpNewSeq:
6870ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @ctxt: the expression context
6871ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @left: left expression
6872ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @right: right expression
6873ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6874ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Get the atom associated to the sequence @left , @right
6875ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Note that @left and @right are consumed in the operation, to keep
6876ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * an handle on them use xmlExpRef() and use xmlExpFree() to release them,
6877ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * this is true even in case of failure (unless ctxt == NULL).
6878ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6879ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Returns the node or NULL in case of error
6880ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard */
6881ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNodePtr
6882ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNewSeq(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) {
688311ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if (ctxt == NULL)
688411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard        return(NULL);
688511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if ((left == NULL) || (right == NULL)) {
6886ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        xmlExpFree(ctxt, left);
6887ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        xmlExpFree(ctxt, right);
6888ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6889ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    }
6890ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, left, right, NULL, 0, 0));
6891ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard}
6892ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard
6893ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard/**
6894ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * xmlExpNewRange:
6895ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @ctxt: the expression context
6896ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @subset: the expression to be repeated
6897ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @min: the lower bound for the repetition
6898ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @max: the upper bound for the repetition, -1 means infinite
6899ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6900ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Get the atom associated to the range (@subset){@min, @max}
6901ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Note that @subset is consumed in the operation, to keep
6902ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * an handle on it use xmlExpRef() and use xmlExpFree() to release it,
6903ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * this is true even in case of failure (unless ctxt == NULL).
6904ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6905ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Returns the node or NULL in case of error
6906ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard */
6907ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNodePtr
6908ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNewRange(xmlExpCtxtPtr ctxt, xmlExpNodePtr subset, int min, int max) {
690911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if (ctxt == NULL)
691011ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard        return(NULL);
691111ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if ((subset == NULL) || (min < 0) || (max < -1) ||
6912ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        ((max >= 0) && (min > max))) {
6913ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	xmlExpFree(ctxt, subset);
6914ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6915ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    }
6916ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    return(xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, subset,
6917ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard                              NULL, NULL, min, max));
6918ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard}
6919ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard
692081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
692181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
692281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *		Public API for operations on expressions		*
692381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
692481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
692581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
692681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic int
692781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpGetLanguageInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
692881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                     const xmlChar**list, int len, int nb) {
692981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int tmp, tmp2;
693081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardtail:
693181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (exp->type) {
693281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_EMPTY:
693381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(0);
693481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_ATOM:
693581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    for (tmp = 0;tmp < nb;tmp++)
693681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (list[tmp] == exp->exp_str)
693781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(0);
693881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            if (nb >= len)
693981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(-2);
694013cee4e37ba9f2a401f976e069539514ebfce7bcDaniel Veillard	    list[nb] = exp->exp_str;
694181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(1);
694281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_COUNT:
694381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    exp = exp->exp_left;
694481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    goto tail;
694581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_SEQ:
694681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_OR:
694781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpGetLanguageInt(ctxt, exp->exp_left, list, len, nb);
694881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp < 0)
694981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp);
695081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp2 = xmlExpGetLanguageInt(ctxt, exp->exp_right, list, len,
695181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                                nb + tmp);
695281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp2 < 0)
695381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp2);
695481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            return(tmp + tmp2);
695581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
695681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(-1);
695781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
695881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
695981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
696081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpGetLanguage:
696181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expression context
696281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
69637802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard * @langList: where to store the tokens
696481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @len: the allocated lenght of @list
696581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
696681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Find all the strings used in @exp and store them in @list
696781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
696881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the number of unique strings found, -1 in case of errors and
696981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *         -2 if there is more than @len strings
697081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
697181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardint
697281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
69737802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard                  const xmlChar**langList, int len) {
69747802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard    if ((ctxt == NULL) || (exp == NULL) || (langList == NULL) || (len <= 0))
697581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
69767802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard    return(xmlExpGetLanguageInt(ctxt, exp, langList, len, 0));
697781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
697881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
697981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic int
698081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpGetStartInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
698181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                  const xmlChar**list, int len, int nb) {
698281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int tmp, tmp2;
698381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardtail:
698481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (exp->type) {
698581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_FORBID:
698681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(0);
698781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_EMPTY:
698881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(0);
698981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_ATOM:
699081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    for (tmp = 0;tmp < nb;tmp++)
699181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (list[tmp] == exp->exp_str)
699281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(0);
699381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            if (nb >= len)
699481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(-2);
699513cee4e37ba9f2a401f976e069539514ebfce7bcDaniel Veillard	    list[nb] = exp->exp_str;
699681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(1);
699781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_COUNT:
699881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    exp = exp->exp_left;
699981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    goto tail;
700081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_SEQ:
700181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb);
700281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp < 0)
700381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp);
700481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (IS_NILLABLE(exp->exp_left)) {
700581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len,
700681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard					    nb + tmp);
700781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (tmp2 < 0)
700881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(tmp2);
700981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp += tmp2;
701081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
701181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            return(tmp);
701281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_OR:
701381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb);
701481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp < 0)
701581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp);
701681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len,
701781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                                nb + tmp);
701881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp2 < 0)
701981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp2);
702081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            return(tmp + tmp2);
702181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
702281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(-1);
702381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
702481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
702581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
702681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpGetStart:
702781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expression context
702881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
70297802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard * @tokList: where to store the tokens
703081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @len: the allocated lenght of @list
703181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
703281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Find all the strings that appears at the start of the languages
703381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * accepted by @exp and store them in @list. E.g. for (a, b) | c
703481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * it will return the list [a, c]
703581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
703681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the number of unique strings found, -1 in case of errors and
703781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *         -2 if there is more than @len strings
703881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
703981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardint
704081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpGetStart(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
70417802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard               const xmlChar**tokList, int len) {
70427802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard    if ((ctxt == NULL) || (exp == NULL) || (tokList == NULL) || (len <= 0))
704381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
70447802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard    return(xmlExpGetStartInt(ctxt, exp, tokList, len, 0));
704581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
704681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
704781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
704881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpIsNillable:
704981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
705081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
705181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Finds if the expression is nillable, i.e. if it accepts the empty sequqnce
705281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
705381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns 1 if nillable, 0 if not and -1 in case of error
705481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
705581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardint
705681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpIsNillable(xmlExpNodePtr exp) {
705781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (exp == NULL)
705881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
705981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(IS_NILLABLE(exp) != 0);
706081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
706181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
706281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr
706381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str)
706481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard{
706581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr ret;
706681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
706781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (exp->type) {
706881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_EMPTY:
706981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
707081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_FORBID:
707181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
707281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_ATOM:
707381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_str == str) {
707481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
707581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv atom: equal => Empty\n");
707681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
707781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        ret = emptyExp;
707881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    } else {
707981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
708081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv atom: mismatch => forbid\n");
708181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
708281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        /* TODO wildcards here */
708381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		ret = forbiddenExp;
708481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
708581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
708681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_OR: {
708781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp;
708881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
708981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
709081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("deriv or: => or(derivs)\n");
709181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
709281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
709381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp == NULL) {
709481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(NULL);
709581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
709681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str);
709781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL) {
709881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        xmlExpFree(ctxt, tmp);
709981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(NULL);
710081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
710181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret,
710281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			     NULL, 0, 0);
710381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
710481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
710581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_SEQ:
710681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
710781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("deriv seq: starting with left\n");
710881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
710981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
711081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL) {
711181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
711281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    } else if (ret == forbiddenExp) {
711381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (IS_NILLABLE(exp->exp_left)) {
711481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
711581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("deriv seq: left failed but nillable\n");
711681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
711781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str);
711881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
711981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    } else {
712081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
712181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv seq: left match => sequence\n");
712281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
712381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        exp->exp_right->ref++;
712481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, exp->exp_right,
712581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         NULL, 0, 0);
712681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
712781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
712881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_COUNT: {
712981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    int min, max;
713081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp;
713181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
713281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_max == 0)
713381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(forbiddenExp);
713481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
713581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL)
713681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
713781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == forbiddenExp) {
713881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
713981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv count: pattern mismatch => forbid\n");
714081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
714181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(ret);
714281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
714381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_max == 1)
714481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(ret);
714581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_max < 0) /* unbounded */
714681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		max = -1;
714781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
714881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		max = exp->exp_max - 1;
714981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_min > 0)
715081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		min = exp->exp_min - 1;
715181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
715281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		min = 0;
715381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    exp->exp_left->ref++;
715481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, NULL,
715581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				     NULL, min, max);
715681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == emptyExp) {
715781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
715881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv count: match to empty => new count\n");
715981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
716081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp);
716181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
716281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
716381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("deriv count: match => sequence with new count\n");
716481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
716581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, tmp,
716681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                              NULL, 0, 0));
716781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
716881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
716981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(NULL);
717081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
717181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
717281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
717381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpStringDerive:
717481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expression context
717581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
717681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @str: the string
717781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @len: the string len in bytes if available
717881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
717981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Do one step of Brzozowski derivation of the expression @exp with
718081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * respect to the input string
718181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
718281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the resulting expression or NULL in case of internal error
718381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
718481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNodePtr
718581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpStringDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
718681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                   const xmlChar *str, int len) {
718781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    const xmlChar *input;
718881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
718981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((exp == NULL) || (ctxt == NULL) || (str == NULL)) {
719081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
719181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
719281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
719381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * check the string is in the dictionnary, if yes use an interned
719481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * copy, otherwise we know it's not an acceptable input
719581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
719681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    input = xmlDictExists(ctxt->dict, str, len);
719781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (input == NULL) {
719881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(forbiddenExp);
719981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
720081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(xmlExpStringDeriveInt(ctxt, exp, input));
720181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
720281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
720381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic int
720481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpCheckCard(xmlExpNodePtr exp, xmlExpNodePtr sub) {
720581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int ret = 1;
720681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
720781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (sub->c_max == -1) {
720881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (exp->c_max != -1)
720981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = 0;
721081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if ((exp->c_max >= 0) && (exp->c_max < sub->c_max)) {
721181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ret = 0;
721281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
721381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#if 0
721481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((IS_NILLABLE(sub)) && (!IS_NILLABLE(exp)))
721581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ret = 0;
721681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
721781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
721881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
721981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
722081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
722181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                                        xmlExpNodePtr sub);
722281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
722381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpDivide:
722481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expressions context
722581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the englobing expression
722681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @sub: the subexpression
722781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @mult: the multiple expression
722881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @remain: the remain from the derivation of the multiple
722981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
723081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Check if exp is a multiple of sub, i.e. if there is a finite number n
723181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * so that sub{n} subsume exp
723281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
723381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the multiple value if successful, 0 if it is not a multiple
723481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *         and -1 in case of internel error.
723581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
723681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
723781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic int
723881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpDivide(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub,
723981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard             xmlExpNodePtr *mult, xmlExpNodePtr *remain) {
724081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int i;
724181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr tmp, tmp2;
724281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
724381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (mult != NULL) *mult = NULL;
724481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (remain != NULL) *remain = NULL;
724581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (exp->c_max == -1) return(0);
724681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (IS_NILLABLE(exp) && (!IS_NILLABLE(sub))) return(0);
724781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
724881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    for (i = 1;i <= exp->c_max;i++) {
724981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        sub->ref++;
725081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT,
725181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				 sub, NULL, NULL, i, i);
725281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == NULL) {
725381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(-1);
725481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
725581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (!xmlExpCheckCard(tmp, exp)) {
725681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, tmp);
725781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    continue;
725881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
725981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	tmp2 = xmlExpExpDeriveInt(ctxt, tmp, exp);
726081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp2 == NULL) {
726181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, tmp);
726281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(-1);
726381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
726481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((tmp2 != forbiddenExp) && (IS_NILLABLE(tmp2))) {
726581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (remain != NULL)
726681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        *remain = tmp2;
726781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
726881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        xmlExpFree(ctxt, tmp2);
726981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (mult != NULL)
727081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        *mult = tmp;
727181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
727281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        xmlExpFree(ctxt, tmp);
727381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
727481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Divide succeeded %d\n", i);
727581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
727681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(i);
727781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
727881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp);
727981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp2);
728081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
728181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
728281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    printf("Divide failed\n");
728381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
728481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(0);
728581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
728681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
728781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
728881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpExpDeriveInt:
728981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expressions context
729081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the englobing expression
729181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @sub: the subexpression
729281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
729381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Try to do a step of Brzozowski derivation but at a higher level
729481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * the input being a subexpression.
729581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
729681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the resulting expression or NULL in case of internal error
729781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
729881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr
729981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
730081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr ret, tmp, tmp2, tmp3;
730181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    const xmlChar **tab;
730281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int len, i;
730381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
730481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
730581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * In case of equality and if the expression can only consume a finite
730681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * amount, then the derivation is empty
730781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
730881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((exp == sub) && (exp->c_max >= 0)) {
730981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
731081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("Equal(exp, sub) and finite -> Empty\n");
731181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
731281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(emptyExp);
731381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
731481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
731581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * decompose sub sequence first
731681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
731781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (sub->type == XML_EXP_EMPTY) {
731881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
731981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("Empty(sub) -> Empty\n");
732081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
732181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	exp->ref++;
732281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(exp);
732381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
732481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (sub->type == XML_EXP_SEQ) {
732581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
732681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("Seq(sub) -> decompose\n");
732781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
732881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left);
732981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == NULL)
733081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(NULL);
733181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == forbiddenExp)
733281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
733381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	ret = xmlExpExpDeriveInt(ctxt, tmp, sub->exp_right);
733481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp);
733581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(ret);
733681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
733781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (sub->type == XML_EXP_OR) {
733881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
733981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("Or(sub) -> decompose\n");
734081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
734181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left);
734281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == forbiddenExp)
734381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
734481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == NULL)
734581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(NULL);
734681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	ret = xmlExpExpDeriveInt(ctxt, exp, sub->exp_right);
734781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((ret == NULL) || (ret == forbiddenExp)) {
734881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, tmp);
734981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
735081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
735181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret, NULL, 0, 0));
735281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
735381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (!xmlExpCheckCard(exp, sub)) {
735481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
735581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("CheckCard(exp, sub) failed -> Forbid\n");
735681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
735781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(forbiddenExp);
735881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
735981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (exp->type) {
736081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_EMPTY:
736181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (sub == emptyExp)
736281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(emptyExp);
736381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
736481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Empty(exp) -> Forbid\n");
736581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
736681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
736781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_FORBID:
736881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
736981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Forbid(exp) -> Forbid\n");
737081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
737181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
737281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_ATOM:
737381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (sub->type == XML_EXP_ATOM) {
737481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        /* TODO: handle wildcards */
737581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (exp->exp_str == sub->exp_str) {
737681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
737781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Atom match -> Empty\n");
737881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
737981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(emptyExp);
738081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                }
738181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
738281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Atom mismatch -> Forbid\n");
738381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
738481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(forbiddenExp);
738581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
738681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((sub->type == XML_EXP_COUNT) &&
738781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (sub->exp_max == 1) &&
738881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (sub->exp_left->type == XML_EXP_ATOM)) {
738981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        /* TODO: handle wildcards */
739081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (exp->exp_str == sub->exp_left->exp_str) {
739181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
739281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Atom match -> Empty\n");
739381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
739481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(emptyExp);
739581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
739681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
739781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Atom mismatch -> Forbid\n");
739881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
739981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(forbiddenExp);
740081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
740181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
740281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Compex exp vs Atom -> Forbid\n");
740381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
740481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
740581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_SEQ:
740681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* try to get the sequence consumed only if possible */
740781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (xmlExpCheckCard(exp->exp_left, sub)) {
740881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		/* See if the sequence can be consumed directly */
740981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
741081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Seq trying left only\n");
741181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
741281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
741381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if ((ret != forbiddenExp) && (ret != NULL)) {
741481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
741581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Seq trying left only worked\n");
741681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
741781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    /*
741881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     * TODO: assumption here that we are determinist
741981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     *       i.e. we won't get to a nillable exp left
742081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     *       subset which could be matched by the right
742181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     *       part too.
742281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     * e.g.: (a | b)+,(a | c) and 'a+,a'
742381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     */
742481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    exp->exp_right->ref++;
742581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret,
742681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard					      exp->exp_right, NULL, 0, 0));
742781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
742881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
742981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    } else {
743081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Seq: left too short\n");
743181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
743281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
743381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* Try instead to decompose */
743481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (sub->type == XML_EXP_COUNT) {
743581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		int min, max;
743681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
743781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
743881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Seq: sub is a count\n");
743981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
744081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left);
744181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (ret == NULL)
744281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(NULL);
744381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (ret != forbiddenExp) {
744481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
744581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Seq , Count match on left\n");
744681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
744781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (sub->exp_max < 0)
744881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        max = -1;
744981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	            else
745081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        max = sub->exp_max -1;
745181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (sub->exp_min > 0)
745281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        min = sub->exp_min -1;
745381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    else
745481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        min = 0;
745581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    exp->exp_right->ref++;
745681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret,
745781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                             exp->exp_right, NULL, 0, 0);
745881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (tmp == NULL)
745981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        return(NULL);
746081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
746181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    sub->exp_left->ref++;
746281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT,
746381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				      sub->exp_left, NULL, NULL, min, max);
746481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (tmp2 == NULL) {
746581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        xmlExpFree(ctxt, tmp);
746681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			return(NULL);
746781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
746881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    ret = xmlExpExpDeriveInt(ctxt, tmp, tmp2);
746981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    xmlExpFree(ctxt, tmp);
747081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    xmlExpFree(ctxt, tmp2);
747181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(ret);
747281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
747381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
747481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* we made no progress on structured operations */
747581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    break;
747681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_OR:
747781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
747881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Or , trying both side\n");
747981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
748081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
748181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL)
748281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
748381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpExpDeriveInt(ctxt, exp->exp_right, sub);
748481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp == NULL) {
748581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, ret);
748681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
748781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
748881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, tmp, NULL, 0, 0));
748981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_COUNT: {
749081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    int min, max;
749181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
749281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (sub->type == XML_EXP_COUNT) {
749381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        /*
749481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		 * Try to see if the loop is completely subsumed
749581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		 */
749681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        tmp = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left);
749781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (tmp == NULL)
749881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(NULL);
749981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (tmp == forbiddenExp) {
750081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    int mult;
750181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
750281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
750381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Count, Count inner don't subsume\n");
750481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
750581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    mult = xmlExpDivide(ctxt, sub->exp_left, exp->exp_left,
750681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                        NULL, &tmp);
750781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (mult <= 0) {
750881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
750981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			printf("Count, Count not multiple => forbidden\n");
751081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
751181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                        return(forbiddenExp);
751281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
751381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (sub->exp_max == -1) {
751481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        max = -1;
751581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			if (exp->exp_max == -1) {
751681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    if (exp->exp_min <= sub->exp_min * mult)
751781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			        min = 0;
751881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    else
751981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			        min = exp->exp_min - sub->exp_min * mult;
752081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			} else {
752181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
752281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("Count, Count finite can't subsume infinite\n");
752381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
752481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                            xmlExpFree(ctxt, tmp);
752581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    return(forbiddenExp);
752681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
752781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    } else {
752881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			if (exp->exp_max == -1) {
752981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
753081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("Infinite loop consume mult finite loop\n");
753181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
753281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    if (exp->exp_min > sub->exp_min * mult) {
753381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				max = -1;
753481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				min = exp->exp_min - sub->exp_min * mult;
753581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    } else {
753681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				max = -1;
753781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				min = 0;
753881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    }
753981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			} else {
754081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    if (exp->exp_max < sub->exp_max * mult) {
754181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
754281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				printf("loops max mult mismatch => forbidden\n");
754381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
754481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				xmlExpFree(ctxt, tmp);
754581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				return(forbiddenExp);
754681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    }
754781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    if (sub->exp_max * mult > exp->exp_min)
754881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				min = 0;
754981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    else
755081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				min = exp->exp_min - sub->exp_max * mult;
755181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    max = exp->exp_max - sub->exp_max * mult;
755281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
755381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
755481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else if (!IS_NILLABLE(tmp)) {
755581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    /*
755681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     * TODO: loop here to try to grow if working on finite
755781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     *       blocks.
755881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     */
755981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
756081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Count, Count remain not nillable => forbidden\n");
756181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
756281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    xmlExpFree(ctxt, tmp);
756381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(forbiddenExp);
756481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else if (sub->exp_max == -1) {
756581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (exp->exp_max == -1) {
756681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        if (exp->exp_min <= sub->exp_min) {
756781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
756881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("Infinite loops Okay => COUNT(0,Inf)\n");
756981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
757081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                            max = -1;
757181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = 0;
757281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			} else {
757381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
757481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("Infinite loops min => Count(X,Inf)\n");
757581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
757681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                            max = -1;
757781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = exp->exp_min - sub->exp_min;
757881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
757981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    } else if (exp->exp_min > sub->exp_min) {
758081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
758181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			printf("loops min mismatch 1 => forbidden ???\n");
758281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
758381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        xmlExpFree(ctxt, tmp);
758481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        return(forbiddenExp);
758581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    } else {
758681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			max = -1;
758781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			min = 0;
758881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
758981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else {
759081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (exp->exp_max == -1) {
759181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
759281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			printf("Infinite loop consume finite loop\n");
759381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
759481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        if (exp->exp_min > sub->exp_min) {
759581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    max = -1;
759681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = exp->exp_min - sub->exp_min;
759781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			} else {
759881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    max = -1;
759981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = 0;
760081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
760181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    } else {
760281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        if (exp->exp_max < sub->exp_max) {
760381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
760481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("loops max mismatch => forbidden\n");
760581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
760681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    xmlExpFree(ctxt, tmp);
760781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    return(forbiddenExp);
760881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
760981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			if (sub->exp_max > exp->exp_min)
761081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = 0;
761181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			else
761281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = exp->exp_min - sub->exp_max;
761381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			max = exp->exp_max - sub->exp_max;
761481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
761581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
761681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
761781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("loops match => SEQ(COUNT())\n");
761881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
761981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		exp->exp_left->ref++;
762081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left,
762181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                          NULL, NULL, min, max);
762281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (tmp2 == NULL) {
762381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(NULL);
762481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
762581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, tmp, tmp2,
762681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         NULL, 0, 0);
762781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(ret);
762881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
762981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
763081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp == NULL)
763181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(NULL);
763281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp == forbiddenExp) {
763381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
763481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("loop mismatch => forbidden\n");
763581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
763681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(forbiddenExp);
763781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
763881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_min > 0)
763981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		min = exp->exp_min - 1;
764081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
764181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		min = 0;
764281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_max < 0)
764381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		max = -1;
764481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
764581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		max = exp->exp_max - 1;
764681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
764781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
764881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("loop match => SEQ(COUNT())\n");
764981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
765081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    exp->exp_left->ref++;
765181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left,
765281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				      NULL, NULL, min, max);
765381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp2 == NULL)
765481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(NULL);
765581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, tmp, tmp2,
765681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				     NULL, 0, 0);
765781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
765881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
765981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
766081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
7661ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard#ifdef DEBUG_DERIV
7662ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    printf("Fallback to derivative\n");
7663ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard#endif
7664ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    if (IS_NILLABLE(sub)) {
7665ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        if (!(IS_NILLABLE(exp)))
7666ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	    return(forbiddenExp);
7667ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	else
7668ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	    ret = emptyExp;
7669ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    } else
7670ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	ret = NULL;
767181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
767281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * here the structured derivation made no progress so
767381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * we use the default token based derivation to force one more step
767481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
767581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->tabSize == 0)
767681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ctxt->tabSize = 40;
767781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
767881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    tab = (const xmlChar **) xmlMalloc(ctxt->tabSize *
767981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                               sizeof(const xmlChar *));
768081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (tab == NULL) {
768181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(NULL);
768281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
768381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
768481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
768581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * collect all the strings accepted by the subexpression on input
768681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
768781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0);
768881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    while (len < 0) {
768981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        const xmlChar **temp;
769054a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	temp = (const xmlChar **) xmlRealloc((xmlChar **) tab, ctxt->tabSize * 2 *
769181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                                     sizeof(const xmlChar *));
769281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (temp == NULL) {
769354a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	    xmlFree((xmlChar **) tab);
769481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(NULL);
769581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
769681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	tab = temp;
769781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	ctxt->tabSize *= 2;
769881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0);
769981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
770081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    for (i = 0;i < len;i++) {
770181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        tmp = xmlExpStringDeriveInt(ctxt, exp, tab[i]);
770281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((tmp == NULL) || (tmp == forbiddenExp)) {
770381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, ret);
770454a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	    xmlFree((xmlChar **) tab);
770581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
770681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
770781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	tmp2 = xmlExpStringDeriveInt(ctxt, sub, tab[i]);
770881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((tmp2 == NULL) || (tmp2 == forbiddenExp)) {
770981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, tmp);
771081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, ret);
771154a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	    xmlFree((xmlChar **) tab);
771281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
771381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
771481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	tmp3 = xmlExpExpDeriveInt(ctxt, tmp, tmp2);
771581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp);
771681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp2);
771781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
771881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((tmp3 == NULL) || (tmp3 == forbiddenExp)) {
771981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, ret);
772054a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	    xmlFree((xmlChar **) tab);
772181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp3);
772281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
772381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
772481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (ret == NULL)
772581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = tmp3;
772681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	else {
772781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, tmp3, NULL, 0, 0);
772881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL) {
772954a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards		xmlFree((xmlChar **) tab);
773081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
773181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
773281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
773381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
773454a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards    xmlFree((xmlChar **) tab);
773581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
773681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
773781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
773881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
77390090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * xmlExpExpDerive:
77400090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * @ctxt: the expressions context
77410090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * @exp: the englobing expression
77420090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * @sub: the subexpression
77430090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard *
77440090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * Evaluates the expression resulting from @exp consuming a sub expression @sub
77450090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * Based on algebraic derivation and sometimes direct Brzozowski derivation
77460090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * it usually tatkes less than linear time and can handle expressions generating
77470090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * infinite languages.
77480090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard *
77490090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * Returns the resulting expression or NULL in case of internal error, the
77500090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard *         result must be freed
77510090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard */
77520090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel VeillardxmlExpNodePtr
77530090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel VeillardxmlExpExpDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
77540090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if ((exp == NULL) || (ctxt == NULL) || (sub == NULL))
77550090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        return(NULL);
77560090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
77570090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    /*
77580090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard     * O(1) speedups
77590090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard     */
77600090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) {
77610090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#ifdef DEBUG_DERIV
77620090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	printf("Sub nillable and not exp : can't subsume\n");
77630090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#endif
77640090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        return(forbiddenExp);
77650090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    }
77660090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (xmlExpCheckCard(exp, sub) == 0) {
77670090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#ifdef DEBUG_DERIV
77680090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	printf("sub generate longuer sequances than exp : can't subsume\n");
77690090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#endif
77700090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        return(forbiddenExp);
77710090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    }
77720090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    return(xmlExpExpDeriveInt(ctxt, exp, sub));
77730090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard}
77740090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
77750090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard/**
777681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpSubsume:
777781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expressions context
777881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the englobing expression
777981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @sub: the subexpression
778081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
778181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Check whether @exp accepts all the languages accexpted by @sub
778281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * the input being a subexpression.
778381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
778481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns 1 if true 0 if false and -1 in case of failure.
778581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
778681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardint
778781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
778881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr tmp;
778981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
779081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((exp == NULL) || (ctxt == NULL) || (sub == NULL))
779181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
779281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
779381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
779481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * TODO: speedup by checking the language of sub is a subset of the
779581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     *       language of exp
779681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
779781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
779881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * O(1) speedups
779981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
780081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) {
780181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
780281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	printf("Sub nillable and not exp : can't subsume\n");
780381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
780481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(0);
780581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
780681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (xmlExpCheckCard(exp, sub) == 0) {
780781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
780881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	printf("sub generate longuer sequances than exp : can't subsume\n");
780981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
781081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(0);
781181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
781281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    tmp = xmlExpExpDeriveInt(ctxt, exp, sub);
781381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
781481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    printf("Result derivation :\n");
781581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    PRINT_EXP(tmp);
781681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
781781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (tmp == NULL)
781881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
781981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (tmp == forbiddenExp)
782081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(0);
782181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (tmp == emptyExp)
782281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(1);
782381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((tmp != NULL) && (IS_NILLABLE(tmp))) {
782481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        xmlExpFree(ctxt, tmp);
782581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(1);
782681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
782781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpFree(ctxt, tmp);
782881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(0);
782981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
7830465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7831465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/************************************************************************
7832465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *									*
7833465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *			Parsing expression 				*
7834465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *									*
7835465a000b1080427bd62d89a925409b7db78616acDaniel Veillard ************************************************************************/
7836465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7837465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic xmlExpNodePtr xmlExpParseExpr(xmlExpCtxtPtr ctxt);
7838465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7839465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#undef CUR
7840465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define CUR (*ctxt->cur)
7841465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#undef NEXT
7842465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define NEXT ctxt->cur++;
7843465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#undef IS_BLANK
7844465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define IS_BLANK(c) ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))
7845465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define SKIP_BLANKS while (IS_BLANK(*ctxt->cur)) ctxt->cur++;
7846465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7847465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic int
7848465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParseNumber(xmlExpCtxtPtr ctxt) {
7849465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    int ret = 0;
7850465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7851465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7852465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (CUR == '*') {
7853465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	NEXT
7854465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	return(-1);
7855465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7856465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if ((CUR < '0') || (CUR > '9'))
7857465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(-1);
7858465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while ((CUR >= '0') && (CUR <= '9')) {
7859465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        ret = ret * 10 + (CUR - '0');
7860465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	NEXT
7861465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7862465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
7863465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
7864465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7865465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic xmlExpNodePtr
7866465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParseOr(xmlExpCtxtPtr ctxt) {
7867465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    const char *base;
7868465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr ret;
7869465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    const xmlChar *val;
7870465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7871465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7872465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    base = ctxt->cur;
7873465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (*ctxt->cur == '(') {
7874465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7875465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpParseExpr(ctxt);
7876465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7877465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (*ctxt->cur != ')') {
7878465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    fprintf(stderr, "unbalanced '(' : %s\n", base);
7879465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7880465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7881465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7882465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	NEXT;
7883465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7884465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	goto parse_quantifier;
7885465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7886465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while ((CUR != 0) && (!(IS_BLANK(CUR))) && (CUR != '(') &&
7887465a000b1080427bd62d89a925409b7db78616acDaniel Veillard           (CUR != ')') && (CUR != '|') && (CUR != ',') && (CUR != '{') &&
7888465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	   (CUR != '*') && (CUR != '+') && (CUR != '?') && (CUR != '}'))
7889465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	NEXT;
7890465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    val = xmlDictLookup(ctxt->dict, BAD_CAST base, ctxt->cur - base);
7891465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (val == NULL)
7892465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(NULL);
7893465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ret = xmlExpHashGetEntry(ctxt, XML_EXP_ATOM, NULL, NULL, val, 0, 0);
7894465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (ret == NULL)
7895465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(NULL);
7896465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7897465a000b1080427bd62d89a925409b7db78616acDaniel Veillardparse_quantifier:
7898465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (CUR == '{') {
7899465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        int min, max;
7900465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7901465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7902465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	min = xmlExpParseNumber(ctxt);
7903465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (min < 0) {
7904465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7905465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7906465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7907465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7908465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (CUR == ',') {
7909465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    NEXT
7910465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    max = xmlExpParseNumber(ctxt);
7911465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    SKIP_BLANKS
7912465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	} else
7913465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    max = min;
7914465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (CUR != '}') {
7915465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7916465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7917465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7918465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7919465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7920465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	                         min, max);
7921465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7922465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    } else if (CUR == '?') {
7923465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7924465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7925465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	                         0, 1);
7926465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7927465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    } else if (CUR == '+') {
7928465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7929465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7930465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	                         1, -1);
7931465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7932465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    } else if (CUR == '*') {
7933465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7934465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7935465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	                         0, -1);
7936465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7937465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7938465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
7939465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
7940465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7941465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7942465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic xmlExpNodePtr
7943465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParseSeq(xmlExpCtxtPtr ctxt) {
7944465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr ret, right;
7945465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7946465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ret = xmlExpParseOr(ctxt);
7947465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7948465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while (CUR == '|') {
7949465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7950465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	right = xmlExpParseOr(ctxt);
7951465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (right == NULL) {
7952465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7953465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7954465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7955465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, right, NULL, 0, 0);
7956465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (ret == NULL)
7957465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7958465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7959465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
7960465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
7961465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7962465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic xmlExpNodePtr
7963465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParseExpr(xmlExpCtxtPtr ctxt) {
7964465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr ret, right;
7965465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7966465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ret = xmlExpParseSeq(ctxt);
7967465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7968465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while (CUR == ',') {
7969465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7970465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	right = xmlExpParseSeq(ctxt);
7971465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (right == NULL) {
7972465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7973465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7974465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7975465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, right, NULL, 0, 0);
7976465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (ret == NULL)
7977465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7978465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7979465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
7980465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
7981465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7982465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
7983465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpParse:
7984465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @ctxt: the expressions context
7985465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @expr: the 0 terminated string
7986465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
7987465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Minimal parser for regexps, it understand the following constructs
7988465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - string terminals
7989465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - choice operator |
7990465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - sequence operator ,
7991465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - subexpressions (...)
7992465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - usual cardinality operators + * and ?
7993465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - finite sequences  { min, max }
7994465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - infinite sequences { min, * }
7995465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * There is minimal checkings made especially no checking on strings values
7996465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
7997465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Returns a new expression or NULL in case of failure
7998465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
7999465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpNodePtr
8000465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParse(xmlExpCtxtPtr ctxt, const char *expr) {
8001465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr ret;
8002465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8003465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ctxt->expr = expr;
8004465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ctxt->cur = expr;
8005465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8006465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ret = xmlExpParseExpr(ctxt);
8007465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
8008465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (*ctxt->cur != 0) {
8009465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        xmlExpFree(ctxt, ret);
8010465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(NULL);
8011465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
8012465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
8013465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8014465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8015465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic void
8016465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpDumpInt(xmlBufferPtr buf, xmlExpNodePtr expr, int glob) {
8017465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr c;
8018465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8019465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (expr == NULL) return;
8020465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (glob) xmlBufferWriteChar(buf, "(");
8021465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    switch (expr->type) {
8022465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_EMPTY:
8023465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, "empty");
8024465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    break;
8025465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_FORBID:
8026465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, "forbidden");
8027465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    break;
8028465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_ATOM:
8029465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteCHAR(buf, expr->exp_str);
8030465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    break;
8031465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_SEQ:
8032465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_left;
8033465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8034465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8035465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8036465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8037465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, " , ");
8038465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_right;
8039465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8040465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8041465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8042465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8043465a000b1080427bd62d89a925409b7db78616acDaniel Veillard            break;
8044465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_OR:
8045465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_left;
8046465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8047465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8048465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8049465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8050465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, " | ");
8051465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_right;
8052465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8053465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8054465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8055465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8056465a000b1080427bd62d89a925409b7db78616acDaniel Veillard            break;
8057465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_COUNT: {
8058465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    char rep[40];
8059465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8060465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_left;
8061465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8062465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8063465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8064465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8065465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((expr->exp_min == 0) && (expr->exp_max == 1)) {
8066465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[0] = '?';
8067465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[1] = 0;
8068465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if ((expr->exp_min == 0) && (expr->exp_max == -1)) {
8069465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[0] = '*';
8070465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[1] = 0;
8071465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if ((expr->exp_min == 1) && (expr->exp_max == -1)) {
8072465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[0] = '+';
8073465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[1] = 0;
8074465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if (expr->exp_max == expr->exp_min) {
8075465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        snprintf(rep, 39, "{%d}", expr->exp_min);
8076465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if (expr->exp_max < 0) {
8077465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        snprintf(rep, 39, "{%d,inf}", expr->exp_min);
8078465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else {
8079465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        snprintf(rep, 39, "{%d,%d}", expr->exp_min, expr->exp_max);
8080465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    }
8081465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    rep[39] = 0;
8082465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, rep);
8083465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    break;
8084465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
8085465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	default:
8086465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    fprintf(stderr, "Error in tree\n");
8087465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
8088465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (glob)
8089465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        xmlBufferWriteChar(buf, ")");
8090465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8091465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
8092465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpDump:
8093465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @buf:  a buffer to receive the output
8094465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @expr:  the compiled expression
8095465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8096465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Serialize the expression as compiled to the buffer
8097465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
8098465a000b1080427bd62d89a925409b7db78616acDaniel Veillardvoid
80995eee767ca9b30a8e8c54808c82060ceb41630d6aDaniel VeillardxmlExpDump(xmlBufferPtr buf, xmlExpNodePtr expr) {
81005eee767ca9b30a8e8c54808c82060ceb41630d6aDaniel Veillard    if ((buf == NULL) || (expr == NULL))
8101465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return;
81025eee767ca9b30a8e8c54808c82060ceb41630d6aDaniel Veillard    xmlExpDumpInt(buf, expr, 0);
8103465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8104465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8105465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
8106465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpMaxToken:
8107465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @expr: a compiled expression
8108465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8109465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Indicate the maximum number of input a expression can accept
8110465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8111465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Returns the maximum length or -1 in case of error
8112465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
8113465a000b1080427bd62d89a925409b7db78616acDaniel Veillardint
8114465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpMaxToken(xmlExpNodePtr expr) {
8115465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (expr == NULL)
8116465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(-1);
8117465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(expr->c_max);
8118465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8119465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8120465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
8121465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpCtxtNbNodes:
8122465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @ctxt: an expression context
8123465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8124465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Debugging facility provides the number of allocated nodes at a that point
8125465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8126465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Returns the number of nodes in use or -1 in case of error
8127465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
8128465a000b1080427bd62d89a925409b7db78616acDaniel Veillardint
8129465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt) {
8130465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (ctxt == NULL)
8131465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(-1);
8132465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ctxt->nb_nodes);
8133465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8134465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8135465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
8136465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpCtxtNbCons:
8137465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @ctxt: an expression context
8138465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8139465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Debugging facility provides the number of allocated nodes over lifetime
8140465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8141465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Returns the number of nodes ever allocated or -1 in case of error
8142465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
8143465a000b1080427bd62d89a925409b7db78616acDaniel Veillardint
8144465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpCtxtNbCons(xmlExpCtxtPtr ctxt) {
8145465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (ctxt == NULL)
8146465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(-1);
8147465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ctxt->nb_cons);
8148465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8149465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
815081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif /* LIBXML_EXPR_ENABLED */
81515d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#define bottom_xmlregexp
81525d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#include "elfgcchack.h"
81534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif /* LIBXML_REGEXP_ENABLED */
8154