xmlregexp.c revision 293416828e1467f877d9dd928f174dcf81b103bc
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) {
2098567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        if ((range1->type != XML_REGEXP_CHARVAL) ||
2099567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    (range1->end < range2->start) ||
2100567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    (range2->end < range1->start))
2101567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 1;
2102567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else
2103567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2104567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else if (range1->type == XML_REGEXP_CHARVAL) {
2105567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        int codepoint;
2106567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	int neg = 0;
2107567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2108567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	/*
2109567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * just check all codepoints in the range for acceptance,
2110567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * this is usually way cheaper since done only once at
2111567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * compilation than testing over and over at runtime or
2112567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * pushing too many states when evaluating.
2113567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 */
2114567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (((range1->neg == 0) && (range2->neg != 0)) ||
2115567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ((range1->neg != 0) && (range2->neg == 0)))
2116567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    neg = 1;
2117567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2118567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	for (codepoint = range1->start;codepoint <= range1->end ;codepoint++) {
2119567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = xmlRegCheckCharacterRange(range2->type, codepoint,
2120567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard					    0, range2->start, range2->end,
2121567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard					    range2->blockName);
2122567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (ret < 0)
2123567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	        return(-1);
2124567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (((neg == 1) && (ret == 0)) ||
2125567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	        ((neg == 0) && (ret == 1)))
2126567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		return(1);
2127567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2128567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	return(0);
2129567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else if ((range1->type == XML_REGEXP_BLOCK_NAME) ||
2130567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard               (range2->type == XML_REGEXP_BLOCK_NAME)) {
2131567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (range1->type == range2->type) {
2132567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = xmlStrEqual(range1->blockName, range2->blockName);
2133567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	} else {
2134567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /*
2135567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * comparing a block range with anything else is way
2136567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * too costly, and maintining the table is like too much
2137567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * memory too, so let's force the automata to save state
2138567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * here.
2139567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     */
2140567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    return(1);
2141567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2142567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else if ((range1->type < XML_REGEXP_LETTER) ||
2143567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard               (range2->type < XML_REGEXP_LETTER)) {
2144567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if ((range1->type == XML_REGEXP_ANYSPACE) &&
2145567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    (range2->type == XML_REGEXP_NOTSPACE))
2146567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2147567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else if ((range1->type == XML_REGEXP_INITNAME) &&
2148567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         (range2->type == XML_REGEXP_NOTINITNAME))
2149567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2150567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else if ((range1->type == XML_REGEXP_NAMECHAR) &&
2151567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         (range2->type == XML_REGEXP_NOTNAMECHAR))
2152567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2153567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else if ((range1->type == XML_REGEXP_DECIMAL) &&
2154567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         (range2->type == XML_REGEXP_NOTDECIMAL))
2155567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2156567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else if ((range1->type == XML_REGEXP_REALCHAR) &&
2157567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         (range2->type == XML_REGEXP_NOTREALCHAR))
2158567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2159567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	else {
2160567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /* same thing to limit complexity */
2161567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    return(1);
2162567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2163567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    } else {
2164567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        ret = 0;
2165567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        /* range1->type < range2->type here */
2166567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        switch (range1->type) {
2167567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_LETTER:
2168567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         /* all disjoint except in the subgroups */
2169567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_LETTER_UPPERCASE) ||
2170567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_LETTER_LOWERCASE) ||
2171567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_LETTER_TITLECASE) ||
2172567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_LETTER_MODIFIER) ||
2173567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_LETTER_OTHERS))
2174567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2175567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2176567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_MARK:
2177567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_MARK_NONSPACING) ||
2178567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_MARK_SPACECOMBINING) ||
2179567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_MARK_ENCLOSING))
2180567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2181567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2182567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_NUMBER:
2183567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_NUMBER_DECIMAL) ||
2184567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_NUMBER_LETTER) ||
2185567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_NUMBER_OTHERS))
2186567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2187567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2188567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_PUNCT:
2189567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_PUNCT_CONNECTOR) ||
2190567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_DASH) ||
2191567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_OPEN) ||
2192567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_CLOSE) ||
2193567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_INITQUOTE) ||
2194567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_FINQUOTE) ||
2195567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_PUNCT_OTHERS))
2196567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2197567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2198567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_SEPAR:
2199567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_SEPAR_SPACE) ||
2200567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SEPAR_LINE) ||
2201567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SEPAR_PARA))
2202567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2203567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2204567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_SYMBOL:
2205567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_SYMBOL_MATH) ||
2206567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SYMBOL_CURRENCY) ||
2207567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SYMBOL_MODIFIER) ||
2208567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_SYMBOL_OTHERS))
2209567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2210567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2211567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    case XML_REGEXP_OTHER:
2212567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type == XML_REGEXP_OTHER_CONTROL) ||
2213567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_OTHER_FORMAT) ||
2214567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type == XML_REGEXP_OTHER_PRIVATE))
2215567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 1;
2216567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 break;
2217567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard            default:
2218567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	         if ((range2->type >= XML_REGEXP_LETTER) &&
2219567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (range2->type < XML_REGEXP_BLOCK_NAME))
2220567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     ret = 0;
2221567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 else {
2222567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     /* safety net ! */
2223567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     return(1);
2224567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 }
2225567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2226567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
2227567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (((range1->neg == 0) && (range2->neg != 0)) ||
2228567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        ((range1->neg != 0) && (range2->neg == 0)))
2229567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	ret = !ret;
2230594e5dfb48ee6fbac1b64155839063648022fc57Daniel Veillard    return(ret);
2231567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard}
2232567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2233e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
2234fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * xmlFACompareAtomTypes:
2235fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * @type1:  an atom type
2236fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * @type2:  an atom type
2237fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard *
2238fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Compares two atoms type to check whether they intersect in some ways,
2239fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * this is used by xmlFACompareAtoms only
2240fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard *
2241fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Returns 1 if they may intersect and 0 otherwise
2242fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard */
2243fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillardstatic int
2244fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel VeillardxmlFACompareAtomTypes(xmlRegAtomType type1, xmlRegAtomType type2) {
2245fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if ((type1 == XML_REGEXP_EPSILON) ||
2246fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        (type1 == XML_REGEXP_CHARVAL) ||
2247fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type1 == XML_REGEXP_RANGES) ||
2248fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type1 == XML_REGEXP_SUBREG) ||
2249fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type1 == XML_REGEXP_STRING) ||
2250fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type1 == XML_REGEXP_ANYCHAR))
2251fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(1);
2252fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if ((type2 == XML_REGEXP_EPSILON) ||
2253fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        (type2 == XML_REGEXP_CHARVAL) ||
2254fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type2 == XML_REGEXP_RANGES) ||
2255fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type2 == XML_REGEXP_SUBREG) ||
2256fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type2 == XML_REGEXP_STRING) ||
2257fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	(type2 == XML_REGEXP_ANYCHAR))
2258fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(1);
2259fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2260fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (type1 == type2) return(1);
2261fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2262fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    /* simplify subsequent compares by making sure type1 < type2 */
2263fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (type1 > type2) {
2264fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        xmlRegAtomType tmp = type1;
2265fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	type1 = type2;
2266fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	type2 = tmp;
2267fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    }
2268fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    switch (type1) {
2269fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_ANYSPACE: /* \s */
2270fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a letter, number, mark, pontuation, symbol */
2271fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTSPACE) ||
2272fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		((type2 >= XML_REGEXP_LETTER) &&
2273fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_LETTER_OTHERS)) ||
2274fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_NUMBER) &&
2275fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_NUMBER_OTHERS)) ||
2276fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2277fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2278fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2279fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2280fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2281fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS))
2282fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ) return(0);
2283fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2284fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTSPACE: /* \S */
2285fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2286fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_INITNAME: /* \l */
2287fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a number, mark, separator, pontuation, symbol or other */
2288fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTINITNAME) ||
2289fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_NUMBER) &&
2290fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_NUMBER_OTHERS)) ||
2291fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2292fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2293fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SEPAR) &&
2294fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2295fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2296fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2297fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2298fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2299fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_OTHER) &&
2300fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_OTHER_NA))
2301fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		) return(0);
2302fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2303fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTINITNAME: /* \L */
2304fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2305fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NAMECHAR: /* \c */
2306fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a mark, separator, pontuation, symbol or other */
2307fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTNAMECHAR) ||
2308fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2309fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2310fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2311fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2312fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SEPAR) &&
2313fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2314fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2315fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2316fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_OTHER) &&
2317fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_OTHER_NA))
2318fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		) return(0);
2319fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2320fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTNAMECHAR: /* \C */
2321fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2322fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_DECIMAL: /* \d */
2323fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a letter, mark, separator, pontuation, symbol or other */
2324fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTDECIMAL) ||
2325fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        (type2 == XML_REGEXP_REALCHAR) ||
2326fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		((type2 >= XML_REGEXP_LETTER) &&
2327fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_LETTER_OTHERS)) ||
2328fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2329fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2330fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2331fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2332fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SEPAR) &&
2333fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2334fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2335fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2336fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_OTHER) &&
2337fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_OTHER_NA))
2338fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		)return(0);
2339fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2340fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTDECIMAL: /* \D */
2341fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2342fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_REALCHAR: /* \w */
2343fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* can't be a mark, separator, pontuation, symbol or other */
2344fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if ((type2 == XML_REGEXP_NOTDECIMAL) ||
2345fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_MARK) &&
2346fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_MARK_ENCLOSING)) ||
2347fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_PUNCT) &&
2348fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_PUNCT_OTHERS)) ||
2349fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SEPAR) &&
2350fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SEPAR_PARA)) ||
2351fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_SYMBOL) &&
2352fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_SYMBOL_OTHERS)) ||
2353fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ((type2 >= XML_REGEXP_OTHER) &&
2354fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		 (type2 <= XML_REGEXP_OTHER_NA))
2355fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		)return(0);
2356fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2357fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NOTREALCHAR: /* \W */
2358fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2359fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	/*
2360fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	 * at that point we know both type 1 and type2 are from
2361fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	 * character categories are ordered and are different,
2362fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	 * it becomes simple because this is a partition
2363fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	 */
2364fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER:
2365fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_LETTER_OTHERS)
2366fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2367fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2368fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_UPPERCASE:
2369fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_LOWERCASE:
2370fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_TITLECASE:
2371fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_MODIFIER:
2372fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_LETTER_OTHERS:
2373fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2374fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_MARK:
2375fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_MARK_ENCLOSING)
2376fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2377fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2378fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_MARK_NONSPACING:
2379fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_MARK_SPACECOMBINING:
2380fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_MARK_ENCLOSING:
2381fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2382fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NUMBER:
2383fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_NUMBER_OTHERS)
2384fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2385fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2386fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NUMBER_DECIMAL:
2387fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NUMBER_LETTER:
2388fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_NUMBER_OTHERS:
2389fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2390fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT:
2391fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_PUNCT_OTHERS)
2392fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2393fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2394fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_CONNECTOR:
2395fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_DASH:
2396fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_OPEN:
2397fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_CLOSE:
2398fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_INITQUOTE:
2399fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_FINQUOTE:
2400fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_PUNCT_OTHERS:
2401fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2402fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SEPAR:
2403fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_SEPAR_PARA)
2404fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2405fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2406fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SEPAR_SPACE:
2407fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SEPAR_LINE:
2408fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SEPAR_PARA:
2409fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2410fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL:
2411fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_SYMBOL_OTHERS)
2412fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2413fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2414fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL_MATH:
2415fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL_CURRENCY:
2416fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL_MODIFIER:
2417fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_SYMBOL_OTHERS:
2418fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2419fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER:
2420fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (type2 <= XML_REGEXP_OTHER_NA)
2421fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        return(1);
2422fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2423fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER_CONTROL:
2424fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER_FORMAT:
2425fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER_PRIVATE:
2426fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_OTHER_NA:
2427fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2428fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	default:
2429fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2430fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    }
2431fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    return(1);
2432fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard}
2433fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2434fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard/**
2435fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * xmlFAEqualAtoms:
2436fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * @atom1:  an atom
2437fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * @atom2:  an atom
24381ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * @deep: if not set only compare string pointers
2439fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard *
2440fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Compares two atoms to check whether they are the same exactly
2441fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * this is used to remove equivalent transitions
2442fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard *
2443fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * Returns 1 if same and 0 otherwise
2444fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard */
2445fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillardstatic int
24461ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel VeillardxmlFAEqualAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2, int deep) {
2447fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    int ret = 0;
2448fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2449fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (atom1 == atom2)
2450fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(1);
2451fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if ((atom1 == NULL) || (atom2 == NULL))
2452fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(0);
2453fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2454fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (atom1->type != atom2->type)
2455fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        return(0);
2456fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    switch (atom1->type) {
2457fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_EPSILON:
2458fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    ret = 0;
2459fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2460fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_STRING:
24611ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard            if (!deep)
24621ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                ret = (atom1->valuep == atom2->valuep);
24631ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard            else
24641ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                ret = xmlStrEqual((xmlChar *)atom1->valuep,
24651ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                                  (xmlChar *)atom2->valuep);
2466fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2467fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_CHARVAL:
2468fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    ret = (atom1->codepoint == atom2->codepoint);
2469fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2470fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	case XML_REGEXP_RANGES:
2471fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    /* too hard to do in the general case */
2472fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    ret = 0;
2473fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	default:
2474fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2475fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    }
2476fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    return(ret);
2477fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard}
2478fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2479fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard/**
2480e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * xmlFACompareAtoms:
2481e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @atom1:  an atom
2482e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @atom2:  an atom
24831ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * @deep: if not set only compare string pointers
2484e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2485567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard * Compares two atoms to check whether they intersect in some ways,
2486fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard * this is used by xmlFAComputesDeterminism and xmlFARecurseDeterminism only
2487e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2488e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Returns 1 if yes and 0 otherwise
2489e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
2490e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardstatic int
24911ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel VeillardxmlFACompareAtoms(xmlRegAtomPtr atom1, xmlRegAtomPtr atom2, int deep) {
2492fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    int ret = 1;
24939efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
2494e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if (atom1 == atom2)
2495e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(1);
2496e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if ((atom1 == NULL) || (atom2 == NULL))
2497e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(0);
2498e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
2499fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if ((atom1->type == XML_REGEXP_ANYCHAR) ||
2500fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        (atom2->type == XML_REGEXP_ANYCHAR))
2501fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	return(1);
2502fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard
2503fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (atom1->type > atom2->type) {
2504567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	xmlRegAtomPtr tmp;
2505567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	tmp = atom1;
2506567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	atom1 = atom2;
2507567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	atom2 = tmp;
2508fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    }
2509fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard    if (atom1->type != atom2->type) {
2510fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        ret = xmlFACompareAtomTypes(atom1->type, atom2->type);
2511fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	/* if they can't intersect at the type level break now */
2512fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	if (ret == 0)
2513fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    return(0);
2514567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
2515e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    switch (atom1->type) {
2516e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard        case XML_REGEXP_STRING:
25171ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard            if (!deep)
25181ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                ret = (atom1->valuep != atom2->valuep);
25191ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard            else
25201ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                ret = xmlRegStrEqualWildcard((xmlChar *)atom1->valuep,
25211ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                                             (xmlChar *)atom2->valuep);
25229efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	    break;
2523e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard        case XML_REGEXP_EPSILON:
2524567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    goto not_determinist;
2525e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard        case XML_REGEXP_CHARVAL:
2526567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (atom2->type == XML_REGEXP_CHARVAL) {
2527fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		ret = (atom1->codepoint == atom2->codepoint);
2528567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    } else {
2529fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	        ret = xmlRegCheckCharacter(atom2, atom1->codepoint);
2530fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		if (ret < 0)
2531fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard		    ret = 1;
2532fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    }
2533fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    break;
2534fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard        case XML_REGEXP_RANGES:
2535fc011b7fb895ed3b43f6c2e5b7a6fbfc078da349Daniel Veillard	    if (atom2->type == XML_REGEXP_RANGES) {
2536567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	        int i, j, res;
2537567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		xmlRegRangePtr r1, r2;
2538567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2539567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		/*
2540567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 * need to check that none of the ranges eventually matches
2541567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		 */
2542567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		for (i = 0;i < atom1->nbRanges;i++) {
2543567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    for (j = 0;j < atom2->nbRanges;j++) {
2544567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			r1 = atom1->ranges[i];
2545567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			r2 = atom2->ranges[j];
2546567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			res = xmlFACompareRanges(r1, r2);
2547567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			if (res == 1) {
2548567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			    ret = 1;
2549567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			    goto done;
2550567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			}
2551567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    }
2552567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		}
2553567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		ret = 0;
2554567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2555567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    break;
2556e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	default:
2557567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    goto not_determinist;
2558e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    }
2559567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillarddone:
25606e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    if (atom1->neg != atom2->neg) {
25619efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard        ret = !ret;
25626e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    }
2563567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    if (ret == 0)
2564567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard        return(0);
2565567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillardnot_determinist:
2566567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    return(1);
2567e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard}
2568e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
2569e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
2570e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * xmlFARecurseDeterminism:
2571e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @ctxt:  a regexp parser context
2572e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2573e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Check whether the associated regexp is determinist,
2574e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * should be called after xmlFAEliminateEpsilonTransitions()
2575e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2576e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
2577e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardstatic int
2578e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel VeillardxmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state,
2579e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	                 int to, xmlRegAtomPtr atom) {
2580e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int ret = 1;
2581567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    int res;
25825de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    int transnr, nbTrans;
2583e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    xmlRegTransPtr t1;
25841ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    int deep = 1;
2585e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
2586e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if (state == NULL)
2587e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(ret);
25881ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
25891ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    if (ctxt->flags & AM_AUTOMATA_RNG)
25901ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard        deep = 0;
25911ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
25925de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    /*
25935de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard     * don't recurse on transitions potentially added in the course of
25945de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard     * the elimination.
25955de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard     */
25965de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    nbTrans = state->nbTrans;
25975de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    for (transnr = 0;transnr < nbTrans;transnr++) {
2598e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	t1 = &(state->trans[transnr]);
2599e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	/*
2600e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	 * check transitions conflicting with the one looked at
2601e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	 */
2602e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	if (t1->atom == NULL) {
26030e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	    if (t1->to < 0)
2604e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		continue;
2605567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
2606e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		                           to, atom);
2607567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (res == 0) {
2608567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	        ret = 0;
2609aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		/* t1->nd = 1; */
2610567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2611e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    continue;
2612e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	}
2613e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	if (t1->to != to)
2614e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    continue;
26151ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard	if (xmlFACompareAtoms(t1->atom, atom, deep)) {
2616567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    ret = 0;
2617567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /* mark the transition as non-deterministic */
2618567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    t1->nd = 1;
2619567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2620e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    }
2621e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    return(ret);
2622e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard}
2623e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
2624e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
2625e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * xmlFAComputesDeterminism:
2626e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @ctxt:  a regexp parser context
2627e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2628e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Check whether the associated regexp is determinist,
2629e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * should be called after xmlFAEliminateEpsilonTransitions()
2630e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
2631e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
2632e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardstatic int
2633e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel VeillardxmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
2634e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int statenr, transnr;
2635e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    xmlRegStatePtr state;
2636567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    xmlRegTransPtr t1, t2, last;
2637e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int i;
2638e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int ret = 1;
26391ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    int deep = 1;
2640e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
26414402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard#ifdef DEBUG_REGEXP_GRAPH
26424402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard    printf("xmlFAComputesDeterminism\n");
26434402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard    xmlRegPrintCtxt(stdout, ctxt);
26444402ab420f68d9384bd6c2066c1676848d98d27cDaniel Veillard#endif
2645e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if (ctxt->determinist != -1)
2646e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(ctxt->determinist);
2647e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
26481ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    if (ctxt->flags & AM_AUTOMATA_RNG)
26491ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard        deep = 0;
26501ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
2651e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    /*
2652567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard     * First cleanup the automata removing cancelled transitions
2653e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard     */
2654e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
2655e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	state = ctxt->states[statenr];
2656e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	if (state == NULL)
2657e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    continue;
26584f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	if (state->nbTrans < 2)
26594f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	    continue;
2660e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	for (transnr = 0;transnr < state->nbTrans;transnr++) {
2661e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    t1 = &(state->trans[transnr]);
2662e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    /*
2663e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	     * Determinism checks in case of counted or all transitions
2664e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	     * will have to be handled separately
2665e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	     */
2666567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (t1->atom == NULL) {
2667aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		/* t1->nd = 1; */
2668e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		continue;
2669567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2670e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    if (t1->to == -1) /* eliminated */
2671e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		continue;
2672e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    for (i = 0;i < transnr;i++) {
2673e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		t2 = &(state->trans[i]);
2674e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		if (t2->to == -1) /* eliminated */
2675e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    continue;
2676e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		if (t2->atom != NULL) {
2677e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    if (t1->to == t2->to) {
26781ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                        /*
26791ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                         * Here we use deep because we want to keep the
26801ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                         * transitions which indicate a conflict
26811ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                         */
26821ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard			if (xmlFAEqualAtoms(t1->atom, t2->atom, deep) &&
268311e28e4dfb84804474a3d7a4bfb08bae8f00bc0aDaniel Veillard                            (t1->counter == t2->counter) &&
268411e28e4dfb84804474a3d7a4bfb08bae8f00bc0aDaniel Veillard                            (t1->count == t2->count))
2685ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack			    t2->to = -1; /* eliminated */
2686567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    }
2687567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		}
2688567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2689567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2690567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    }
2691567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2692567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    /*
2693567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard     * Check for all states that there aren't 2 transitions
2694567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard     * with the same atom and a different target.
2695567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard     */
2696567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
2697567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	state = ctxt->states[statenr];
2698567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (state == NULL)
2699567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    continue;
2700567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (state->nbTrans < 2)
2701567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    continue;
2702567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	last = NULL;
2703567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	for (transnr = 0;transnr < state->nbTrans;transnr++) {
2704567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    t1 = &(state->trans[transnr]);
2705567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /*
2706567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * Determinism checks in case of counted or all transitions
2707567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     * will have to be handled separately
2708567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	     */
2709567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (t1->atom == NULL) {
2710567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		continue;
2711567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    }
2712567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    if (t1->to == -1) /* eliminated */
2713567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		continue;
2714567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    for (i = 0;i < transnr;i++) {
2715567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		t2 = &(state->trans[i]);
2716567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		if (t2->to == -1) /* eliminated */
2717567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    continue;
2718567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		if (t2->atom != NULL) {
27191ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                    /*
27201ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                     * But here we don't use deep because we want to
27211ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                     * find transitions which indicate a conflict
27221ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard                     */
27231ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard		    if (xmlFACompareAtoms(t1->atom, t2->atom, 1)) {
2724567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			ret = 0;
2725567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			/* mark the transitions as non-deterministic ones */
2726567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			t1->nd = 1;
2727567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			t2->nd = 1;
2728567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			last = t1;
2729e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    }
2730e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		} else if (t1->to != -1) {
2731e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    /*
2732e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		     * do the closure in case of remaining specific
2733e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		     * epsilon transitions like choices or all
2734e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		     */
2735e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    ret = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to],
2736e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard						   t2->to, t2->atom);
2737567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    /* don't shortcut the computation so all non deterministic
2738567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		       transition get marked down
2739e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		    if (ret == 0)
2740aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard			return(0);
2741aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		     */
2742567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    if (ret == 0) {
2743567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			t1->nd = 1;
2744aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard			/* t2->nd = 1; */
2745567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard			last = t1;
2746567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    }
2747e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard		}
2748e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    }
2749567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    /* don't shortcut the computation so all non deterministic
2750567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	       transition get marked down
2751e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	    if (ret == 0)
2752567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		break; */
2753e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	}
2754567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2755567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	/*
2756567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * mark specifically the last non-deterministic transition
2757567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * from a state since there is no need to set-up rollback
2758567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 * from it
2759567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	 */
2760567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	if (last != NULL) {
2761567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    last->nd = 2;
2762567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	}
2763567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2764567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	/* don't shortcut the computation so all non deterministic
2765567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	   transition get marked down
2766e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	if (ret == 0)
2767567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    break; */
2768e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    }
2769567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard
2770e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    ctxt->determinist = ret;
2771e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    return(ret);
2772e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard}
2773e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
27744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
27754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
27764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *	Routines to check input against transition atoms		*
27774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
27784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
27794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
27804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
27814255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegCheckCharacterRange(xmlRegAtomType type, int codepoint, int neg,
27824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	                  int start, int end, const xmlChar *blockName) {
27834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret = 0;
27844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
27854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (type) {
27864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_STRING:
27874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SUBREG:
27884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_RANGES:
27894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_EPSILON:
27904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
27914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYCHAR:
27924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = ((codepoint != '\n') && (codepoint != '\r'));
27934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
27944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_CHARVAL:
27954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = ((codepoint >= start) && (codepoint <= end));
27964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
27974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTSPACE:
27984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
27994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYSPACE:
28004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = ((codepoint == '\n') || (codepoint == '\r') ||
28014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   (codepoint == '\t') || (codepoint == ' '));
28024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTINITNAME:
28044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_INITNAME:
2806871611bb0325095b30559ff1edc1fdaa2ad5fd2fWilliam M. Brack	    ret = (IS_LETTER(codepoint) ||
28074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   (codepoint == '_') || (codepoint == ':'));
28084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTNAMECHAR:
28104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NAMECHAR:
2812871611bb0325095b30559ff1edc1fdaa2ad5fd2fWilliam M. Brack	    ret = (IS_LETTER(codepoint) || IS_DIGIT(codepoint) ||
28134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   (codepoint == '.') || (codepoint == '-') ||
28144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		   (codepoint == '_') || (codepoint == ':') ||
2815871611bb0325095b30559ff1edc1fdaa2ad5fd2fWilliam M. Brack		   IS_COMBINING(codepoint) || IS_EXTENDER(codepoint));
28164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTDECIMAL:
28184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_DECIMAL:
28204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatNd(codepoint);
28214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_REALCHAR:
28234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    neg = !neg;
28244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTREALCHAR:
28254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatP(codepoint);
28264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 0)
28274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = xmlUCSIsCatZ(codepoint);
28284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 0)
28294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = xmlUCSIsCatC(codepoint);
28304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER:
28324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatL(codepoint);
28334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_UPPERCASE:
28354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLu(codepoint);
28364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_LOWERCASE:
28384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLl(codepoint);
28394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_TITLECASE:
28414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLt(codepoint);
28424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_MODIFIER:
28444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLm(codepoint);
28454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_OTHERS:
28474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatLo(codepoint);
28484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK:
28504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatM(codepoint);
28514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_NONSPACING:
28534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatMn(codepoint);
28544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_SPACECOMBINING:
28564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatMc(codepoint);
28574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_ENCLOSING:
28594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatMe(codepoint);
28604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER:
28624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatN(codepoint);
28634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_DECIMAL:
28654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatNd(codepoint);
28664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_LETTER:
28684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatNl(codepoint);
28694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_OTHERS:
28714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatNo(codepoint);
28724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT:
28744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatP(codepoint);
28754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CONNECTOR:
28774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPc(codepoint);
28784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_DASH:
28804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPd(codepoint);
28814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OPEN:
28834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPs(codepoint);
28844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CLOSE:
28864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPe(codepoint);
28874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_INITQUOTE:
28894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPi(codepoint);
28904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_FINQUOTE:
28924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPf(codepoint);
28934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OTHERS:
28954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatPo(codepoint);
28964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
28974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR:
28984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatZ(codepoint);
28994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_SPACE:
29014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatZs(codepoint);
29024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_LINE:
29044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatZl(codepoint);
29054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_PARA:
29074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatZp(codepoint);
29084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL:
29104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatS(codepoint);
29114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MATH:
29134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatSm(codepoint);
29144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_CURRENCY:
29164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatSc(codepoint);
29174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MODIFIER:
29194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatSk(codepoint);
29204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_OTHERS:
29224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatSo(codepoint);
29234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER:
29254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatC(codepoint);
29264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_CONTROL:
29284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatCc(codepoint);
29294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_FORMAT:
29314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatCf(codepoint);
29324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_PRIVATE:
29344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsCatCo(codepoint);
29354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_NA:
29374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* ret = xmlUCSIsCatCn(codepoint); */
29384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* Seems it doesn't exist anymore in recent Unicode releases */
29394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = 0;
29404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_BLOCK_NAME:
29424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlUCSIsBlock(codepoint, (const char *) blockName);
29434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
29444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
29454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (neg)
29464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(!ret);
29474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
29484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
29494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
29504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
29514255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint) {
29524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i, ret = 0;
29534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegRangePtr range;
29544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
2955871611bb0325095b30559ff1edc1fdaa2ad5fd2fWilliam M. Brack    if ((atom == NULL) || (!IS_CHAR(codepoint)))
29564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
29574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
29584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    switch (atom->type) {
29594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SUBREG:
29604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_EPSILON:
29614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
29624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_CHARVAL:
29634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard            return(codepoint == atom->codepoint);
29644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_RANGES: {
29654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int accept = 0;
2966f2a1283564df8ded1942b231c60c3a7ae4ff748aDaniel Veillard
29674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    for (i = 0;i < atom->nbRanges;i++) {
29684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		range = atom->ranges[i];
2969f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		if (range->neg == 2) {
29704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
29714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard						0, range->start, range->end,
29724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard						range->blockName);
29734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret != 0)
29744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			return(0); /* excluded char */
2975f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		} else if (range->neg) {
2976f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
2977f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard						0, range->start, range->end,
2978f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard						range->blockName);
2979f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		    if (ret == 0)
2980f2a1283564df8ded1942b231c60c3a7ae4ff748aDaniel Veillard		        accept = 1;
2981f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		    else
2982f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard		        return(0);
29834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		} else {
29844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    ret = xmlRegCheckCharacterRange(range->type, codepoint,
29854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard						0, range->start, range->end,
29864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard						range->blockName);
29874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret != 0)
29884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			accept = 1; /* might still be excluded */
29894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
29904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
29914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(accept);
29924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
29934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_STRING:
29944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    printf("TODO: XML_REGEXP_STRING\n");
29954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
29964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYCHAR:
29974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_ANYSPACE:
29984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTSPACE:
29994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_INITNAME:
30004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTINITNAME:
30014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NAMECHAR:
30024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTNAMECHAR:
30034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_DECIMAL:
30044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTDECIMAL:
30054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_REALCHAR:
30064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NOTREALCHAR:
30074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER:
30084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_UPPERCASE:
30094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_LOWERCASE:
30104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_TITLECASE:
30114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_MODIFIER:
30124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_LETTER_OTHERS:
30134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK:
30144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_NONSPACING:
30154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_SPACECOMBINING:
30164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_MARK_ENCLOSING:
30174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER:
30184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_DECIMAL:
30194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_LETTER:
30204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_NUMBER_OTHERS:
30214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT:
30224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CONNECTOR:
30234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_DASH:
30244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OPEN:
30254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_CLOSE:
30264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_INITQUOTE:
30274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_FINQUOTE:
30284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_PUNCT_OTHERS:
30294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR:
30304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_SPACE:
30314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_LINE:
30324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SEPAR_PARA:
30334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL:
30344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MATH:
30354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_CURRENCY:
30364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_MODIFIER:
30374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_SYMBOL_OTHERS:
30384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER:
30394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_CONTROL:
30404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_FORMAT:
30414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_PRIVATE:
30424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        case XML_REGEXP_OTHER_NA:
30434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	case XML_REGEXP_BLOCK_NAME:
30444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = xmlRegCheckCharacterRange(atom->type, codepoint, 0, 0, 0,
30454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                            (const xmlChar *)atom->valuep);
30464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (atom->neg)
30474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = !ret;
30484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
30494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
30504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
30514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
30524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
30534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
30544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
3055ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack *	Saving and restoring state of an execution context		*
30564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
30574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
30584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
30594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
30604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
30614255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegDebugExec(xmlRegExecCtxtPtr exec) {
30624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("state: %d:%d:idx %d", exec->state->no, exec->transno, exec->index);
30634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->inputStack != NULL) {
30644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int i;
30654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf(": ");
30664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0;(i < 3) && (i < exec->inputStackNr);i++)
30670e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	    printf("%s ", (const char *)
30680e05f4c2e0bf18930d4019426de31c9ae4d6411aDaniel Veillard	           exec->inputStack[exec->inputStackNr - (i + 1)].value);
30694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
30704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf(": %s", &(exec->inputString[exec->index]));
30714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
30724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("\n");
30734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
30744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
30754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
30764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
30774255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegExecSave(xmlRegExecCtxtPtr exec) {
30784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
30794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("saving ");
30804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno++;
30814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFARegDebugExec(exec);
30824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno--;
30834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
308494cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard#ifdef MAX_PUSH
308594cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    if (exec->nbPush > MAX_PUSH) {
308694cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard        return;
308794cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    }
308894cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    exec->nbPush++;
308994cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard#endif
30904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
30914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->maxRollbacks == 0) {
30924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->maxRollbacks = 4;
30934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->rollbacks = (xmlRegExecRollback *) xmlMalloc(exec->maxRollbacks *
30944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                             sizeof(xmlRegExecRollback));
30954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->rollbacks == NULL) {
3096ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "saving regexp");
30974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->maxRollbacks = 0;
30984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
30994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
31004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	memset(exec->rollbacks, 0,
31014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	       exec->maxRollbacks * sizeof(xmlRegExecRollback));
31024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (exec->nbRollbacks >= exec->maxRollbacks) {
31034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegExecRollback *tmp;
31044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int len = exec->maxRollbacks;
31054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->maxRollbacks *= 2;
31074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegExecRollback *) xmlRealloc(exec->rollbacks,
31084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->maxRollbacks * sizeof(xmlRegExecRollback));
31094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
3110ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "saving regexp");
31114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->maxRollbacks /= 2;
31124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
31134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
31144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->rollbacks = tmp;
31154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = &exec->rollbacks[len];
31164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	memset(tmp, 0, (exec->maxRollbacks - len) * sizeof(xmlRegExecRollback));
31174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
31184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks[exec->nbRollbacks].state = exec->state;
31194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks[exec->nbRollbacks].index = exec->index;
31204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks[exec->nbRollbacks].nextbranch = exec->transno + 1;
31214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->comp->nbCounters > 0) {
31224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
31234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->rollbacks[exec->nbRollbacks].counts = (int *)
31244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlMalloc(exec->comp->nbCounters * sizeof(int));
31254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
3126ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard		xmlRegexpErrMemory(NULL, "saving regexp");
31274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -5;
31284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return;
31294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
31304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
31314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	memcpy(exec->rollbacks[exec->nbRollbacks].counts, exec->counts,
31324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	       exec->comp->nbCounters * sizeof(int));
31334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
31344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->nbRollbacks++;
31354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
31364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
31384255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegExecRollBack(xmlRegExecCtxtPtr exec) {
31394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->nbRollbacks <= 0) {
31404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->status = -1;
31414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
31424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf("rollback failed on empty stack\n");
31434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
31444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
31454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
31464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->nbRollbacks--;
31474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->state = exec->rollbacks[exec->nbRollbacks].state;
31484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->index = exec->rollbacks[exec->nbRollbacks].index;
31494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno = exec->rollbacks[exec->nbRollbacks].nextbranch;
31504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->comp->nbCounters > 0) {
31514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->rollbacks[exec->nbRollbacks].counts == NULL) {
31524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    fprintf(stderr, "exec save: allocation failed");
31534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->status = -6;
31544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
31554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
31564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	memcpy(exec->counts, exec->rollbacks[exec->nbRollbacks].counts,
31574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	       exec->comp->nbCounters * sizeof(int));
31584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
31594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
31614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("restored ");
31624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFARegDebugExec(exec);
31634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
31644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
31654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
31674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
3168ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack *	Verifier, running an input against a compiled regexp		*
31694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
31704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
31714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
31734255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegExec(xmlRegexpPtr comp, const xmlChar *content) {
31744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegExecCtxt execval;
31754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegExecCtxtPtr exec = &execval;
3176567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard    int ret, codepoint = 0, len, deter;
31774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
31784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputString = content;
31794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->index = 0;
318094cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    exec->nbPush = 0;
31814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->determinist = 1;
31824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->maxRollbacks = 0;
31834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->nbRollbacks = 0;
31844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks = NULL;
31854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->status = 0;
31864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->comp = comp;
31874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->state = comp->states[0];
31884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno = 0;
31894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transcount = 0;
3190f2a1283564df8ded1942b231c60c3a7ae4ff748aDaniel Veillard    exec->inputStack = NULL;
3191f2a1283564df8ded1942b231c60c3a7ae4ff748aDaniel Veillard    exec->inputStackMax = 0;
31924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (comp->nbCounters > 0) {
31934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int));
3194ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	if (exec->counts == NULL) {
3195ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "running regexp");
31964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
3197ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	}
31984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        memset(exec->counts, 0, comp->nbCounters * sizeof(int));
31994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else
32004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->counts = NULL;
32014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((exec->status == 0) &&
32024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	   ((exec->inputString[exec->index] != 0) ||
3203ad55998f74ab7f89cc5ed454589fb8f528873a02Daniel Veillard	    ((exec->state != NULL) &&
3204ad55998f74ab7f89cc5ed454589fb8f528873a02Daniel Veillard	     (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
32054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegTransPtr trans;
32064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegAtomPtr atom;
32074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
32084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	/*
32090e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	 * If end of input on non-terminal state, rollback, however we may
32104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * still have epsilon like transition for counted transitions
32110e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	 * on counters, in that case don't break too early.  Additionally,
32120e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	 * if we are working on a range like "AB{0,2}", where B is not present,
32130e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	 * we don't want to break.
32144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 */
321511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard	len = 1;
32160e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	if ((exec->inputString[exec->index] == 0) && (exec->counts == NULL)) {
3217ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	    /*
3218ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	     * if there is a transition, we must check if
3219ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	     *  atom allows minOccurs of 0
3220ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	     */
3221ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack	    if (exec->transno < exec->state->nbTrans) {
32220e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	        trans = &exec->state->trans[exec->transno];
32230e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		if (trans->to >=0) {
32240e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    atom = trans->atom;
32250e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    if (!((atom->min == 0) && (atom->max > 0)))
32260e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		        goto rollback;
32270e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		}
32280e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	    } else
32290e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	        goto rollback;
32300e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	}
32314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
32324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->transcount = 0;
32334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (;exec->transno < exec->state->nbTrans;exec->transno++) {
32344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    trans = &exec->state->trans[exec->transno];
32354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->to < 0)
32364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		continue;
32374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom = trans->atom;
32384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = 0;
3239567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard	    deter = 1;
32404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->count >= 0) {
32414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		int count;
32424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlRegCounterPtr counter;
32434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
324411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		if (exec->counts == NULL) {
324511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    exec->status = -1;
324611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    goto error;
324711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		}
32484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		/*
32494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 * A counted transition.
32504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 */
32514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
32524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		count = exec->counts[trans->count];
32534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		counter = &exec->comp->counters[trans->count];
32544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
32554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("testing count %d: val %d, min %d, max %d\n",
32564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		       trans->count, count, counter->min,  counter->max);
32574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
32584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = ((count >= counter->min) && (count <= counter->max));
3259567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		if ((ret) && (counter->min != counter->max))
3260567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    deter = 0;
32614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (atom == NULL) {
32624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		fprintf(stderr, "epsilon transition left at runtime\n");
32634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -2;
32644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
32654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (exec->inputString[exec->index] != 0) {
32664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard                codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len);
32674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = xmlRegCheckCharacter(atom, codepoint);
32680e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		if ((ret == 1) && (atom->min >= 0) && (atom->max > 0)) {
32694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlRegStatePtr to = comp->states[trans->to];
32704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
32714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
32724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * this is a multiple input sequence
3273fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		     * If there is a counter associated increment it now.
3274fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		     * before potentially saving and rollback
3275c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		     * do not increment if the counter is already over the
3276c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		     * maximum limit in which case get to next transition
32774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
3278fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		    if (trans->counter >= 0) {
3279c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			xmlRegCounterPtr counter;
3280c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard
3281c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			if ((exec->counts == NULL) ||
3282c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			    (exec->comp == NULL) ||
3283c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			    (exec->comp->counters == NULL)) {
328411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    exec->status = -1;
328511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    goto error;
328611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			}
3287c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			counter = &exec->comp->counters[trans->counter];
3288c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			if (exec->counts[trans->counter] >= counter->max)
3289c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			    continue; /* for loop on transitions */
3290c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard
3291fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard#ifdef DEBUG_REGEXP_EXEC
3292fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard			printf("Increasing count %d\n", trans->counter);
3293fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard#endif
3294fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard			exec->counts[trans->counter]++;
3295fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		    }
32964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->state->nbTrans > exec->transno + 1) {
32974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			xmlFARegExecSave(exec);
32984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
32994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->transcount = 1;
33004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    do {
33014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
33024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * Try to progress as much as possible on the input
33034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
33044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount == atom->max) {
33054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
33064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
33074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->index += len;
33084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
33094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * End of input: stop here
33104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
33114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->inputString[exec->index] == 0) {
33124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->index -= len;
33134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
33144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
33154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount >= atom->min) {
33164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    int transno = exec->transno;
33174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlRegStatePtr state = exec->state;
33184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
33194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    /*
33204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     * The transition is acceptable save it
33214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     */
33224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = -1; /* trick */
33234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = to;
33244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlFARegExecSave(exec);
33254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = transno;
33264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = state;
33274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
33284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			codepoint = CUR_SCHAR(&(exec->inputString[exec->index]),
33294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard				              len);
33304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = xmlRegCheckCharacter(atom, codepoint);
33314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->transcount++;
33324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    } while (ret == 1);
33334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->transcount < atom->min)
33344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
33354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
33364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
33374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * If the last check failed but one transition was found
33384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * possible, rollback
33394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
33404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret < 0)
33414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
33424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret == 0) {
33434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			goto rollback;
33444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
3345fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		    if (trans->counter >= 0) {
334611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			if (exec->counts == NULL) {
334711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    exec->status = -1;
334811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    goto error;
334911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			}
3350fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard#ifdef DEBUG_REGEXP_EXEC
3351fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard			printf("Decreasing count %d\n", trans->counter);
3352fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard#endif
3353fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard			exec->counts[trans->counter]--;
3354fc6eca0d8196f200da4bf4083b0d9dbc7079460aDaniel Veillard		    }
33550e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		} else if ((ret == 0) && (atom->min == 0) && (atom->max > 0)) {
33560e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    /*
33570e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		     * we don't match on the codepoint, but minOccurs of 0
33580e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		     * says that's ok.  Setting len to 0 inhibits stepping
33590e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		     * over the codepoint.
33600e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		     */
33610e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    exec->transcount = 1;
33620e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    len = 0;
33630e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		    ret = 1;
33644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
33650e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	    } else if ((atom->min == 0) && (atom->max > 0)) {
33660e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack	        /* another spot to match when minOccurs is 0 */
33670e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		exec->transcount = 1;
33680e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		len = 0;
33690e00b28db65e0ad7f56e22874286682e90ffe9fbWilliam M. Brack		ret = 1;
33704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
33714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 1) {
3372567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		if ((trans->nd == 1) ||
3373567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		    ((trans->count >= 0) && (deter == 0) &&
3374567a45b5e931388acf850d56f937f1f66ff0f860Daniel Veillard		     (exec->state->nbTrans > exec->transno + 1))) {
3375aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
3376aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		    if (trans->nd == 1)
3377aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		        printf("Saving on nd transition atom %d for %c at %d\n",
3378aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard			       trans->atom->no, codepoint, exec->index);
3379aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		    else
3380aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard		        printf("Saving on counted transition count %d for %c at %d\n",
3381aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard			       trans->count, codepoint, exec->index);
3382aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#endif
33834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFARegExecSave(exec);
33844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
33854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->counter >= 0) {
3386c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    xmlRegCounterPtr counter;
3387c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard
3388c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard                    /* make sure we don't go over the counter maximum value */
3389c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    if ((exec->counts == NULL) ||
3390c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			(exec->comp == NULL) ||
3391c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			(exec->comp->counters == NULL)) {
3392c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			exec->status = -1;
339311ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			goto error;
339411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    }
3395c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    counter = &exec->comp->counters[trans->counter];
3396c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard		    if (exec->counts[trans->counter] >= counter->max)
3397c821e03c66873f74d1eda5c6b4a7b0bb9ca9105bDaniel Veillard			continue; /* for loop on transitions */
33984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
33994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Increasing count %d\n", trans->counter);
34004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
34014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->counts[trans->counter]++;
34024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
340310752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		if ((trans->count >= 0) &&
340410752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    (trans->count < REGEXP_ALL_COUNTER)) {
340511ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    if (exec->counts == NULL) {
340611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		        exec->status = -1;
340711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			goto error;
340811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    }
340910752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard#ifdef DEBUG_REGEXP_EXEC
341010752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    printf("resetting count %d on transition\n",
341110752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		           trans->count);
341210752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard#endif
341310752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    exec->counts[trans->count] = 0;
341410752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		}
34154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
34164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("entering state %d\n", trans->to);
34174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
34184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->state = comp->states[trans->to];
34194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->transno = 0;
34204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->atom != NULL) {
34214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->index += len;
34224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
34234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		goto progress;
34244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (ret < 0) {
34254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -4;
34264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
34274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
34284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
34294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((exec->transno != 0) || (exec->state->nbTrans == 0)) {
34304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardrollback:
34314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /*
34324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Failed to find a way out
34334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     */
34344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->determinist = 0;
3435aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
3436aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	    printf("rollback from state %d on %d:%c\n", exec->state->no,
3437aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard	           codepoint,codepoint);
3438aa62201290b6f3f3305f0fff504faf89c286a360Daniel Veillard#endif
34394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFARegExecRollBack(exec);
34404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
34414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardprogress:
34424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	continue;
34434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
344411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillarderror:
34454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->rollbacks != NULL) {
34464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->counts != NULL) {
34474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int i;
34484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
34494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    for (i = 0;i < exec->maxRollbacks;i++)
34504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (exec->rollbacks[i].counts != NULL)
34514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFree(exec->rollbacks[i].counts);
34524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
34534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->rollbacks);
34544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
34554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->counts != NULL)
34564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->counts);
34574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->status == 0)
34584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
345994cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    if (exec->status == -1) {
346094cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard	if (exec->nbPush > MAX_PUSH)
346194cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard	    return(-1);
34624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
346394cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    }
34644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(exec->status);
34654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
34664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
34674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
34684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
3469ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack *	Progressive interface to the verifier one atom at a time	*
34704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
34714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
34727bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#ifdef DEBUG_ERR
34737bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillardstatic void testerr(xmlRegExecCtxtPtr exec);
34747bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#endif
34754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
34764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
347701c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * xmlRegNewExecCtxt:
34784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @comp: a precompiled regular expression
34794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @callback: a callback function used for handling progresses in the
34804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *            automata matching phase
34814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @data: the context data associated to the callback in this context
34824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
34834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Build a context used for progressive evaluation of a regexp.
348401c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard *
348501c13b5be2d249ef66d86585adee87901bb8efa2Daniel Veillard * Returns the new context
34864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
34874255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegExecCtxtPtr
34884255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegNewExecCtxt(xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data) {
34894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegExecCtxtPtr exec;
34904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
34914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (comp == NULL)
34924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
3493a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if ((comp->compact == NULL) && (comp->states == NULL))
3494a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        return(NULL);
34954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt));
34964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec == NULL) {
3497ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	xmlRegexpErrMemory(NULL, "creating execution context");
34984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
34994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
35004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    memset(exec, 0, sizeof(xmlRegExecCtxt));
35014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputString = NULL;
35024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->index = 0;
35034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->determinist = 1;
35044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->maxRollbacks = 0;
35054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->nbRollbacks = 0;
35064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->rollbacks = NULL;
35074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->status = 0;
35084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->comp = comp;
350923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (comp->compact == NULL)
351023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	exec->state = comp->states[0];
35114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transno = 0;
35124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->transcount = 0;
35134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->callback = callback;
35144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->data = data;
35154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (comp->nbCounters > 0) {
35167bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        /*
35177bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	 * For error handling, exec->counts is allocated twice the size
35187bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	 * the second half is used to store the data in case of rollback
35197bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	 */
35207bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	exec->counts = (int *) xmlMalloc(comp->nbCounters * sizeof(int)
35217bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	                                 * 2);
35224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->counts == NULL) {
3523ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "creating execution context");
35244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFree(exec);
35254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(NULL);
35264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
35277bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        memset(exec->counts, 0, comp->nbCounters * sizeof(int) * 2);
35287bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	exec->errCounts = &exec->counts[comp->nbCounters];
35297bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    } else {
35304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->counts = NULL;
35317bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	exec->errCounts = NULL;
35327bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    }
35334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStackMax = 0;
35344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStackNr = 0;
35354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack = NULL;
35367bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    exec->errStateNo = -1;
35377bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    exec->errString = NULL;
353894cc103b8cfcfb040b5aad121d7fbd928f6a1336Daniel Veillard    exec->nbPush = 0;
35394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(exec);
35404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
35414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
35434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegFreeExecCtxt:
35444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @exec: a regular expression evaulation context
35454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
35464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free the structures associated to a regular expression evaulation context.
35474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
35484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
35494255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegFreeExecCtxt(xmlRegExecCtxtPtr exec) {
35504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec == NULL)
35514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
35524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->rollbacks != NULL) {
35544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->counts != NULL) {
35554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int i;
35564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    for (i = 0;i < exec->maxRollbacks;i++)
35584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (exec->rollbacks[i].counts != NULL)
35594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFree(exec->rollbacks[i].counts);
35604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
35614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->rollbacks);
35624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
35634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->counts != NULL)
35644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->counts);
35654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->inputStack != NULL) {
35664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int i;
35674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35683237023d6a8036dff817c3d46485ce6495d8ae21Daniel Veillard	for (i = 0;i < exec->inputStackNr;i++) {
35693237023d6a8036dff817c3d46485ce6495d8ae21Daniel Veillard	    if (exec->inputStack[i].value != NULL)
35703237023d6a8036dff817c3d46485ce6495d8ae21Daniel Veillard		xmlFree(exec->inputStack[i].value);
35713237023d6a8036dff817c3d46485ce6495d8ae21Daniel Veillard	}
35724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(exec->inputStack);
35734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
35747bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    if (exec->errString != NULL)
35757bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        xmlFree(exec->errString);
35764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(exec);
35774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
35784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
35804255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, const xmlChar *value,
35814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	                    void *data) {
35824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
35834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("saving value: %d:%s\n", exec->inputStackNr, value);
35844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
35854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->inputStackMax == 0) {
35864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->inputStackMax = 4;
35874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->inputStack = (xmlRegInputTokenPtr)
35884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken));
35894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (exec->inputStack == NULL) {
3590ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "pushing input string");
35914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->inputStackMax = 0;
35924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
35934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
35944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (exec->inputStackNr + 1 >= exec->inputStackMax) {
35954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegInputTokenPtr tmp;
35964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
35974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->inputStackMax *= 2;
35984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	tmp = (xmlRegInputTokenPtr) xmlRealloc(exec->inputStack,
35994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->inputStackMax * sizeof(xmlRegInputToken));
36004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (tmp == NULL) {
3601ff46a0443e6b999297e52c160b88536b8089ec56Daniel Veillard	    xmlRegexpErrMemory(NULL, "pushing input string");
36024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->inputStackMax /= 2;
36034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
36044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
36054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->inputStack = tmp;
36064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
36074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack[exec->inputStackNr].value = xmlStrdup(value);
36084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack[exec->inputStackNr].data = data;
36094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStackNr++;
36104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack[exec->inputStackNr].value = NULL;
36114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    exec->inputStack[exec->inputStackNr].data = NULL;
36124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
36134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
3614c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard/**
3615c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * xmlRegStrEqualWildcard:
3616c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * @expStr:  the string to be evaluated
3617c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * @valStr:  the validation string
3618c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard *
3619c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * Checks if both strings are equal or have the same content. "*"
3620c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * can be used as a wildcard in @valStr; "|" is used as a seperator of
3621c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * substrings in both @expStr and @valStr.
3622c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard *
3623c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * Returns 1 if the comparison is satisfied and the number of substrings
3624c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard * is equal, 0 otherwise.
3625c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard */
3626c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard
3627c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillardstatic int
3628c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel VeillardxmlRegStrEqualWildcard(const xmlChar *expStr, const xmlChar *valStr) {
3629c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    if (expStr == valStr) return(1);
3630c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    if (expStr == NULL) return(0);
3631c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    if (valStr == NULL) return(0);
3632c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    do {
3633c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	/*
3634c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	* Eval if we have a wildcard for the current item.
3635c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	*/
3636c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard        if (*expStr != *valStr) {
36374f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	    /* if one of them starts with a wildcard make valStr be it */
36384f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	    if (*valStr == '*') {
36394f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	        const xmlChar *tmp;
36404f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard
36414f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard		tmp = valStr;
36424f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard		valStr = expStr;
36434f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard		expStr = tmp;
36444f82c8a161404d1fe6ca9fe6edb404df00e14f11Daniel Veillard	    }
3645c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	    if ((*valStr != 0) && (*expStr != 0) && (*expStr++ == '*')) {
3646c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		do {
3647c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		    if (*valStr == XML_REG_STRING_SEPARATOR)
3648c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard			break;
3649c0e833f0024d46f50772620f24e6cf9d93748017Kasimier T. Buchcik		    valStr++;
3650c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		} while (*valStr != 0);
3651c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		continue;
3652c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	    } else
3653c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		return(0);
3654c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	}
3655c0e833f0024d46f50772620f24e6cf9d93748017Kasimier T. Buchcik	expStr++;
3656c0e833f0024d46f50772620f24e6cf9d93748017Kasimier T. Buchcik	valStr++;
3657c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    } while (*valStr != 0);
3658c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    if (*expStr != 0)
3659c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	return (0);
3660c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    else
3661c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	return (1);
3662c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard}
36634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
36644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
366523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * xmlRegCompactPushString:
366623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @exec: a regexp execution context
366723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @comp:  the precompiled exec with a compact table
366823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @value: a string token input
366923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @data: data associated to the token to reuse in callbacks
367023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *
367123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * Push one input token in the execution context
367223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *
367323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * Returns: 1 if the regexp reached a final state, 0 if non-final, and
367423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *     a negative value in case of error.
367523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard */
367623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillardstatic int
367723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel VeillardxmlRegCompactPushString(xmlRegExecCtxtPtr exec,
367823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	                xmlRegexpPtr comp,
367923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	                const xmlChar *value,
368023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	                void *data) {
368123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int state = exec->index;
368223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int i, target;
368323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
368423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if ((comp == NULL) || (comp->compact == NULL) || (comp->stringMap == NULL))
368523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(-1);
368623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
368723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (value == NULL) {
368823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	/*
368923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 * are we at a final state ?
369023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	 */
369123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	if (comp->compact[state * (comp->nbstrings + 1)] ==
369223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard            XML_REGEXP_FINAL_STATE)
369323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    return(1);
369423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(0);
369523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
369623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
369723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_PUSH
369823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    printf("value pushed: %s\n", value);
369923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
370023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
370123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    /*
3702ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack     * Examine all outside transitions from current state
370323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     */
370423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    for (i = 0;i < comp->nbstrings;i++) {
370523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
370623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	if ((target > 0) && (target <= comp->nbstates)) {
3707c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	    target--; /* to avoid 0 */
3708c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard	    if (xmlRegStrEqualWildcard(comp->stringMap[i], value)) {
3709c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		exec->index = target;
3710118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		if ((exec->callback != NULL) && (comp->transdata != NULL)) {
3711118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		    exec->callback(exec->data, value,
3712118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard			  comp->transdata[state * comp->nbstrings + i], data);
3713118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard		}
371423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_PUSH
371523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		printf("entering state %d\n", target);
371623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
371723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		if (comp->compact[target * (comp->nbstrings + 1)] ==
3718cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    XML_REGEXP_SINK_STATE)
3719cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    goto error;
3720cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard
3721cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		if (comp->compact[target * (comp->nbstrings + 1)] ==
372223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    XML_REGEXP_FINAL_STATE)
372323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		    return(1);
372423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard		return(0);
372523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    }
372623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	}
372723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
372823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    /*
372923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     * Failed to find an exit transition out from current state for the
373023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     * current token
373123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard     */
373223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#ifdef DEBUG_PUSH
373323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    printf("failed to find a transition for %s on state %d\n", value, state);
373423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard#endif
3735cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillarderror:
37367bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    if (exec->errString != NULL)
37377bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        xmlFree(exec->errString);
37387bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    exec->errString = xmlStrdup(value);
37397bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    exec->errStateNo = state;
374023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    exec->status = -1;
37417bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#ifdef DEBUG_ERR
37427bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    testerr(exec);
37437bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#endif
374423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    return(-1);
374523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard}
374623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
374723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard/**
37486e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * xmlRegExecPushStringInternal:
3749ea7751d53bf497e873dca39b2c305e300e2574f9Daniel Veillard * @exec: a regexp execution context or NULL to indicate the end
37504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @value: a string token input
37514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @data: data associated to the token to reuse in callbacks
37526e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * @compound: value was assembled from 2 strings
37534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
37544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Push one input token in the execution context
37554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
37564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns: 1 if the regexp reached a final state, 0 if non-final, and
37574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *     a negative value in case of error.
37584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
37596e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillardstatic int
37606e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel VeillardxmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, const xmlChar *value,
37616e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard	                     void *data, int compound) {
37624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegTransPtr trans;
37634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
37644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
37654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int final = 0;
37669070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard    int progress = 1;
37674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
37684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec == NULL)
37694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
377023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (exec->comp == NULL)
377123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(-1);
37724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->status != 0)
37734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(exec->status);
37744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
377523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (exec->comp->compact != NULL)
377623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(xmlRegCompactPushString(exec, exec->comp, value, data));
377723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
37784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (value == NULL) {
37794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        if (exec->state->type == XML_REGEXP_FINAL_STATE)
37804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(1);
37814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	final = 1;
37824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
37834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
37844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
37854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    printf("value pushed: %s\n", value);
37864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
37874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /*
37884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * If we have an active rollback stack push the new value there
37894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     * and get back to where we were left
37904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard     */
37914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((value != NULL) && (exec->inputStackNr > 0)) {
37924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFARegExecSaveInputString(exec, value, data);
37934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	value = exec->inputStack[exec->index].value;
37944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	data = exec->inputStack[exec->index].data;
37954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
37964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	printf("value loaded: %s\n", value);
37974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
37984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
37994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((exec->status == 0) &&
38014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	   ((value != NULL) ||
38024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ((final == 1) &&
38034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     (exec->state->type != XML_REGEXP_FINAL_STATE)))) {
38044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	/*
38064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * End of input on non-terminal state, rollback, however we may
38074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * still have epsilon like transition for counted transitions
38084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * on counters, in that case don't break too early.
38094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 */
3810b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	if ((value == NULL) && (exec->counts == NULL))
38114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    goto rollback;
38124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->transcount = 0;
38144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (;exec->transno < exec->state->nbTrans;exec->transno++) {
38154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    trans = &exec->state->trans[exec->transno];
38164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->to < 0)
38174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		continue;
38184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom = trans->atom;
38194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = 0;
3820441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
3821441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		int i;
3822441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		int count;
3823441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		xmlRegTransPtr t;
3824441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		xmlRegCounterPtr counter;
3825441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard
3826441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		ret = 0;
3827441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard
3828441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard#ifdef DEBUG_PUSH
3829441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		printf("testing all lax %d\n", trans->count);
3830441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard#endif
3831441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		/*
3832441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		 * Check all counted transitions from the current state
3833441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		 */
3834441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		if ((value == NULL) && (final)) {
3835441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    ret = 1;
3836441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		} else if (value != NULL) {
3837441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    for (i = 0;i < exec->state->nbTrans;i++) {
3838441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			t = &exec->state->trans[i];
3839441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			if ((t->counter < 0) || (t == trans))
3840441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    continue;
3841441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			counter = &exec->comp->counters[t->counter];
3842441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			count = exec->counts[t->counter];
3843441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			if ((count < counter->max) &&
3844441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		            (t->atom != NULL) &&
3845441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    (xmlStrEqual(value, t->atom->valuep))) {
3846441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    ret = 0;
3847441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    break;
3848441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			}
3849441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			if ((count >= counter->min) &&
3850441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    (count < counter->max) &&
385111ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard			    (t->atom != NULL) &&
3852441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    (xmlStrEqual(value, t->atom->valuep))) {
3853441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    ret = 1;
3854441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			    break;
3855441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			}
3856441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    }
3857441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		}
3858441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard	    } else if (trans->count == REGEXP_ALL_COUNTER) {
38598a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		int i;
38608a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		int count;
38618a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		xmlRegTransPtr t;
38628a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		xmlRegCounterPtr counter;
38638a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard
38648a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		ret = 1;
38658a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard
38668a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard#ifdef DEBUG_PUSH
38678a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		printf("testing all %d\n", trans->count);
38688a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard#endif
38698a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		/*
38708a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		 * Check all counted transitions from the current state
38718a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		 */
38728a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		for (i = 0;i < exec->state->nbTrans;i++) {
38738a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard                    t = &exec->state->trans[i];
38748a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		    if ((t->counter < 0) || (t == trans))
38758a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard			continue;
38768a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard                    counter = &exec->comp->counters[t->counter];
38778a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		    count = exec->counts[t->counter];
38788a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		    if ((count < counter->min) || (count > counter->max)) {
38798a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard			ret = 0;
38808a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard			break;
38818a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		    }
38828a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard		}
38838a001f62c195f956c7655df7464ff753b28bc957Daniel Veillard	    } else if (trans->count >= 0) {
38844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		int count;
38854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlRegCounterPtr counter;
38864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		/*
38884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 * A counted transition.
38894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 */
38904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
38914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		count = exec->counts[trans->count];
38924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		counter = &exec->comp->counters[trans->count];
38934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
38944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("testing count %d: val %d, min %d, max %d\n",
38954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		       trans->count, count, counter->min,  counter->max);
38964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
38974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = ((count >= counter->min) && (count <= counter->max));
38984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (atom == NULL) {
38994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		fprintf(stderr, "epsilon transition left at runtime\n");
39004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -2;
39014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
39024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (value != NULL) {
3903c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard		ret = xmlRegStrEqualWildcard(atom->valuep, value);
39046e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard		if (atom->neg) {
39059efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard		    ret = !ret;
39066e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard		    if (!compound)
39076e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard		        ret = 0;
39086e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard		}
3909441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		if ((ret == 1) && (trans->counter >= 0)) {
3910441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    xmlRegCounterPtr counter;
3911441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    int count;
3912441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard
3913441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    count = exec->counts[trans->counter];
3914441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    counter = &exec->comp->counters[trans->counter];
3915441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		    if (count >= counter->max)
3916441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard			ret = 0;
3917441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		}
3918441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard
39194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if ((ret == 1) && (atom->min > 0) && (atom->max > 0)) {
39204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlRegStatePtr to = exec->comp->states[trans->to];
39214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
39224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
39234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * this is a multiple input sequence
39244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
39254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->state->nbTrans > exec->transno + 1) {
39264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->inputStackNr <= 0) {
39274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlFARegExecSaveInputString(exec, value, data);
39284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
39294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			xmlFARegExecSave(exec);
39304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
39314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->transcount = 1;
39324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    do {
39334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
39344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * Try to progress as much as possible on the input
39354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
39364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount == atom->max) {
39374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
39384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
39394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->index++;
39404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			value = exec->inputStack[exec->index].value;
39414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			data = exec->inputStack[exec->index].data;
39424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
39434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			printf("value loaded: %s\n", value);
39444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
39454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
39464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
39474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * End of input: stop here
39484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
39494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (value == NULL) {
39504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->index --;
39514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
39524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
39534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount >= atom->min) {
39544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    int transno = exec->transno;
39554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlRegStatePtr state = exec->state;
39564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
39574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    /*
39584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     * The transition is acceptable save it
39594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     */
39604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = -1; /* trick */
39614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = to;
39624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    if (exec->inputStackNr <= 0) {
39634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard				xmlFARegExecSaveInputString(exec, value, data);
39644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    }
39654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlFARegExecSave(exec);
39664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = transno;
39674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = state;
39684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
39694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = xmlStrEqual(value, atom->valuep);
39704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->transcount++;
39714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    } while (ret == 1);
39724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->transcount < atom->min)
39734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
39744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
39754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
39764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * If the last check failed but one transition was found
39774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * possible, rollback
39784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
39794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret < 0)
39804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
39814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret == 0) {
39824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			goto rollback;
39834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
39844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
39854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
39864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 1) {
39879887395b556af391306245b52487c215337c4054William M. Brack		if ((exec->callback != NULL) && (atom != NULL) &&
39889887395b556af391306245b52487c215337c4054William M. Brack			(data != NULL)) {
39894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->callback(exec->data, atom->valuep,
39904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			           atom->data, data);
39914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
39924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (exec->state->nbTrans > exec->transno + 1) {
39934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->inputStackNr <= 0) {
39944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			xmlFARegExecSaveInputString(exec, value, data);
39954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
39964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFARegExecSave(exec);
39974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
39984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->counter >= 0) {
39994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Increasing count %d\n", trans->counter);
40014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->counts[trans->counter]++;
40034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
400410752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		if ((trans->count >= 0) &&
400510752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    (trans->count < REGEXP_ALL_COUNTER)) {
400610752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard#ifdef DEBUG_REGEXP_EXEC
400710752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    printf("resetting count %d on transition\n",
400810752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		           trans->count);
400910752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard#endif
401010752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		    exec->counts[trans->count] = 0;
401110752284e3e3401725a2ab49fee1367201eeff6aDaniel Veillard		}
40124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("entering state %d\n", trans->to);
40144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
4015cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                if ((exec->comp->states[trans->to] != NULL) &&
4016cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (exec->comp->states[trans->to]->type ==
4017cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     XML_REGEXP_SINK_STATE)) {
4018cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    /*
4019cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     * entering a sink state, save the current state as error
4020cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     * state.
4021cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     */
4022cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    if (exec->errString != NULL)
4023cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard			xmlFree(exec->errString);
4024cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    exec->errString = xmlStrdup(value);
4025cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    exec->errState = exec->state;
4026cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    memcpy(exec->errCounts, exec->counts,
4027cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard			   exec->comp->nbCounters * sizeof(int));
4028cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		}
40294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->state = exec->comp->states[trans->to];
40304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->transno = 0;
40314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->atom != NULL) {
40324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->inputStack != NULL) {
40334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->index++;
40344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->index < exec->inputStackNr) {
40354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    value = exec->inputStack[exec->index].value;
40364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    data = exec->inputStack[exec->index].data;
40374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    printf("value loaded: %s\n", value);
40394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			} else {
40414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    value = NULL;
40424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    data = NULL;
40434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    printf("end of input\n");
40454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
40474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    } else {
40484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			value = NULL;
40494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			data = NULL;
40504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			printf("end of input\n");
40524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
40544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
40554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		goto progress;
40564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (ret < 0) {
40574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -4;
40584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
40594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
40604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
40614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((exec->transno != 0) || (exec->state->nbTrans == 0)) {
40624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardrollback:
40639070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard            /*
4064cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     * if we didn't yet rollback on the current input
4065cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     * store the current state as the error state.
40669070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard	     */
4067cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if ((progress) && (exec->state != NULL) &&
4068cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        (exec->state->type != XML_REGEXP_SINK_STATE)) {
40699070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard	        progress = 0;
40709070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		if (exec->errString != NULL)
40719070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		    xmlFree(exec->errString);
40729070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		exec->errString = xmlStrdup(value);
40739070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		exec->errState = exec->state;
40749070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		memcpy(exec->errCounts, exec->counts,
40759070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard		       exec->comp->nbCounters * sizeof(int));
40769070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard	    }
40779070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard
40784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /*
40794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Failed to find a way out
40804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     */
40814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->determinist = 0;
40824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFARegExecRollBack(exec);
40834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (exec->status == 0) {
40844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		value = exec->inputStack[exec->index].value;
40854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		data = exec->inputStack[exec->index].data;
40864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_PUSH
40874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("value loaded: %s\n", value);
40884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
40894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
40904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
40919070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard	continue;
40924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardprogress:
40939070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard        progress = 1;
40944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	continue;
40954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
40964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->status == 0) {
40974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        return(exec->state->type == XML_REGEXP_FINAL_STATE);
40984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
40997bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#ifdef DEBUG_ERR
41009070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard    if (exec->status < 0) {
41017bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	testerr(exec);
41027bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    }
41039070015b406518e7215f04c0c17eb3cac3e9849bDaniel Veillard#endif
41044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(exec->status);
41054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
41064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
410752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard/**
41086e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * xmlRegExecPushString:
41096e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * @exec: a regexp execution context or NULL to indicate the end
41106e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * @value: a string token input
41116e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * @data: data associated to the token to reuse in callbacks
41126e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard *
41136e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * Push one input token in the execution context
41146e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard *
41156e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * Returns: 1 if the regexp reached a final state, 0 if non-final, and
41166e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard *     a negative value in case of error.
41176e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard */
41186e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillardint
41196e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel VeillardxmlRegExecPushString(xmlRegExecCtxtPtr exec, const xmlChar *value,
41206e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard	             void *data) {
41216e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    return(xmlRegExecPushStringInternal(exec, value, data, 0));
41226e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard}
41236e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard
41246e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard/**
412552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * xmlRegExecPushString2:
412652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @exec: a regexp execution context or NULL to indicate the end
412752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @value: the first string token input
412852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @value2: the second string token input
412952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @data: data associated to the token to reuse in callbacks
413052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *
413152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * Push one input token in the execution context
413252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *
413352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * Returns: 1 if the regexp reached a final state, 0 if non-final, and
413452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *     a negative value in case of error.
413552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard */
413652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillardint
413752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel VeillardxmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value,
413852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard                      const xmlChar *value2, void *data) {
413952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    xmlChar buf[150];
414052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    int lenn, lenp, ret;
414152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    xmlChar *str;
414252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
414352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (exec == NULL)
414452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(-1);
414552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (exec->comp == NULL)
414652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(-1);
414752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (exec->status != 0)
414852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(exec->status);
414952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
415052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (value2 == NULL)
415152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard        return(xmlRegExecPushString(exec, value, data));
415252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
415352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    lenn = strlen((char *) value2);
415452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    lenp = strlen((char *) value);
415552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
415652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (150 < lenn + lenp + 2) {
41573c908dca479ed50dca24b8593bca90e40dbde6b8Daniel Veillard	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
415852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	if (str == NULL) {
415952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	    exec->status = -1;
416052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	    return(-1);
416152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	}
416252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    } else {
416352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	str = buf;
416452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    }
416552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    memcpy(&str[0], value, lenp);
4166c0826a7709eddbf10ade02f0ce80e5d077ac05f6Daniel Veillard    str[lenp] = XML_REG_STRING_SEPARATOR;
416752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    memcpy(&str[lenp + 1], value2, lenn);
416852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    str[lenn + lenp + 1] = 0;
416952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
417052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (exec->comp->compact != NULL)
417152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	ret = xmlRegCompactPushString(exec, exec->comp, str, data);
417252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    else
41736e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard        ret = xmlRegExecPushStringInternal(exec, str, data, 1);
417452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
417552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (str != buf)
41760b1ff14bd0c7c50f8cdce96478615570e1435c4fDaniel Veillard        xmlFree(str);
417752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    return(ret);
417852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard}
417952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
41807bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard/**
418177005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard * xmlRegExecGetValues:
4182fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @exec: a regexp execution context
4183fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @err: error extraction or normal one
41847bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard * @nbval: pointer to the number of accepted values IN/OUT
4185cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard * @nbneg: return number of negative transitions
41867bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard * @values: pointer to the array of acceptable values
4187fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @terminal: return value if this was a terminal state
41887bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard *
4189fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Extract informations from the regexp execution, internal routine to
4190fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * implement xmlRegExecNextValues() and xmlRegExecErrInfo()
41917bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard *
41927bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard * Returns: 0 in case of success or -1 in case of error.
41937bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard */
4194fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillardstatic int
4195fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel VeillardxmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
4196cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                    int *nbval, int *nbneg,
4197cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    xmlChar **values, int *terminal) {
41987bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    int maxval;
4199cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    int nb = 0;
42007bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
4201cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    if ((exec == NULL) || (nbval == NULL) || (nbneg == NULL) ||
4202cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard        (values == NULL) || (*nbval <= 0))
42037bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        return(-1);
4204fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
42057bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    maxval = *nbval;
42067bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    *nbval = 0;
4207cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    *nbneg = 0;
42087bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    if ((exec->comp != NULL) && (exec->comp->compact != NULL)) {
42097bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        xmlRegexpPtr comp;
42107bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	int target, i, state;
42117bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
42127bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        comp = exec->comp;
4213fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
4214fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	if (err) {
4215fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (exec->errStateNo == -1) return(-1);
4216fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    state = exec->errStateNo;
4217fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	} else {
4218fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    state = exec->index;
4219fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	}
4220fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	if (terminal != NULL) {
4221fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (comp->compact[state * (comp->nbstrings + 1)] ==
4222fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	        XML_REGEXP_FINAL_STATE)
4223fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		*terminal = 1;
4224fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    else
4225fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		*terminal = 0;
4226fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	}
4227cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	for (i = 0;(i < comp->nbstrings) && (nb < maxval);i++) {
42287bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
4229cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if ((target > 0) && (target <= comp->nbstates) &&
4230cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        (comp->compact[(target - 1) * (comp->nbstrings + 1)] !=
4231cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		 XML_REGEXP_SINK_STATE)) {
4232cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        values[nb++] = comp->stringMap[i];
42337bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		(*nbval)++;
42347bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    }
42357bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	}
4236cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	for (i = 0;(i < comp->nbstrings) && (nb < maxval);i++) {
4237cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    target = comp->compact[state * (comp->nbstrings + 1) + i + 1];
4238cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if ((target > 0) && (target <= comp->nbstates) &&
4239cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        (comp->compact[(target - 1) * (comp->nbstrings + 1)] ==
4240cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		 XML_REGEXP_SINK_STATE)) {
4241cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        values[nb++] = comp->stringMap[i];
4242cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		(*nbneg)++;
4243cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    }
4244cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	}
42457bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    } else {
42467bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard        int transno;
42477bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	xmlRegTransPtr trans;
42487bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	xmlRegAtomPtr atom;
4249fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	xmlRegStatePtr state;
4250fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
4251fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	if (terminal != NULL) {
4252fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (exec->state->type == XML_REGEXP_FINAL_STATE)
4253fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		*terminal = 1;
4254fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    else
4255fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		*terminal = 0;
4256fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	}
42577bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
4258fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	if (err) {
4259fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (exec->errState == NULL) return(-1);
4260fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    state = exec->errState;
4261fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	} else {
4262fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    if (exec->state == NULL) return(-1);
4263fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    state = exec->state;
4264fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	}
42657bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	for (transno = 0;
4266cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     (transno < state->nbTrans) && (nb < maxval);
42677bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	     transno++) {
4268fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    trans = &state->trans[transno];
42697bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    if (trans->to < 0)
42707bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		continue;
42717bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    atom = trans->atom;
42727bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    if ((atom == NULL) || (atom->valuep == NULL))
42737bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		continue;
42747bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
4275cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        /* this should not be reached but ... */
42767bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	        TODO;
42777bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    } else if (trans->count == REGEXP_ALL_COUNTER) {
4278cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        /* this should not be reached but ... */
42797bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	        TODO;
42807bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    } else if (trans->counter >= 0) {
428111ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		xmlRegCounterPtr counter = NULL;
42827bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		int count;
42837bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
4284fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		if (err)
4285fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		    count = exec->errCounts[trans->counter];
4286fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		else
4287fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard		    count = exec->counts[trans->counter];
428811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		if (exec->comp != NULL)
428911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		    counter = &exec->comp->counters[trans->counter];
429011ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard		if ((counter == NULL) || (count < counter->max)) {
429177005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    if (atom->neg)
429277005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep2;
429377005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    else
429477005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep;
42957bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		    (*nbval)++;
42967bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard		}
42977bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    } else {
4298cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                if ((exec->comp->states[trans->to] != NULL) &&
4299cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (exec->comp->states[trans->to]->type !=
4300cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     XML_REGEXP_SINK_STATE)) {
430177005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    if (atom->neg)
430277005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep2;
430377005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    else
430477005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep;
4305cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (*nbval)++;
4306cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		}
4307cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    }
4308cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	}
4309cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	for (transno = 0;
4310cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     (transno < state->nbTrans) && (nb < maxval);
4311cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	     transno++) {
4312cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    trans = &state->trans[transno];
4313cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if (trans->to < 0)
4314cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		continue;
4315cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    atom = trans->atom;
4316cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if ((atom == NULL) || (atom->valuep == NULL))
4317cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		continue;
4318cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    if (trans->count == REGEXP_ALL_LAX_COUNTER) {
4319cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        continue;
4320cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    } else if (trans->count == REGEXP_ALL_COUNTER) {
4321cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        continue;
4322cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    } else if (trans->counter >= 0) {
4323cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	        continue;
4324cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard	    } else {
4325cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                if ((exec->comp->states[trans->to] != NULL) &&
4326cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (exec->comp->states[trans->to]->type ==
4327cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		     XML_REGEXP_SINK_STATE)) {
432877005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    if (atom->neg)
432977005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep2;
433077005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard		    else
433177005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard			values[nb++] = (xmlChar *) atom->valuep;
4332cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		    (*nbneg)++;
4333cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard		}
43347bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	    }
43357bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard	}
43367bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    }
43377bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    return(0);
43387bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard}
43397bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
4340fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard/**
4341fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * xmlRegExecNextValues:
4342fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @exec: a regexp execution context
4343fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @nbval: pointer to the number of accepted values IN/OUT
4344cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard * @nbneg: return number of negative transitions
4345fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @values: pointer to the array of acceptable values
4346fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @terminal: return value if this was a terminal state
4347fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard *
4348fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Extract informations from the regexp execution,
4349fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * the parameter @values must point to an array of @nbval string pointers
4350fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * on return nbval will contain the number of possible strings in that
4351fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * state and the @values array will be updated with them. The string values
4352fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * returned will be freed with the @exec context and don't need to be
4353fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * deallocated.
4354fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard *
4355fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Returns: 0 in case of success or -1 in case of error.
4356fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard */
4357fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillardint
4358cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel VeillardxmlRegExecNextValues(xmlRegExecCtxtPtr exec, int *nbval, int *nbneg,
4359cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                     xmlChar **values, int *terminal) {
4360cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    return(xmlRegExecGetValues(exec, 0, nbval, nbneg, values, terminal));
4361fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard}
4362fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
4363fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard/**
4364fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * xmlRegExecErrInfo:
4365fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @exec: a regexp execution context generating an error
4366fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @string: return value for the error string
4367fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @nbval: pointer to the number of accepted values IN/OUT
4368cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard * @nbneg: return number of negative transitions
4369fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @values: pointer to the array of acceptable values
4370fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @terminal: return value if this was a terminal state
4371fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard *
4372fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Extract error informations from the regexp execution, the parameter
4373fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * @string will be updated with the value pushed and not accepted,
4374fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * the parameter @values must point to an array of @nbval string pointers
4375fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * on return nbval will contain the number of possible strings in that
4376fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * state and the @values array will be updated with them. The string values
4377fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * returned will be freed with the @exec context and don't need to be
4378fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * deallocated.
4379fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard *
4380fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard * Returns: 0 in case of success or -1 in case of error.
4381fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard */
4382fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillardint
4383fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel VeillardxmlRegExecErrInfo(xmlRegExecCtxtPtr exec, const xmlChar **string,
4384cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard                  int *nbval, int *nbneg, xmlChar **values, int *terminal) {
4385fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard    if (exec == NULL)
4386fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard        return(-1);
4387fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard    if (string != NULL) {
4388fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard        if (exec->status != 0)
4389fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    *string = exec->errString;
4390fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	else
4391fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard	    *string = NULL;
4392fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard    }
4393cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    return(xmlRegExecGetValues(exec, 1, nbval, nbneg, values, terminal));
4394fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard}
4395fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard
43967bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#ifdef DEBUG_ERR
43977bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillardstatic void testerr(xmlRegExecCtxtPtr exec) {
43987bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    const xmlChar *string;
4399cee2b3a5f124e19db46109132c22e1b8faec1c87Daniel Veillard    xmlChar *values[5];
44007bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard    int nb = 5;
4401cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    int nbneg;
4402fc0b6f6adac16ea1bf2ca3bfe935e67d9e9fb974Daniel Veillard    int terminal;
4403cc026dc6b069f38e8295bd4115e0620f4ede32adDaniel Veillard    xmlRegExecErrInfo(exec, &string, &nb, &nbneg, &values[0], &terminal);
44047bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard}
44057bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard#endif
44067bd8b4b817db9f3bda399acdb9e5d9919d257e89Daniel Veillard
44074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#if 0
44084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
44094255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
44104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegTransPtr trans;
44114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
44124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
44134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int codepoint, len;
44144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec == NULL)
44164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
44174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (exec->status != 0)
44184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(exec->status);
44194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((exec->status == 0) &&
44214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	   ((exec->inputString[exec->index] != 0) ||
44224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    (exec->state->type != XML_REGEXP_FINAL_STATE))) {
44234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	/*
44254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * End of input on non-terminal state, rollback, however we may
44264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * still have epsilon like transition for counted transitions
44274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 * on counters, in that case don't break too early.
44284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	 */
44294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((exec->inputString[exec->index] == 0) && (exec->counts == NULL))
44304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    goto rollback;
44314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	exec->transcount = 0;
44334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (;exec->transno < exec->state->nbTrans;exec->transno++) {
44344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    trans = &exec->state->trans[exec->transno];
44354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->to < 0)
44364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		continue;
44374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    atom = trans->atom;
44384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ret = 0;
44394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (trans->count >= 0) {
44404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		int count;
44414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		xmlRegCounterPtr counter;
44424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		/*
44444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 * A counted transition.
44454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		 */
44464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		count = exec->counts[trans->count];
44484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		counter = &exec->comp->counters[trans->count];
44494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
44504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("testing count %d: val %d, min %d, max %d\n",
44514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		       trans->count, count, counter->min,  counter->max);
44524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
44534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = ((count >= counter->min) && (count <= counter->max));
44544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (atom == NULL) {
44554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		fprintf(stderr, "epsilon transition left at runtime\n");
44564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -2;
44574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
44584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (exec->inputString[exec->index] != 0) {
44594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard                codepoint = CUR_SCHAR(&(exec->inputString[exec->index]), len);
44604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ret = xmlRegCheckCharacter(atom, codepoint);
44614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if ((ret == 1) && (atom->min > 0) && (atom->max > 0)) {
44624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlRegStatePtr to = exec->comp->states[trans->to];
44634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
44654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * this is a multiple input sequence
44664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
44674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->state->nbTrans > exec->transno + 1) {
44684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			xmlFARegExecSave(exec);
44694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
44704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->transcount = 1;
44714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    do {
44724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
44734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * Try to progress as much as possible on the input
44744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
44754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount == atom->max) {
44764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
44774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
44784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->index += len;
44794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			/*
44804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 * End of input: stop here
44814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 */
44824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->inputString[exec->index] == 0) {
44834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->index -= len;
44844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    break;
44854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
44864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			if (exec->transcount >= atom->min) {
44874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    int transno = exec->transno;
44884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlRegStatePtr state = exec->state;
44894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
44904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    /*
44914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     * The transition is acceptable save it
44924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			     */
44934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = -1; /* trick */
44944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = to;
44954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    xmlFARegExecSave(exec);
44964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->transno = transno;
44974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			    exec->state = state;
44984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			}
44994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			codepoint = CUR_SCHAR(&(exec->inputString[exec->index]),
45004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard				              len);
45014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = xmlRegCheckCharacter(atom, codepoint);
45024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			exec->transcount++;
45034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    } while (ret == 1);
45044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (exec->transcount < atom->min)
45054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
45064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    /*
45084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * If the last check failed but one transition was found
45094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     * possible, rollback
45104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		     */
45114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret < 0)
45124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			ret = 0;
45134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    if (ret == 0) {
45144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			goto rollback;
45154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    }
45164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
45174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
45184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (ret == 1) {
45194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (exec->state->nbTrans > exec->transno + 1) {
45204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    xmlFARegExecSave(exec);
45214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
452254eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		/*
452354eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		 * restart count for expressions like this ((abc){2})*
452454eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		 */
452554eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		if (trans->count >= 0) {
452654eb0243c442292953b4a3df39568735039ebc82Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
452754eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		    printf("Reset count %d\n", trans->count);
452854eb0243c442292953b4a3df39568735039ebc82Daniel Veillard#endif
452954eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		    exec->counts[trans->count] = 0;
453054eb0243c442292953b4a3df39568735039ebc82Daniel Veillard		}
45314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->counter >= 0) {
45324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
45334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    printf("Increasing count %d\n", trans->counter);
45344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
45354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->counts[trans->counter]++;
45364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
45374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef DEBUG_REGEXP_EXEC
45384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		printf("entering state %d\n", trans->to);
45394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
45404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->state = exec->comp->states[trans->to];
45414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->transno = 0;
45424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		if (trans->atom != NULL) {
45434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		    exec->index += len;
45444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		}
45454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		goto progress;
45464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else if (ret < 0) {
45474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		exec->status = -4;
45484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
45494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
45504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
45514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if ((exec->transno != 0) || (exec->state->nbTrans == 0)) {
45524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardrollback:
45534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /*
45544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     * Failed to find a way out
45554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	     */
45564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    exec->determinist = 0;
45574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFARegExecRollBack(exec);
45584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
45594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardprogress:
45604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	continue;
45614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
45624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
45634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif
45644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
45654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
4566ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack *	Parser for the Schemas Datatype Regular Expressions		*
45674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *	http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#regexs	*
45684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
45694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
45704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
45724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAIsChar:
4573441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
45744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
45754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [10]   Char   ::=   [^.\?*+()|#x5B#x5D]
45764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
45774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
45784255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAIsChar(xmlRegParserCtxtPtr ctxt) {
45794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int cur;
45804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int len;
45814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR_SCHAR(ctxt->cur, len);
45834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((cur == '.') || (cur == '\\') || (cur == '?') ||
45844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == '*') || (cur == '+') || (cur == '(') ||
45854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == ')') || (cur == '|') || (cur == 0x5B) ||
45864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == 0x5D) || (cur == 0))
45874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
45884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(cur);
45894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
45904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
45914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
45924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharProp:
4593441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
45944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
45954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [27]   charProp   ::=   IsCategory | IsBlock
45964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [28]   IsCategory ::= Letters | Marks | Numbers | Punctuation |
45974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *                       Separators | Symbols | Others
45984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [29]   Letters   ::=   'L' [ultmo]?
45994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [30]   Marks   ::=   'M' [nce]?
46004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [31]   Numbers   ::=   'N' [dlo]?
46014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [32]   Punctuation   ::=   'P' [cdseifo]?
46024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [33]   Separators   ::=   'Z' [slp]?
46034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [34]   Symbols   ::=   'S' [mcko]?
46044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [35]   Others   ::=   'C' [cfon]?
46054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [36]   IsBlock   ::=   'Is' [a-zA-Z0-9#x2D]+
46064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
46074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
46084255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
46094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int cur;
4610779af00750fa86045e94422287d67a2cf5723f65William M. Brack    xmlRegAtomType type = (xmlRegAtomType) 0;
46114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlChar *blockName = NULL;
46124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
46134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
46144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == 'L') {
46154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
46164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
46174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'u') {
46184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_UPPERCASE;
46204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'l') {
46214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_LOWERCASE;
46234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 't') {
46244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_TITLECASE;
46264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'm') {
46274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_MODIFIER;
46294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
46304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER_OTHERS;
46324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
46334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_LETTER;
46344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
46354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'M') {
46364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
46374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
46384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'n') {
46394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* nonspacing */
46414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_MARK_NONSPACING;
46424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'c') {
46434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* spacing combining */
46454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_MARK_SPACECOMBINING;
46464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'e') {
46474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* enclosing */
46494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_MARK_ENCLOSING;
46504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
46514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all marks */
46524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_MARK;
46534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
46544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'N') {
46554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
46564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
46574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'd') {
46584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* digital */
46604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_NUMBER_DECIMAL;
46614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'l') {
46624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* letter */
46644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_NUMBER_LETTER;
46654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
46664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* other */
46684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_NUMBER_OTHERS;
46694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
46704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all numbers */
46714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_NUMBER;
46724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
46734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'P') {
46744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
46754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
46764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'c') {
46774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* connector */
46794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_CONNECTOR;
46804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'd') {
46814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* dash */
46834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_DASH;
46844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 's') {
46854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* open */
46874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_OPEN;
46884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'e') {
46894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* close */
46914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_CLOSE;
46924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'i') {
46934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* initial quote */
46954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_INITQUOTE;
46964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'f') {
46974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
46984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* final quote */
46994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_FINQUOTE;
47004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
47014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* other */
47034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT_OTHERS;
47044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
47054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all punctuation */
47064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_PUNCT;
47074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'Z') {
47094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 's') {
47124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* space */
47144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SEPAR_SPACE;
47154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'l') {
47164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* line */
47184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SEPAR_LINE;
47194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'p') {
47204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* paragraph */
47224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SEPAR_PARA;
47234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
47244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all separators */
47254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SEPAR;
47264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'S') {
47284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'm') {
47314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL_MATH;
47334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* math */
47344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'c') {
47354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL_CURRENCY;
47374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* currency */
47384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'k') {
47394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL_MODIFIER;
47414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* modifiers */
47424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
47434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL_OTHERS;
47454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* other */
47464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
47474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all symbols */
47484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_SYMBOL;
47494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'C') {
47514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur == 'c') {
47544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* control */
47564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER_CONTROL;
47574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'f') {
47584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* format */
47604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER_FORMAT;
47614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'o') {
47624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* private use */
47644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER_PRIVATE;
47654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (cur == 'n') {
47664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* not assigned */
47684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER_NA;
47694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
47704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    /* all others */
47714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    type = XML_REGEXP_OTHER;
47724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'I') {
47744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	const xmlChar *start;
47754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur != 's') {
47784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("IsXXXX expected");
47794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
47804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
47824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	start = ctxt->cur;
47834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
47844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (((cur >= 'a') && (cur <= 'z')) ||
47854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ((cur >= 'A') && (cur <= 'Z')) ||
47864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ((cur >= '0') && (cur <= '9')) ||
47874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    (cur == 0x2D)) {
47884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
47894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    cur = CUR;
47904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    while (((cur >= 'a') && (cur <= 'z')) ||
47914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		((cur >= 'A') && (cur <= 'Z')) ||
47924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		((cur >= '0') && (cur <= '9')) ||
47934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		(cur == 0x2D)) {
47944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		NEXT;
47954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		cur = CUR;
47964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
47974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
47984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	type = XML_REGEXP_BLOCK_NAME;
47994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	blockName = xmlStrndup(start, ctxt->cur - start);
48004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
48014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("Unknown char property");
48024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
48034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
48044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->atom == NULL) {
48054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = xmlRegNewAtom(ctxt, type);
48064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom != NULL)
48074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom->valuep = blockName;
48084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (ctxt->atom->type == XML_REGEXP_RANGES) {
48094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
48104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		           type, 0, 0, blockName);
48114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
48124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
48134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
48144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
48154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharClassEsc:
4816441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
48174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
48184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [23] charClassEsc ::= ( SingleCharEsc | MultiCharEsc | catEsc | complEsc )
48194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [24] SingleCharEsc ::= '\' [nrt\|.?*+(){}#x2D#x5B#x5D#x5E]
48204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [25] catEsc   ::=   '\p{' charProp '}'
48214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [26] complEsc ::=   '\P{' charProp '}'
48224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [37] MultiCharEsc ::= '.' | ('\' [sSiIcCdDwW])
48234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
48244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
48254255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) {
48264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int cur;
48274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
48284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR == '.') {
48294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL) {
48304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_ANYCHAR);
48314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
48324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
48334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			       XML_REGEXP_ANYCHAR, 0, 0, NULL);
48344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
48374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
48384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR != '\\') {
48394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("Escaped sequence: expecting \\");
48404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
48414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
48424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    NEXT;
48434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
48444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == 'p') {
48454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR != '{') {
48474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Expecting '{'");
48484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
48494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharProp(ctxt);
48524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR != '}') {
48534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Expecting '}'");
48544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
48554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (cur == 'P') {
48584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR != '{') {
48604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Expecting '{'");
48614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
48624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharProp(ctxt);
48654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom->neg = 1;
48664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR != '}') {
48674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Expecting '}'");
48684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
48694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((cur == 'n') || (cur == 'r') || (cur == 't') || (cur == '\\') ||
48724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == '|') || (cur == '.') || (cur == '?') || (cur == '*') ||
48734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == '+') || (cur == '(') || (cur == ')') || (cur == '{') ||
48744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == '}') || (cur == 0x2D) || (cur == 0x5B) || (cur == 0x5D) ||
48754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == 0x5E)) {
48764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL) {
48774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL);
487899c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	    if (ctxt->atom != NULL) {
487999c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	        switch (cur) {
488099c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		    case 'n':
488199c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		        ctxt->atom->codepoint = '\n';
488299c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard			break;
488399c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		    case 'r':
488499c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		        ctxt->atom->codepoint = '\r';
488599c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard			break;
488699c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		    case 't':
488799c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		        ctxt->atom->codepoint = '\t';
488899c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard			break;
488999c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		    default:
489099c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard			ctxt->atom->codepoint = cur;
489199c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard		}
489299c394d9c50efdaca1d4c437cf22c9c160ed9c65Daniel Veillard	    }
48934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
48944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
48954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			       XML_REGEXP_CHARVAL, cur, cur, NULL);
48964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
48974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
48984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((cur == 's') || (cur == 'S') || (cur == 'i') || (cur == 'I') ||
48994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == 'c') || (cur == 'C') || (cur == 'd') || (cur == 'D') ||
49004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	(cur == 'w') || (cur == 'W')) {
4901b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	xmlRegAtomType type = XML_REGEXP_ANYSPACE;
49024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
49034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	switch (cur) {
49044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 's':
49054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_ANYSPACE;
49064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'S':
49084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTSPACE;
49094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'i':
49114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_INITNAME;
49124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'I':
49144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTINITNAME;
49154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'c':
49174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NAMECHAR;
49184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'C':
49204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTNAMECHAR;
49214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'd':
49234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_DECIMAL;
49244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'D':
49264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTDECIMAL;
49274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'w':
49294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_REALCHAR;
49304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'W':
49324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		type = XML_REGEXP_NOTREALCHAR;
49334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
49344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
49354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
49364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL) {
49374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom = xmlRegNewAtom(ctxt, type);
49384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (ctxt->atom->type == XML_REGEXP_RANGES) {
49394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
49404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			       type, 0, 0, NULL);
49414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
4942cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard    } else {
4943cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard	ERROR("Wrong escape sequence, misuse of character '\\'");
49444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
49454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
49464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
49474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
49484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharRange:
4949441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
49504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
49514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [17]   charRange   ::=     seRange | XmlCharRef | XmlCharIncDash
49524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [18]   seRange   ::=   charOrEsc '-' charOrEsc
49534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [20]   charOrEsc   ::=   XmlChar | SingleCharEsc
49544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [21]   XmlChar   ::=   [^\#x2D#x5B#x5D]
49554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [22]   XmlCharIncDash   ::=   [^\#x5B#x5D]
49564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
49574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
49584255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharRange(xmlRegParserCtxtPtr ctxt) {
4959dc99df936c74b6ced82904086544fec365d1f219William M. Brack    int cur, len;
49604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int start = -1;
49614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int end = -1;
49624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
4963777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard    if (CUR == '\0') {
4964777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard        ERROR("Expecting ']'");
4965777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard	return;
4966777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard    }
4967777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard
49684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
49694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == '\\') {
49704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
49714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
49724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	switch (cur) {
49734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'n': start = 0xA; break;
49744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'r': start = 0xD; break;
49754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 't': start = 0x9; break;
49764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '\\': case '|': case '.': case '-': case '^': case '?':
49774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '*': case '+': case '{': case '}': case '(': case ')':
49784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '[': case ']':
49794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		start = cur; break;
49804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    default:
49814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ERROR("Invalid escape value");
49824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return;
49834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
49844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	end = start;
4985dc99df936c74b6ced82904086544fec365d1f219William M. Brack        len = 1;
49864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((cur != 0x5B) && (cur != 0x5D)) {
4987dc99df936c74b6ced82904086544fec365d1f219William M. Brack        end = start = CUR_SCHAR(ctxt->cur, len);
49884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
49894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("Expecting a char range");
49904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
49914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
4992a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack    /*
4993a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack     * Since we are "inside" a range, we can assume ctxt->cur is past
4994a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack     * the start of ctxt->string, and PREV should be safe
4995a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack     */
4996a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack    if ((start == '-') && (NXT(1) != ']') && (PREV != '[') && (PREV != '^')) {
4997a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack	NEXTL(len);
49984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
49994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5000a9cbf28361410926c82ae47a2c9d1a22795976c1William M. Brack    NEXTL(len);
50014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
500210f1ef4ce875d6affb467f33ab653cd8072e5888William M. Brack    if ((cur != '-') || (NXT(1) == ']')) {
50034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
50044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		              XML_REGEXP_CHARVAL, start, end, NULL);
50054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
50064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
50074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    NEXT;
50084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
50094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == '\\') {
50104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
50114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = CUR;
50124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	switch (cur) {
50134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'n': end = 0xA; break;
50144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 'r': end = 0xD; break;
50154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case 't': end = 0x9; break;
50164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '\\': case '|': case '.': case '-': case '^': case '?':
50174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '*': case '+': case '{': case '}': case '(': case ')':
50184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    case '[': case ']':
50194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		end = cur; break;
50204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    default:
50214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ERROR("Invalid escape value");
50224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		return;
50234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
5024dc99df936c74b6ced82904086544fec365d1f219William M. Brack        len = 1;
50254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((cur != 0x5B) && (cur != 0x5D)) {
5026dc99df936c74b6ced82904086544fec365d1f219William M. Brack        end = CUR_SCHAR(ctxt->cur, len);
50274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
50284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("Expecting the end of a char range");
50294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
50304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5031dc99df936c74b6ced82904086544fec365d1f219William M. Brack    NEXTL(len);
50324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* TODO check that the values are acceptable character ranges for XML */
50334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (end < start) {
50344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("End of range is before start of range");
50354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
50364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard        xmlRegAtomAddRange(ctxt, ctxt->atom, ctxt->neg,
50374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		           XML_REGEXP_CHARVAL, start, end, NULL);
50384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
50394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return;
50404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
50414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
50424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
50434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParsePosCharGroup:
5044441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
50454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
50464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [14]   posCharGroup ::= ( charRange | charClassEsc  )+
50474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
50484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
50494255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) {
50504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    do {
5051041b687e93cc4d5806b902ed3b445a47669dc2adDaniel Veillard	if (CUR == '\\') {
50524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParseCharClassEsc(ctxt);
50534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
50544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParseCharRange(ctxt);
50554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
50564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } while ((CUR != ']') && (CUR != '^') && (CUR != '-') &&
5057777737ea020106db4d376f2d8b3992198892f29aDaniel Veillard             (CUR != 0) && (ctxt->error == 0));
50584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
50594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
50604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
50614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharGroup:
5062441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
50634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
50644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [13]   charGroup    ::= posCharGroup | negCharGroup | charClassSub
50654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [15]   negCharGroup ::= '^' posCharGroup
50664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [16]   charClassSub ::= ( posCharGroup | negCharGroup ) '-' charClassExpr
50674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [12]   charClassExpr ::= '[' charGroup ']'
50684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
50694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
50704255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharGroup(xmlRegParserCtxtPtr ctxt) {
50714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int n = ctxt->neg;
50724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((CUR != ']') && (ctxt->error == 0)) {
50734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == '^') {
50744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    int neg = ctxt->neg;
50754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
50764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
50774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->neg = !ctxt->neg;
50784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParsePosCharGroup(ctxt);
50794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->neg = neg;
508010f1ef4ce875d6affb467f33ab653cd8072e5888William M. Brack	} else if ((CUR == '-') && (NXT(1) == '[')) {
5081f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard	    int neg = ctxt->neg;
5082f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard	    ctxt->neg = 2;
508310f1ef4ce875d6affb467f33ab653cd8072e5888William M. Brack	    NEXT;	/* eat the '-' */
508410f1ef4ce875d6affb467f33ab653cd8072e5888William M. Brack	    NEXT;	/* eat the '[' */
50854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParseCharGroup(ctxt);
50864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (CUR == ']') {
50874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		NEXT;
50884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    } else {
50894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ERROR("charClassExpr: ']' expected");
50904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		break;
50914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    }
5092f8b9de32543a23c932a392362d4e4a6704c2c953Daniel Veillard	    ctxt->neg = neg;
50934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    break;
50944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else if (CUR != ']') {
50954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlFAParsePosCharGroup(ctxt);
50964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
50974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
50984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->neg = n;
50994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
51004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
51024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseCharClass:
5103441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
51044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
51054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [11]   charClass   ::=     charClassEsc | charClassExpr
51064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [12]   charClassExpr   ::=   '[' charGroup ']'
51074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
51084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
51094255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseCharClass(xmlRegParserCtxtPtr ctxt) {
51104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR == '[') {
51114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
51124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_RANGES);
51134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL)
51144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return;
51154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharGroup(ctxt);
51164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == ']') {
51174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
51184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
51194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("xmlFAParseCharClass: ']' expected");
51204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
51214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else {
51224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharClassEsc(ctxt);
51234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
51254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
51274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseQuantExact:
5128441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
51294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
51304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [8]   QuantExact   ::=   [0-9]+
5131a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard *
5132a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard * Returns 0 if success or -1 in case of error
51334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
51344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
51354255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
51364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret = 0;
51374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ok = 0;
51384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((CUR >= '0') && (CUR <= '9')) {
51404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ret = ret * 10 + (CUR - '0');
51414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ok = 1;
51424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
51434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ok != 1) {
51454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
51464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
51484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
51494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
51514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseQuantifier:
5152441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
51534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
51544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [4]   quantifier   ::=   [?*+] | ( '{' quantity '}' )
51554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [5]   quantity   ::=   quantRange | quantMin | QuantExact
51564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [6]   quantRange   ::=   QuantExact ',' QuantExact
51574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [7]   quantMin   ::=   QuantExact ','
51584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [8]   QuantExact   ::=   [0-9]+
51594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
51604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
51614255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseQuantifier(xmlRegParserCtxtPtr ctxt) {
51624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int cur;
51634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    cur = CUR;
51654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((cur == '?') || (cur == '*') || (cur == '+')) {
51664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom != NULL) {
51674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    if (cur == '?')
51684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ctxt->atom->quant = XML_REGEXP_QUANT_OPT;
51694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    else if (cur == '*')
51704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ctxt->atom->quant = XML_REGEXP_QUANT_MULT;
51714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    else if (cur == '+')
51724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		ctxt->atom->quant = XML_REGEXP_QUANT_PLUS;
51734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
51744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
51754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
51764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
51774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (cur == '{') {
51784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	int min = 0, max = 0;
51794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
51804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
51814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	cur = xmlFAParseQuantExact(ctxt);
51824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (cur >= 0)
51834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    min = cur;
51844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == ',') {
51854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
5186ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	    if (CUR == '}')
5187ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	        max = INT_MAX;
5188ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	    else {
5189ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	        cur = xmlFAParseQuantExact(ctxt);
5190ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	        if (cur >= 0)
5191ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard		    max = cur;
5192ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard		else {
5193ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard		    ERROR("Improper quantifier");
5194ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard		}
5195ebe48c60cc941881718222e69fabf604fe23e43dDaniel Veillard	    }
51964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
51974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == '}') {
51984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
51994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
52004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("Unterminated quantifier");
52014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
52024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (max == 0)
52034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    max = min;
52044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom != NULL) {
52054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom->quant = XML_REGEXP_QUANT_RANGE;
52064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom->min = min;
52074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom->max = max;
52084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
52094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
52104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
52114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
52124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
52134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
52154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseAtom:
5216441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
52174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
52184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [9]   atom   ::=   Char | charClass | ( '(' regExp ')' )
52194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
52204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
52214255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseAtom(xmlRegParserCtxtPtr ctxt) {
52224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int codepoint, len;
52234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    codepoint = xmlFAIsChar(ctxt);
52254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (codepoint > 0) {
52264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_CHARVAL);
52274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL)
52284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
52294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	codepoint = CUR_SCHAR(ctxt->cur, len);
52304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom->codepoint = codepoint;
52314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXTL(len);
52324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
52334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (CUR == '|') {
52344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
52354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (CUR == 0) {
52364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
52374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (CUR == ')') {
52384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
52394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if (CUR == '(') {
524076d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	xmlRegStatePtr start, oldend, start0;
52414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
524376d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	/*
524476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	 * this extra Epsilon transition is needed if we count with 0 allowed
524576d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	 * unfortunately this can't be known at that point
524676d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	 */
524776d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	xmlFAGenerateEpsilonTransition(ctxt, ctxt->state, NULL);
524876d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	start0 = ctxt->state;
52494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAGenerateEpsilonTransition(ctxt, ctxt->state, NULL);
52504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	start = ctxt->state;
52514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	oldend = ctxt->end;
52524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->end = NULL;
52534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = NULL;
52544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseRegExp(ctxt, 0);
52554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (CUR == ')') {
52564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    NEXT;
52574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	} else {
52584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ERROR("xmlFAParseAtom: expecting ')'");
52594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
52604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = xmlRegNewAtom(ctxt, XML_REGEXP_SUBREG);
52614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ctxt->atom == NULL)
52624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    return(-1);
52634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom->start = start;
526476d59b6d6ff8284ee6ed69ee4118e7da935d5e57Daniel Veillard	ctxt->atom->start0 = start0;
52654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom->stop = ctxt->state;
52664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->end = oldend;
52674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
52684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    } else if ((CUR == '[') || (CUR == '\\') || (CUR == '.')) {
52694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAParseCharClass(ctxt);
52704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(1);
52714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
52724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
52734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
52744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
52764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParsePiece:
5277441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
52784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
52794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [3]   piece   ::=   atom quantifier?
52804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
52814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic int
52824255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParsePiece(xmlRegParserCtxtPtr ctxt) {
52834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
52844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->atom = NULL;
52864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlFAParseAtom(ctxt);
52874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret == 0)
52884255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(0);
52894255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->atom == NULL) {
52904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("internal: no atom generated");
52914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
52924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAParseQuantifier(ctxt);
52934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(1);
52944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
52954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
52964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
52974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseBranch:
5298441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
529954eb0243c442292953b4a3df39568735039ebc82Daniel Veillard * @to: optional target to the end of the branch
530054eb0243c442292953b4a3df39568735039ebc82Daniel Veillard *
530154eb0243c442292953b4a3df39568735039ebc82Daniel Veillard * @to is used to optimize by removing duplicate path in automata
530254eb0243c442292953b4a3df39568735039ebc82Daniel Veillard * in expressions like (a|b)(c|d)
53034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
53044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [2]   branch   ::=   piece*
53054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
5306a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillardstatic int
530754eb0243c442292953b4a3df39568735039ebc82Daniel VeillardxmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr to) {
53084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePtr previous;
53094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int ret;
53104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    previous = ctxt->state;
53124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlFAParsePiece(ctxt);
53134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ret != 0) {
531454eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	if (xmlFAGenerateTransitions(ctxt, previous,
531554eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	        (CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0)
53162cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	    return(-1);
53172cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	previous = ctxt->state;
53184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->atom = NULL;
53194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
53204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((ret != 0) && (ctxt->error == 0)) {
53214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ret = xmlFAParsePiece(ctxt);
53224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	if (ret != 0) {
532354eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	    if (xmlFAGenerateTransitions(ctxt, previous,
532454eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	            (CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0)
5325a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard		    return(-1);
53264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    previous = ctxt->state;
53274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    ctxt->atom = NULL;
53284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	}
53294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5330a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    return(0);
53314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
53324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
53344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFAParseRegExp:
5335441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard * @ctxt:  a regexp parser context
5336ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * @top:  is this the top-level expression ?
53374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
53384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * [1]   regExp   ::=     branch  ( '|' branch )*
53394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
53404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardstatic void
53414255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
5342c7e3cc49bade82dba0cda4ae7c07ffcd1e32fe25Daniel Veillard    xmlRegStatePtr start, end;
53434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53442cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    /* if not top start should have been generated by an epsilon trans */
53454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    start = ctxt->state;
53462cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    ctxt->end = NULL;
534754eb0243c442292953b4a3df39568735039ebc82Daniel Veillard    xmlFAParseBranch(ctxt, NULL);
53482cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    if (top) {
53492cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard#ifdef DEBUG_REGEXP_GRAPH
53502cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	printf("State %d is final\n", ctxt->state->no);
53512cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard#endif
53522cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	ctxt->state->type = XML_REGEXP_FINAL_STATE;
53532cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    }
53544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR != '|') {
53554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->end = ctxt->state;
53564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
53574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
53584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    end = ctxt->state;
53594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    while ((CUR == '|') && (ctxt->error == 0)) {
53604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	NEXT;
53614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->state = start;
53622cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	ctxt->end = NULL;
536354eb0243c442292953b4a3df39568735039ebc82Daniel Veillard	xmlFAParseBranch(ctxt, end);
53642cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    }
53652cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard    if (!top) {
53662cbf596c7f6d4ef21798bb06efd7542781124300Daniel Veillard	ctxt->state = end;
53674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ctxt->end = end;
53684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
53694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
53704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
53724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
53734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 			The basic API					*
53744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
53754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
53764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
53774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
53784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegexpPrint:
53794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @output: the file for the output debug
53804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @regexp: the compiled regexp
53814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
53824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Print the content of the compiled regular expression
53834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
53844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
53854255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpPrint(FILE *output, xmlRegexpPtr regexp) {
53864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
53874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
5388a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard    if (output == NULL)
5389a82b182655ccee95e3b7210066206ddb3918823fDaniel Veillard        return;
53904255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, " regexp: ");
53914255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp == NULL) {
53924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, "NULL\n");
53934255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
53944255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
53954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "'%s' ", regexp->string);
53964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "\n");
53974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d atoms:\n", regexp->nbAtoms);
53984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < regexp->nbAtoms; i++) {
53994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, " %02d ", i);
54004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegPrintAtom(output, regexp->atoms[i]);
54014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d states:", regexp->nbStates);
54034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "\n");
54044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < regexp->nbStates; i++) {
54054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegPrintState(output, regexp->states[i]);
54064255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    fprintf(output, "%d counters:\n", regexp->nbCounters);
54084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    for (i = 0;i < regexp->nbCounters; i++) {
54094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	fprintf(output, " %d: min %d max %d\n", i, regexp->counters[i].min,
54104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		                                regexp->counters[i].max);
54114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
54134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
54154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegexpCompile:
54164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @regexp:  a regular expression string
54174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
54184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Parses a regular expression conforming to XML Schemas Part 2 Datatype
5419ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Appendix F and builds an automata suitable for testing strings against
54204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * that regular expression
54214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
54224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the compiled expression or NULL in case of error
54234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
54244255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpPtr
54254255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpCompile(const xmlChar *regexp) {
54264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegexpPtr ret;
54274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegParserCtxtPtr ctxt;
54284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt = xmlRegNewParserCtxt(regexp);
54304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt == NULL)
54314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
54324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* initialize the parser */
54344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->end = NULL;
54354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->start = ctxt->state = xmlRegNewState(ctxt);
54364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePush(ctxt, ctxt->start);
54374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* parse the expression building an automata */
54394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAParseRegExp(ctxt, 1);
54404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (CUR != 0) {
54414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	ERROR("xmlFAParseRegExp: extra characters");
54424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
5443cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard    if (ctxt->error != 0) {
5444cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard	xmlRegFreeParserCtxt(ctxt);
5445cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard	return(NULL);
5446cb4284e29641aa7dd990d42aba772b7f5c1ab50dDaniel Veillard    }
54474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->end = ctxt->state;
54484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->start->type = XML_REGEXP_START_STATE;
54494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->end->type = XML_REGEXP_FINAL_STATE;
54504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* remove the Epsilon except for counted transitions */
54524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAEliminateEpsilonTransitions(ctxt);
54534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt->error != 0) {
54564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlRegFreeParserCtxt(ctxt);
54574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
54584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
54594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlRegEpxFromParse(ctxt);
54604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegFreeParserCtxt(ctxt);
54614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
54624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
54634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
54654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegexpExec:
54664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @comp:  the compiled regular expression
54674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @content:  the value to check against the regular expression
54684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5469ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Check if the regular expression generates the value
54704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5471ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Returns 1 if it matches, 0 if not and a negative value in case of error
54724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
54734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardint
54744255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpExec(xmlRegexpPtr comp, const xmlChar *content) {
54754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((comp == NULL) || (content == NULL))
54764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
54774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(xmlFARegExec(comp, content));
54784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
54794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
54804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
548123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * xmlRegexpIsDeterminist:
548223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * @comp:  the compiled regular expression
548323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *
548423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard * Check if the regular expression is determinist
548523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard *
5486ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * Returns 1 if it yes, 0 if not and a negative value in case of error
548723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard */
548823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillardint
548923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel VeillardxmlRegexpIsDeterminist(xmlRegexpPtr comp) {
549023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    xmlAutomataPtr am;
549123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    int ret;
549223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
549323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (comp == NULL)
549423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(-1);
549523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (comp->determinist != -1)
549623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	return(comp->determinist);
549723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
549823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am = xmlNewAutomata();
5499bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard    if (am->states != NULL) {
5500bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard	int i;
5501bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard
5502bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard	for (i = 0;i < am->nbStates;i++)
5503bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard	    xmlRegFreeState(am->states[i]);
5504bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard	xmlFree(am->states);
5505bd9afb529069415baf1f32d907f035de19dae788Daniel Veillard    }
550623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->nbAtoms = comp->nbAtoms;
550723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->atoms = comp->atoms;
550823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->nbStates = comp->nbStates;
550923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->states = comp->states;
551023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->determinist = -1;
55111ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    am->flags = comp->flags;
551223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    ret = xmlFAComputesDeterminism(am);
551323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->atoms = NULL;
551423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    am->states = NULL;
551523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    xmlFreeAutomata(am);
55161ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    comp->determinist = ret;
551723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    return(ret);
551823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard}
551923e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
552023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard/**
55214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlRegFreeRegexp:
55224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @regexp:  the regexp
55234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
55244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free a regexp
55254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
55264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
55274255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegFreeRegexp(xmlRegexpPtr regexp) {
55284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    int i;
55294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp == NULL)
55304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
55314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp->string != NULL)
55334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(regexp->string);
55344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp->states != NULL) {
55354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0;i < regexp->nbStates;i++)
55364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegFreeState(regexp->states[i]);
55374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(regexp->states);
55384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
55394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp->atoms != NULL) {
55404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	for (i = 0;i < regexp->nbAtoms;i++)
55414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	    xmlRegFreeAtom(regexp->atoms[i]);
55424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(regexp->atoms);
55434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    }
55444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (regexp->counters != NULL)
55454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFree(regexp->counters);
554623e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (regexp->compact != NULL)
554723e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	xmlFree(regexp->compact);
5548118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard    if (regexp->transdata != NULL)
5549118aed78f360f51d182770e62b251ef324707aa2Daniel Veillard	xmlFree(regexp->transdata);
555023e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    if (regexp->stringMap != NULL) {
555123e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	for (i = 0; i < regexp->nbstrings;i++)
555223e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	    xmlFree(regexp->stringMap[i]);
555323e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard	xmlFree(regexp->stringMap);
555423e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    }
555523e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard
55564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFree(regexp);
55574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
55584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#ifdef LIBXML_AUTOMATA_ENABLED
55604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/************************************************************************
55614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
55624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 			The Automata interface				*
55634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * 									*
55644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard ************************************************************************/
55654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
55674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlNewAutomata:
55684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
55694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Create a new automata
55704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
55714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the new object or NULL in case of failure
55724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
55734255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataPtr
55744255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlNewAutomata(void) {
55754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlAutomataPtr ctxt;
55764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt = xmlRegNewParserCtxt(NULL);
55784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (ctxt == NULL)
55794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
55804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55814255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    /* initialize the parser */
55824255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->end = NULL;
55834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ctxt->start = ctxt->state = xmlRegNewState(ctxt);
5584a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (ctxt->start == NULL) {
5585a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	xmlFreeAutomata(ctxt);
5586a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(NULL);
5587a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
5588d0271473abc7ca82a22e9a953ec525a6f4b504d5Daniel Veillard    ctxt->start->type = XML_REGEXP_START_STATE;
5589a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (xmlRegStatePush(ctxt, ctxt->start) < 0) {
5590a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        xmlRegFreeState(ctxt->start);
5591a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	xmlFreeAutomata(ctxt);
5592a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(NULL);
5593a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
55941ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    ctxt->flags = 0;
55954255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55964255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ctxt);
55974255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
55984255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
55994255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
56004255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlFreeAutomata:
56014255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
56024255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
56034255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Free an automata
56044255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
56054255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardvoid
56064255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlFreeAutomata(xmlAutomataPtr am) {
56074255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (am == NULL)
56084255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return;
56094255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegFreeParserCtxt(am);
56104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
56114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
5613293416828e1467f877d9dd928f174dcf81b103bcDaniel Veillard * xmlAutomataSetFlags:
56141ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * @am: an automata
56151ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * @flags:  a set of internal flags
56161ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard *
56171ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard * Set some flags on the automata
56181ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard */
56191ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillardvoid
56201ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel VeillardxmlAutomataSetFlags(xmlAutomataPtr am, int flags) {
56211ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    if (am == NULL)
56221ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard	return;
56231ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard    am->flags |= flags;
56241ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard}
56251ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard
56261ba2aca3ebc3b47653a86849746b168a4e0bd8c6Daniel Veillard/**
56274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataGetInitState:
56284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
56294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5630a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * Initial state lookup
5631a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard *
56324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the initial state of the automata
56334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
56344255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
56354255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataGetInitState(xmlAutomataPtr am) {
56364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (am == NULL)
56374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
56384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(am->start);
56394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
56404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
56424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataSetFinalState:
56434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
56444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @state: a state in this automata
56454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
56464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Makes that state a final state
56474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
56484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns 0 or -1 in case of error
56494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
56504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillardint
56514255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataSetFinalState(xmlAutomataPtr am, xmlAutomataStatePtr state) {
56524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((am == NULL) || (state == NULL))
56534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(-1);
56544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    state->type = XML_REGEXP_FINAL_STATE;
56554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(0);
56564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
56574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
56594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataNewTransition:
56604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
56614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @from: the starting point of the transition
56624255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @to: the target point of the transition or NULL
56634255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @token: the input string associated to that transition
56644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @data: data passed to the callback function if the transition is activated
56654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5666ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
56674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * and then adds a transition from the @from state to the target state
56684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * activated by the value of @token
56694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
56704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the target state or NULL in case of error
56714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
56724255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
56734255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataNewTransition(xmlAutomataPtr am, xmlAutomataStatePtr from,
56744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 xmlAutomataStatePtr to, const xmlChar *token,
56754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 void *data) {
56764255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
56774255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
56784255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
56794255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
56804255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
5681a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (atom == NULL)
5682a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        return(NULL);
56834255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->data = data;
56844255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL)
56854255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
56864255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->valuep = xmlStrdup(token);
56874255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
5688a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
5689a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        xmlRegFreeAtom(atom);
5690a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(NULL);
5691a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
56924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
569352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(am->state);
569452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    return(to);
569552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard}
569652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
569752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard/**
569852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * xmlAutomataNewTransition2:
569952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @am: an automata
570052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @from: the starting point of the transition
570152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @to: the target point of the transition or NULL
570252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @token: the first input string associated to that transition
570352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @token2: the second input string associated to that transition
570452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * @data: data passed to the callback function if the transition is activated
570552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *
5706ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
570752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * and then adds a transition from the @from state to the target state
570852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * activated by the value of @token
570952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard *
571052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard * Returns the target state or NULL in case of error
571152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard */
571252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel VeillardxmlAutomataStatePtr
571352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel VeillardxmlAutomataNewTransition2(xmlAutomataPtr am, xmlAutomataStatePtr from,
571452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard			  xmlAutomataStatePtr to, const xmlChar *token,
571552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard			  const xmlChar *token2, void *data) {
571652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    xmlRegAtomPtr atom;
571752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
571852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
571952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(NULL);
572052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
572152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (atom == NULL)
572252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	return(NULL);
572311ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    atom->data = data;
572452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if ((token2 == NULL) || (*token2 == 0)) {
572552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	atom->valuep = xmlStrdup(token);
572652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    } else {
572752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	int lenn, lenp;
572852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	xmlChar *str;
572952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
573052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	lenn = strlen((char *) token2);
573152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	lenp = strlen((char *) token);
573252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
57333c908dca479ed50dca24b8593bca90e40dbde6b8Daniel Veillard	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
573452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	if (str == NULL) {
573552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	    xmlRegFreeAtom(atom);
573652b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	    return(NULL);
573752b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	}
573852b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	memcpy(&str[0], token, lenp);
573952b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	str[lenp] = '|';
574052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	memcpy(&str[lenp + 1], token2, lenn);
574152b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	str[lenn + lenp + 1] = 0;
574252b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
574352b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard	atom->valuep = str;
574452b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    }
574552b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard
5746a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
5747a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        xmlRegFreeAtom(atom);
5748a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard	return(NULL);
5749a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
575052b48c7a7bfb338f434d39f9fc3e54768e301575Daniel Veillard    if (to == NULL)
57514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(am->state);
57529efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    return(to);
57539efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard}
57549efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
57559efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard/**
57569efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * xmlAutomataNewNegTrans:
57579efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @am: an automata
57589efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @from: the starting point of the transition
57599efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @to: the target point of the transition or NULL
57609efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @token: the first input string associated to that transition
57619efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @token2: the second input string associated to that transition
57629efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * @data: data passed to the callback function if the transition is activated
57639efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard *
57649efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * If @to is NULL, this creates first a new target state in the automata
57659efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * and then adds a transition from the @from state to the target state
57669efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * activated by any value except (@token,@token2)
57676e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard * Note that if @token2 is not NULL, then (X, NULL) won't match to follow
57686e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard # the semantic of XSD ##other
57699efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard *
57709efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard * Returns the target state or NULL in case of error
57719efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard */
57729efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel VeillardxmlAutomataStatePtr
57739efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel VeillardxmlAutomataNewNegTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
57749efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard		       xmlAutomataStatePtr to, const xmlChar *token,
57759efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard		       const xmlChar *token2, void *data) {
57769efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    xmlRegAtomPtr atom;
577777005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard    xmlChar err_msg[200];
57789efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
57799efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
57809efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	return(NULL);
57819efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
57829efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if (atom == NULL)
57839efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	return(NULL);
57849efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    atom->data = data;
57859efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    atom->neg = 1;
57869efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if ((token2 == NULL) || (*token2 == 0)) {
57879efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	atom->valuep = xmlStrdup(token);
57889efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    } else {
57899efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	int lenn, lenp;
57909efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	xmlChar *str;
57919efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
57929efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	lenn = strlen((char *) token2);
57939efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	lenp = strlen((char *) token);
57949efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
57959efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
57969efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	if (str == NULL) {
57979efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	    xmlRegFreeAtom(atom);
57989efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	    return(NULL);
57999efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	}
58009efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	memcpy(&str[0], token, lenp);
58019efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	str[lenp] = '|';
58029efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	memcpy(&str[lenp + 1], token2, lenn);
58039efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	str[lenn + lenp + 1] = 0;
58049efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
58059efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	atom->valuep = str;
58069efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    }
5807db68b74dc7ec531361a736de7769a3e8ce881f79Daniel Veillard    snprintf((char *) err_msg, 199, "not %s", (const char *) atom->valuep);
580877005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard    err_msg[199] = 0;
580977005e6ff0426ae3cfefdcfb5796f29a8e83a83bDaniel Veillard    atom->valuep2 = xmlStrdup(err_msg);
58109efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard
58119efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
58129efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard        xmlRegFreeAtom(atom);
58139efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	return(NULL);
58149efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    }
58156e65e15777ebb281aec362fa2aba51e2cb5aa87fDaniel Veillard    am->negs++;
58169efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard    if (to == NULL)
58179efc476bb6fe9d7d84ee0fe1190888801d9374ccDaniel Veillard	return(am->state);
58184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(to);
58194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
58204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
58214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
582287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * xmlAutomataNewCountTrans2:
582387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @am: an automata
582487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @from: the starting point of the transition
582587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @to: the target point of the transition or NULL
582687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @token: the input string associated to that transition
582787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @token2: the second input string associated to that transition
582887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @min:  the minimum successive occurences of token
582987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @max:  the maximum successive occurences of token
583087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @data:  data associated to the transition
583187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik *
583287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * If @to is NULL, this creates first a new target state in the automata
583387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * and then adds a transition from the @from state to the target state
583487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * activated by a succession of input of value @token and @token2 and
583587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * whose number is between @min and @max
583687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik *
583787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * Returns the target state or NULL in case of error
583887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik */
583987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. BuchcikxmlAutomataStatePtr
584087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. BuchcikxmlAutomataNewCountTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
584187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 xmlAutomataStatePtr to, const xmlChar *token,
584287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 const xmlChar *token2,
584387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 int min, int max, void *data) {
584487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    xmlRegAtomPtr atom;
584587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    int counter;
584687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
584787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((am == NULL) || (from == NULL) || (token == NULL))
584887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
584987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (min < 0)
585087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
585187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((max < min) || (max < 1))
585287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
585387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
585487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (atom == NULL)
585587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
585687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((token2 == NULL) || (*token2 == 0)) {
585787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->valuep = xmlStrdup(token);
585887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    } else {
585987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	int lenn, lenp;
586087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlChar *str;
586187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
586287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	lenn = strlen((char *) token2);
586387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	lenp = strlen((char *) token);
586487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
586587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
586687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	if (str == NULL) {
586787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	    xmlRegFreeAtom(atom);
586887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	    return(NULL);
586987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	}
587087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	memcpy(&str[0], token, lenp);
587187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str[lenp] = '|';
587287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	memcpy(&str[lenp + 1], token2, lenn);
587387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str[lenn + lenp + 1] = 0;
587487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
587587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->valuep = str;
587687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    }
587787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->data = data;
587887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (min == 0)
587987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->min = 1;
588087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    else
588187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->min = min;
588287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->max = max;
588387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
588487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    /*
588587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik     * associate a counter to the transition.
588687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik     */
588787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    counter = xmlRegGetCounter(am);
588887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->counters[counter].min = min;
588987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->counters[counter].max = max;
589087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
589187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    /* xmlFAGenerateTransitions(am, from, to, atom); */
589287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (to == NULL) {
589387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik        to = xmlRegNewState(am);
589487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlRegStatePush(am, to);
589587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    }
58965de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(am, from, atom, to, counter, -1);
589787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    xmlRegAtomPush(am, atom);
589887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->state = to;
589987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
590087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (to == NULL)
590187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	to = am->state;
590287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (to == NULL)
590387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
590487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (min == 0)
590587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlFAGenerateEpsilonTransition(am, from, to);
590687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    return(to);
590787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik}
590887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
590987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik/**
59104255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataNewCountTrans:
59114255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
59124255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @from: the starting point of the transition
59134255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @to: the target point of the transition or NULL
59144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @token: the input string associated to that transition
59154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @min:  the minimum successive occurences of token
5916a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @max:  the maximum successive occurences of token
5917a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @data:  data associated to the transition
59184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
5919ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
59204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * and then adds a transition from the @from state to the target state
59214255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * activated by a succession of input of value @token and whose number
59224255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * is between @min and @max
59234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
59244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the target state or NULL in case of error
59254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
59264255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
59274255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
59284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 xmlAutomataStatePtr to, const xmlChar *token,
59294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard			 int min, int max, void *data) {
59304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegAtomPtr atom;
59310ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    int counter;
59324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
59334255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
59344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (min < 0)
59364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((max < min) || (max < 1))
59384255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59394255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
59404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (atom == NULL)
59414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->valuep = xmlStrdup(token);
59434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->data = data;
59444255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (min == 0)
59454255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	atom->min = 1;
59464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    else
59474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	atom->min = min;
59484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    atom->max = max;
59494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
59500ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    /*
59510ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard     * associate a counter to the transition.
59520ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard     */
59530ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    counter = xmlRegGetCounter(am);
59540ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    am->counters[counter].min = min;
59550ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    am->counters[counter].max = max;
59560ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard
59570ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    /* xmlFAGenerateTransitions(am, from, to, atom); */
59580ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    if (to == NULL) {
59590ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard        to = xmlRegNewState(am);
59600ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard	xmlRegStatePush(am, to);
5961a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
59625de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(am, from, atom, to, counter, -1);
59630ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    xmlRegAtomPush(am, atom);
59640ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard    am->state = to;
59650ddb21c46ca6ac5297ff5f6537480de8463223eaDaniel Veillard
59664255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
59674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	to = am->state;
59684255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
59694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
59704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (min == 0)
59714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	xmlFAGenerateEpsilonTransition(am, from, to);
59724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(to);
59734255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
59744255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
59754255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
597687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * xmlAutomataNewOnceTrans2:
597787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @am: an automata
597887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @from: the starting point of the transition
597987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @to: the target point of the transition or NULL
598087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @token: the input string associated to that transition
598187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @token2: the second input string associated to that transition
598287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @min:  the minimum successive occurences of token
598387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @max:  the maximum successive occurences of token
598487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * @data:  data associated to the transition
598587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik *
598687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * If @to is NULL, this creates first a new target state in the automata
598787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * and then adds a transition from the @from state to the target state
598887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * activated by a succession of input of value @token and @token2 and whose
598987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * number is between @min and @max, moreover that transition can only be
599087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * crossed once.
599187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik *
599287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik * Returns the target state or NULL in case of error
599387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik */
599487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. BuchcikxmlAutomataStatePtr
599587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. BuchcikxmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomataStatePtr from,
599687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 xmlAutomataStatePtr to, const xmlChar *token,
599787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 const xmlChar *token2,
599887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik			 int min, int max, void *data) {
599987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    xmlRegAtomPtr atom;
600087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    int counter;
600187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
600287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((am == NULL) || (from == NULL) || (token == NULL))
600387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
600487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (min < 1)
600587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
600687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((max < min) || (max < 1))
600787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
600887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
600987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (atom == NULL)
601087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	return(NULL);
601187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if ((token2 == NULL) || (*token2 == 0)) {
601287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->valuep = xmlStrdup(token);
601387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    } else {
601487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	int lenn, lenp;
601587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlChar *str;
601687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
601787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	lenn = strlen((char *) token2);
601887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	lenp = strlen((char *) token);
601987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
602087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
602187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	if (str == NULL) {
602287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	    xmlRegFreeAtom(atom);
602387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	    return(NULL);
602487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	}
602587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	memcpy(&str[0], token, lenp);
602687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str[lenp] = '|';
602787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	memcpy(&str[lenp + 1], token2, lenn);
602887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	str[lenn + lenp + 1] = 0;
602987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
603087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	atom->valuep = str;
603187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    }
603287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->data = data;
603387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->quant = XML_REGEXP_QUANT_ONCEONLY;
603411ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    atom->min = min;
603587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    atom->max = max;
603687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    /*
603787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik     * associate a counter to the transition.
603887876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik     */
603987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    counter = xmlRegGetCounter(am);
604087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->counters[counter].min = 1;
604187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->counters[counter].max = 1;
604287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
604387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    /* xmlFAGenerateTransitions(am, from, to, atom); */
604487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    if (to == NULL) {
604587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	to = xmlRegNewState(am);
604687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik	xmlRegStatePush(am, to);
604787876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    }
60485de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(am, from, atom, to, counter, -1);
604987876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    xmlRegAtomPush(am, atom);
605087876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    am->state = to;
605187876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik    return(to);
605287876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik}
605387876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
605487876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
605587876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik
605687876407ced312c9b2c8d8b03f988a7dd484a68eKasimier T. Buchcik/**
60577646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * xmlAutomataNewOnceTrans:
60587646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @am: an automata
60597646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @from: the starting point of the transition
60607646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @to: the target point of the transition or NULL
60617646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @token: the input string associated to that transition
60627646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @min:  the minimum successive occurences of token
6063a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @max:  the maximum successive occurences of token
6064a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @data:  data associated to the transition
60657646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
6066ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
60677646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * and then adds a transition from the @from state to the target state
60687646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * activated by a succession of input of value @token and whose number
6069ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * is between @min and @max, moreover that transition can only be crossed
60707646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * once.
60717646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
60727646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * Returns the target state or NULL in case of error
60737646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard */
60747646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlAutomataStatePtr
60757646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
60767646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard			 xmlAutomataStatePtr to, const xmlChar *token,
60777646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard			 int min, int max, void *data) {
60787646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    xmlRegAtomPtr atom;
60797646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    int counter;
60807646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
60817646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if ((am == NULL) || (from == NULL) || (token == NULL))
60827646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
60837646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (min < 1)
60847646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
60857646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if ((max < min) || (max < 1))
60867646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
60877646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
60887646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (atom == NULL)
60897646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
60907646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom->valuep = xmlStrdup(token);
60917646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom->data = data;
60927646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom->quant = XML_REGEXP_QUANT_ONCEONLY;
609311ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    atom->min = min;
60947646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    atom->max = max;
60957646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    /*
60967646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard     * associate a counter to the transition.
60977646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard     */
60987646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    counter = xmlRegGetCounter(am);
60997646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    am->counters[counter].min = 1;
61007646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    am->counters[counter].max = 1;
61017646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
61027646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    /* xmlFAGenerateTransitions(am, from, to, atom); */
61037646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (to == NULL) {
61047646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	to = xmlRegNewState(am);
61057646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	xmlRegStatePush(am, to);
61067646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    }
61075de0938fd16e2a4aabcab44f45c85a2f8a7f0a21Daniel Veillard    xmlRegStateAddTrans(am, from, atom, to, counter, -1);
61087646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    xmlRegAtomPush(am, atom);
61097646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    am->state = to;
61107646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    return(to);
61117646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard}
61127646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
61137646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard/**
61144255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataNewState:
61154255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
61164255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
61174255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Create a new disconnected state in the automata
61184255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
61194255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the new state or NULL in case of error
61204255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
61214255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
61224255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataNewState(xmlAutomataPtr am) {
61234255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlAutomataStatePtr to;
61244255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
61254255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (am == NULL)
61264255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
61274255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    to = xmlRegNewState(am);
61284255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegStatePush(am, to);
61294255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(to);
61304255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
61314255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
61324255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
6133a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * xmlAutomataNewEpsilon:
61344255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
61354255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @from: the starting point of the transition
61364255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @to: the target point of the transition or NULL
61374255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
6138ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
6139ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * and then adds an epsilon transition from the @from state to the
61404255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * target state
61414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
61424255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the target state or NULL in case of error
61434255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
61444255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataStatePtr
61454255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataNewEpsilon(xmlAutomataPtr am, xmlAutomataStatePtr from,
61464255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard		      xmlAutomataStatePtr to) {
61474255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if ((am == NULL) || (from == NULL))
61484255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(NULL);
61494255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAGenerateEpsilonTransition(am, from, to);
61504255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    if (to == NULL)
61514255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard	return(am->state);
61524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(to);
61534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
61544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
6155b509f1543df71549969eeac076349e05d2f78044Daniel Veillard/**
61567646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * xmlAutomataNewAllTrans:
61577646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @am: an automata
61587646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @from: the starting point of the transition
61597646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * @to: the target point of the transition or NULL
6160a9b66d00b5fbae2381f59c0be4d8c7b8e3c16cf7Daniel Veillard * @lax: allow to transition if not all all transitions have been activated
61617646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
6162ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
61637646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * and then adds a an ALL transition from the @from state to the
61647646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * target state. That transition is an epsilon transition allowed only when
61657646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * all transitions from the @from node have been activated.
61667646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard *
61677646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard * Returns the target state or NULL in case of error
61687646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard */
61697646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlAutomataStatePtr
61707646b18d64b6c739d04ca453493070e88c4aab13Daniel VeillardxmlAutomataNewAllTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6171441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard		       xmlAutomataStatePtr to, int lax) {
61727646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if ((am == NULL) || (from == NULL))
61737646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(NULL);
6174441bc32e3167ed55df415500e3a22eda4eec1ac6Daniel Veillard    xmlFAGenerateAllTransition(am, from, to, lax);
61757646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    if (to == NULL)
61767646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard	return(am->state);
61777646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard    return(to);
61787646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard}
61797646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard
61807646b18d64b6c739d04ca453493070e88c4aab13Daniel Veillard/**
6181b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * xmlAutomataNewCounter:
6182b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @am: an automata
6183b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @min:  the minimal value on the counter
6184b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @max:  the maximal value on the counter
6185b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6186b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * Create a new counter
6187b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6188b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * Returns the counter number or -1 in case of error
6189b509f1543df71549969eeac076349e05d2f78044Daniel Veillard */
6190b509f1543df71549969eeac076349e05d2f78044Daniel Veillardint
6191b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataNewCounter(xmlAutomataPtr am, int min, int max) {
6192b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    int ret;
6193b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
6194b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if (am == NULL)
6195b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(-1);
6196b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
6197b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    ret = xmlRegGetCounter(am);
6198b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if (ret < 0)
6199b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(-1);
6200b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    am->counters[ret].min = min;
6201b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    am->counters[ret].max = max;
6202b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    return(ret);
6203b509f1543df71549969eeac076349e05d2f78044Daniel Veillard}
6204b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
6205b509f1543df71549969eeac076349e05d2f78044Daniel Veillard/**
6206b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * xmlAutomataNewCountedTrans:
6207b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @am: an automata
6208b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @from: the starting point of the transition
6209b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @to: the target point of the transition or NULL
6210b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @counter: the counter associated to that transition
6211b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6212ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
6213b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * and then adds an epsilon transition from the @from state to the target state
6214b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * which will increment the counter provided
6215b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6216b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * Returns the target state or NULL in case of error
6217b509f1543df71549969eeac076349e05d2f78044Daniel Veillard */
6218b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataStatePtr
6219b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataNewCountedTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6220b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		xmlAutomataStatePtr to, int counter) {
6221b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if ((am == NULL) || (from == NULL) || (counter < 0))
6222b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(NULL);
6223b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    xmlFAGenerateCountedEpsilonTransition(am, from, to, counter);
6224b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if (to == NULL)
6225b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(am->state);
6226b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    return(to);
6227b509f1543df71549969eeac076349e05d2f78044Daniel Veillard}
6228b509f1543df71549969eeac076349e05d2f78044Daniel Veillard
6229b509f1543df71549969eeac076349e05d2f78044Daniel Veillard/**
6230b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * xmlAutomataNewCounterTrans:
6231b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @am: an automata
6232b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @from: the starting point of the transition
6233b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @to: the target point of the transition or NULL
6234b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * @counter: the counter associated to that transition
6235b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6236ddf71d61c939b561a2014f27a88e6a9899355b79William M. Brack * If @to is NULL, this creates first a new target state in the automata
6237b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * and then adds an epsilon transition from the @from state to the target state
6238b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * which will be allowed only if the counter is within the right range.
6239b509f1543df71549969eeac076349e05d2f78044Daniel Veillard *
6240b509f1543df71549969eeac076349e05d2f78044Daniel Veillard * Returns the target state or NULL in case of error
6241b509f1543df71549969eeac076349e05d2f78044Daniel Veillard */
6242b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataStatePtr
6243b509f1543df71549969eeac076349e05d2f78044Daniel VeillardxmlAutomataNewCounterTrans(xmlAutomataPtr am, xmlAutomataStatePtr from,
6244b509f1543df71549969eeac076349e05d2f78044Daniel Veillard		xmlAutomataStatePtr to, int counter) {
6245b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if ((am == NULL) || (from == NULL) || (counter < 0))
6246b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(NULL);
6247b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    xmlFAGenerateCountedTransition(am, from, to, counter);
6248b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    if (to == NULL)
6249b509f1543df71549969eeac076349e05d2f78044Daniel Veillard	return(am->state);
6250b509f1543df71549969eeac076349e05d2f78044Daniel Veillard    return(to);
6251b509f1543df71549969eeac076349e05d2f78044Daniel Veillard}
62524255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
62534255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard/**
62544255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * xmlAutomataCompile:
62554255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * @am: an automata
62564255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
62574255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Compile the automata into a Reg Exp ready for being executed.
62584255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * The automata should be free after this point.
62594255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard *
62604255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard * Returns the compiled regexp or NULL in case of error
62614255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard */
62624255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlRegexpPtr
62634255d504151db75c17f85192ce74f45dd2d65533Daniel VeillardxmlAutomataCompile(xmlAutomataPtr am) {
62644255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlRegexpPtr ret;
62654255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
6266a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    if ((am == NULL) || (am->error != 0)) return(NULL);
62674255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    xmlFAEliminateEpsilonTransitions(am);
626823e73571f8f6918e4ea7be3506ee5bd24ee86c52Daniel Veillard    /* xmlFAComputesDeterminism(am); */
62694255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    ret = xmlRegEpxFromParse(am);
62704255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard
62714255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard    return(ret);
62724255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard}
6273e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
6274e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard/**
6275e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * xmlAutomataIsDeterminist:
6276e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * @am: an automata
6277e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
6278e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Checks if an automata is determinist.
6279e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard *
6280e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard * Returns 1 if true, 0 if not, and -1 in case of error
6281e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard */
6282e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillardint
6283e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel VeillardxmlAutomataIsDeterminist(xmlAutomataPtr am) {
6284e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    int ret;
6285e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
6286e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    if (am == NULL)
6287e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard	return(-1);
6288e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard
6289e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    ret = xmlFAComputesDeterminism(am);
6290e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard    return(ret);
6291e19fc23b6427f4df516af7b3f6df7baa942e4207Daniel Veillard}
62924255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif /* LIBXML_AUTOMATA_ENABLED */
629381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
629481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef LIBXML_EXPR_ENABLED
629581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
629681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
629781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *		Formal Expression handling code				*
629881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
629981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
630081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
630181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
630281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *		Expression handling context				*
630381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
630481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
630581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
630681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstruct _xmlExpCtxt {
630781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlDictPtr dict;
630881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr *table;
630981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int size;
631081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int nbElems;
631181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int nb_nodes;
6312594e5dfb48ee6fbac1b64155839063648022fc57Daniel Veillard    int maxNodes;
631381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    const char *expr;
631481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    const char *cur;
631581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int nb_cons;
631681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int tabSize;
631781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard};
631881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
631981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
632081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpNewCtxt:
632181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @maxNodes:  the maximum number of nodes
632281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @dict:  optional dictionnary to use internally
632381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
632481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Creates a new context for manipulating expressions
632581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
632681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the context or NULL in case of error
632781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
632881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpCtxtPtr
632981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNewCtxt(int maxNodes, xmlDictPtr dict) {
633081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpCtxtPtr ret;
633181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int size = 256;
633281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
633381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (maxNodes <= 4096)
633481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        maxNodes = 4096;
633581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
633681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret = (xmlExpCtxtPtr) xmlMalloc(sizeof(xmlExpCtxt));
633781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ret == NULL)
633881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
633981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    memset(ret, 0, sizeof(xmlExpCtxt));
634081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->size = size;
634181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->nbElems = 0;
6342594e5dfb48ee6fbac1b64155839063648022fc57Daniel Veillard    ret->maxNodes = maxNodes;
634381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->table = xmlMalloc(size * sizeof(xmlExpNodePtr));
634481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ret->table == NULL) {
634581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        xmlFree(ret);
634681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(NULL);
634781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
634881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    memset(ret->table, 0, size * sizeof(xmlExpNodePtr));
634981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (dict == NULL) {
635081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ret->dict = xmlDictCreate();
635181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (ret->dict == NULL) {
635281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlFree(ret->table);
635381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlFree(ret);
635481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(NULL);
635581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
635681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else {
635781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ret->dict = dict;
635881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlDictReference(ret->dict);
635981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
636081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
636181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
636281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
636381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
636481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpFreeCtxt:
636581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt:  an expression context
636681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
636781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Free an expression context
636881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
636981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardvoid
637081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpFreeCtxt(xmlExpCtxtPtr ctxt) {
637181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt == NULL)
637281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return;
637381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlDictFree(ctxt->dict);
637481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->table != NULL)
637581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlFree(ctxt->table);
637681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlFree(ctxt);
637781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
637881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
637981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
638081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
638181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *		Structure associated to an expression node		*
638281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
638381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
6384465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define MAX_NODES 10000
6385465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
6386465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/* #define DEBUG_DERIV */
6387465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
6388465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/*
6389465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * TODO:
6390465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - Wildcards
6391465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - public API for creation
6392465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
6393465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Started
6394465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - regression testing
6395465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
6396465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Done
6397465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - split into module and test tool
6398465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * - memleaks
6399465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
640081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
640181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardtypedef enum {
640281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    XML_EXP_NILABLE = (1 << 0)
640381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard} xmlExpNodeInfo;
640481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
640581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define IS_NILLABLE(node) ((node)->info & XML_EXP_NILABLE)
640681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
640781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstruct _xmlExpNode {
640881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned char type;/* xmlExpNodeType */
640981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned char info;/* OR of xmlExpNodeInfo */
641081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned short key;	/* the hash key */
641181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned int ref;	/* The number of references */
641281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int c_max;		/* the maximum length it can consume */
641381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr exp_left;
641481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr next;/* the next node in the hash table or free list */
641581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    union {
641681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	struct {
641781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    int f_min;
641881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    int f_max;
641981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} count;
642081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	struct {
642181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr f_right;
642281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} children;
642381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        const xmlChar *f_str;
642481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } field;
642581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard};
642681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
642781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define exp_min field.count.f_min
642881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define exp_max field.count.f_max
642981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/* #define exp_left field.children.f_left */
643081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define exp_right field.children.f_right
643181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#define exp_str field.f_str
643281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
643381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr xmlExpNewNode(xmlExpCtxtPtr ctxt, xmlExpNodeType type);
643481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNode forbiddenExpNode = {
643581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    XML_EXP_FORBID, 0, 0, 0, 0, NULL, NULL, {{ 0, 0}}
643681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard};
643781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNodePtr forbiddenExp = &forbiddenExpNode;
643881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNode emptyExpNode = {
643981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    XML_EXP_EMPTY, 1, 0, 0, 0, NULL, NULL, {{ 0, 0}}
644081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard};
644181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNodePtr emptyExp = &emptyExpNode;
644281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
644381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
644481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
644581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *  The custom hash table for unicity and canonicalization		*
644681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *  of sub-expressions pointers						*
644781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
644881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
644981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/*
645081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpHashNameComputeKey:
645181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Calculate the hash key for a token
645281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
645381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic unsigned short
645481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpHashNameComputeKey(const xmlChar *name) {
645581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned short value = 0L;
645681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    char ch;
645781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
645881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (name != NULL) {
645981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	value += 30 * (*name);
646081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	while ((ch = *name++) != 0) {
646181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value = value ^ ((value << 5) + (value >> 3) + (unsigned long)ch);
646281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
646381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
646481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return (value);
646581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
646681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
646781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/*
646881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpHashComputeKey:
646981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Calculate the hash key for a compound expression
647081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
647181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic unsigned short
647281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpHashComputeKey(xmlExpNodeType type, xmlExpNodePtr left,
647381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                     xmlExpNodePtr right) {
647481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned long value;
647581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned short ret;
647681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
647781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (type) {
647881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_SEQ:
647981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value = left->key;
648081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value += right->key;
648181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value *= 3;
648281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = (unsigned short) value;
648381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    break;
648481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_OR:
648581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value = left->key;
648681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value += right->key;
648781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value *= 7;
648881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = (unsigned short) value;
648981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    break;
649081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_COUNT:
649181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value = left->key;
649281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    value += right->key;
649381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = (unsigned short) value;
649481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    break;
649581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	default:
649681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = 0;
649781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
649881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
649981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
650081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
650181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
650281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr
650381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNewNode(xmlExpCtxtPtr ctxt, xmlExpNodeType type) {
650481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr ret;
650581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
650681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->nb_nodes >= MAX_NODES)
650781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
650881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret = (xmlExpNodePtr) xmlMalloc(sizeof(xmlExpNode));
650981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ret == NULL)
651081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
651181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    memset(ret, 0, sizeof(xmlExpNode));
651281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->type = type;
651381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ret->next = NULL;
651481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ctxt->nb_nodes++;
651581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ctxt->nb_cons++;
651681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
651781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
651881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
651981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
652081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpHashGetEntry:
652181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @table: the hash table
652281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
652381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Get the unique entry from the hash table. The entry is created if
652481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * needed. @left and @right are consumed, i.e. their ref count will
652581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * be decremented by the operation.
652681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
652781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the pointer or NULL in case of error
652881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
652981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr
653081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpHashGetEntry(xmlExpCtxtPtr ctxt, xmlExpNodeType type,
653181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                   xmlExpNodePtr left, xmlExpNodePtr right,
653281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		   const xmlChar *name, int min, int max) {
653381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    unsigned short kbase, key;
653481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr entry;
653581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr insert;
653681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
653781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt == NULL)
653881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(NULL);
653981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
654081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
654181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * Check for duplicate and insertion location.
654281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
654381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (type == XML_EXP_ATOM) {
654481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	kbase = xmlExpHashNameComputeKey(name);
654581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if (type == XML_EXP_COUNT) {
654681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* COUNT reduction rule 1 */
654781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* a{1} -> a */
654881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (min == max) {
654981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (min == 1) {
655081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(left);
655181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
655281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (min == 0) {
655381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, left);
655481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(emptyExp);
655581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
655681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
655781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (min < 0) {
655881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, left);
655981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
656081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
656181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (max == -1)
656281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    kbase = min + 79;
656381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	else
656481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    kbase = max - min;
656581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	kbase += left->key;
656681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if (type == XML_EXP_OR) {
656781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* Forbid reduction rules */
656881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left->type == XML_EXP_FORBID) {
656981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, left);
657081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(right);
657181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
657281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (right->type == XML_EXP_FORBID) {
657381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, right);
657481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(left);
657581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
657681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
657781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* OR reduction rule 1 */
657881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* a | a reduced to a */
657981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left == right) {
658081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    left->ref--;
658181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(left);
658281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
658381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* OR canonicalization rule 1 */
658481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* linearize (a | b) | c into a | (b | c) */
658581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if ((left->type == XML_EXP_OR) && (right->type != XML_EXP_OR)) {
658681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp = left;
658781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            left = right;
658881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    right = tmp;
658981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
659081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* OR reduction rule 2 */
659181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* a | (a | b) and b | (a | b) are reduced to a | b */
659281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (right->type == XML_EXP_OR) {
659381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((left == right->exp_left) ||
659481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (left == right->exp_right)) {
659581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, left);
659681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(right);
659781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
659881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
659981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* OR canonicalization rule 2 */
660081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* linearize (a | b) | c into a | (b | c) */
660181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left->type == XML_EXP_OR) {
660281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp;
660381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
660481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* OR canonicalization rule 2 */
660581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((left->exp_right->type != XML_EXP_OR) &&
660681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (left->exp_right->key < left->exp_left->key)) {
660781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        tmp = left->exp_right;
660881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		left->exp_right = left->exp_left;
660981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		left->exp_left = tmp;
661081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
661181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    left->exp_right->ref++;
661281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_right, right,
661381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                             NULL, 0, 0);
661481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    left->exp_left->ref++;
661581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_left, tmp,
661681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                             NULL, 0, 0);
661781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
661881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, left);
661981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
662081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
662181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (right->type == XML_EXP_OR) {
662281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* Ordering in the tree */
662381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* C | (A | B) -> A | (B | C) */
662481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (left->key > right->exp_right->key) {
662581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpNodePtr tmp;
662681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		right->exp_right->ref++;
662781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_right,
662881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         left, NULL, 0, 0);
662981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		right->exp_left->ref++;
663081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_left,
663181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         tmp, NULL, 0, 0);
663281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, right);
663381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(tmp);
663481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
663581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* Ordering in the tree */
663681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* B | (A | C) -> A | (B | C) */
663781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (left->key > right->exp_left->key) {
663881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpNodePtr tmp;
663981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		right->exp_right->ref++;
664081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left,
664181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         right->exp_right, NULL, 0, 0);
664281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		right->exp_left->ref++;
664381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, right->exp_left,
664481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         tmp, NULL, 0, 0);
664581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, right);
664681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(tmp);
664781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
664881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
664981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	/* we know both types are != XML_EXP_OR here */
665081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        else if (left->key > right->key) {
665181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp = left;
665281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            left = right;
665381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    right = tmp;
665481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
665581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	kbase = xmlExpHashComputeKey(type, left, right);
665681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if (type == XML_EXP_SEQ) {
665781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* Forbid reduction rules */
665881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left->type == XML_EXP_FORBID) {
665981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, right);
666081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(left);
666181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
666281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (right->type == XML_EXP_FORBID) {
666381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, left);
666481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(right);
666581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
666681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* Empty reduction rules */
666781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (right->type == XML_EXP_EMPTY) {
666881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(left);
666981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
667081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (left->type == XML_EXP_EMPTY) {
667181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(right);
667281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
667381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	kbase = xmlExpHashComputeKey(type, left, right);
667481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else
667581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
667681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
667781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    key = kbase % ctxt->size;
667881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->table[key] != NULL) {
667981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	for (insert = ctxt->table[key]; insert != NULL;
668081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	     insert = insert->next) {
668181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((insert->key == kbase) &&
668281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (insert->type == type)) {
668381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (type == XML_EXP_ATOM) {
668481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (name == insert->exp_str) {
668581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			insert->ref++;
668681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			return(insert);
668781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
668881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else if (type == XML_EXP_COUNT) {
668981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if ((insert->exp_min == min) && (insert->exp_max == max) &&
669081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        (insert->exp_left == left)) {
669181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			insert->ref++;
669281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			left->ref--;
669381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			return(insert);
669481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
669581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else if ((insert->exp_left == left) &&
669681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			   (insert->exp_right == right)) {
669781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    insert->ref++;
669881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    left->ref--;
669981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    right->ref--;
670081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(insert);
670181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
670281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
670381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
670481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
670581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
670681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    entry = xmlExpNewNode(ctxt, type);
670781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (entry == NULL)
670881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
670981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    entry->key = kbase;
671081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (type == XML_EXP_ATOM) {
671181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->exp_str = name;
671281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->c_max = 1;
671381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if (type == XML_EXP_COUNT) {
671481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        entry->exp_min = min;
671581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        entry->exp_max = max;
671681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->exp_left = left;
671781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((min == 0) || (IS_NILLABLE(left)))
671881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    entry->info |= XML_EXP_NILABLE;
671981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (max < 0)
672081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    entry->c_max = -1;
672181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	else
672281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    entry->c_max = max * entry->exp_left->c_max;
672381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else {
672481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->exp_left = left;
672581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	entry->exp_right = right;
672681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (type == XML_EXP_OR) {
672781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((IS_NILLABLE(left)) || (IS_NILLABLE(right)))
672881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		entry->info |= XML_EXP_NILABLE;
672981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((entry->exp_left->c_max == -1) ||
673081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (entry->exp_right->c_max == -1))
673181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		entry->c_max = -1;
673281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else if (entry->exp_left->c_max > entry->exp_right->c_max)
673381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        entry->c_max = entry->exp_left->c_max;
673481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
673581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        entry->c_max = entry->exp_right->c_max;
673681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} else {
673781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((IS_NILLABLE(left)) && (IS_NILLABLE(right)))
673881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		entry->info |= XML_EXP_NILABLE;
673981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((entry->exp_left->c_max == -1) ||
674081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (entry->exp_right->c_max == -1))
674181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		entry->c_max = -1;
674281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
674381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        entry->c_max = entry->exp_left->c_max + entry->exp_right->c_max;
674481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
674581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
674681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    entry->ref = 1;
674781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->table[key] != NULL)
674881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        entry->next = ctxt->table[key];
674981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
675081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ctxt->table[key] = entry;
675181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    ctxt->nbElems++;
675281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
675381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(entry);
675481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
675581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
675681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
675781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpFree:
675881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expression context
675981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
676081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
676181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Dereference the expression
676281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
676381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardvoid
676481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpFree(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp) {
676581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((exp == NULL) || (exp == forbiddenExp) || (exp == emptyExp))
676681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return;
676781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    exp->ref--;
676881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (exp->ref == 0) {
676981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        unsigned short key;
677081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
677181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        /* Unlink it first from the hash table */
677281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	key = exp->key % ctxt->size;
677381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (ctxt->table[key] == exp) {
677481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ctxt->table[key] = exp->next;
677581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} else {
677681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp;
677781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
677881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = ctxt->table[key];
677981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    while (tmp != NULL) {
678081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (tmp->next == exp) {
678181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    tmp->next = exp->next;
678281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    break;
678381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
678481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        tmp = tmp->next;
678581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
678681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
678781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
678881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if ((exp->type == XML_EXP_SEQ) || (exp->type == XML_EXP_OR)) {
678981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, exp->exp_left);
679081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, exp->exp_right);
679181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	} else if (exp->type == XML_EXP_COUNT) {
679281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, exp->exp_left);
679381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
679481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        xmlFree(exp);
679581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	ctxt->nb_nodes--;
679681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
679781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
679881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
679981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
680081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpRef:
680181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
680281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
680381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Increase the reference count of the expression
680481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
680581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardvoid
680681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpRef(xmlExpNodePtr exp) {
680781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (exp != NULL)
680881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        exp->ref++;
680981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
681081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
6811ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard/**
6812ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * xmlExpNewAtom:
6813ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @ctxt: the expression context
6814ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @name: the atom name
6815ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @len: the atom name lenght in byte (or -1);
6816ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6817ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Get the atom associated to this name from that context
6818ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6819ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Returns the node or NULL in case of error
6820ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard */
6821ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNodePtr
6822ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNewAtom(xmlExpCtxtPtr ctxt, const xmlChar *name, int len) {
6823ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    if ((ctxt == NULL) || (name == NULL))
6824ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6825ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    name = xmlDictLookup(ctxt->dict, name, len);
6826ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    if (name == NULL)
6827ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6828ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    return(xmlExpHashGetEntry(ctxt, XML_EXP_ATOM, NULL, NULL, name, 0, 0));
6829ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard}
6830ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard
6831ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard/**
6832ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * xmlExpNewOr:
6833ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @ctxt: the expression context
6834ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @left: left expression
6835ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @right: right expression
6836ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6837ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Get the atom associated to the choice @left | @right
6838ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Note that @left and @right are consumed in the operation, to keep
6839ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * an handle on them use xmlExpRef() and use xmlExpFree() to release them,
6840ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * this is true even in case of failure (unless ctxt == NULL).
6841ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6842ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Returns the node or NULL in case of error
6843ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard */
6844ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNodePtr
6845ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNewOr(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) {
684611ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if (ctxt == NULL)
684711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard        return(NULL);
684811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if ((left == NULL) || (right == NULL)) {
6849ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        xmlExpFree(ctxt, left);
6850ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        xmlExpFree(ctxt, right);
6851ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6852ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    }
6853ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, left, right, NULL, 0, 0));
6854ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard}
6855ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard
6856ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard/**
6857ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * xmlExpNewSeq:
6858ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @ctxt: the expression context
6859ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @left: left expression
6860ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @right: right expression
6861ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6862ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Get the atom associated to the sequence @left , @right
6863ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Note that @left and @right are consumed in the operation, to keep
6864ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * an handle on them use xmlExpRef() and use xmlExpFree() to release them,
6865ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * this is true even in case of failure (unless ctxt == NULL).
6866ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6867ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Returns the node or NULL in case of error
6868ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard */
6869ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNodePtr
6870ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNewSeq(xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right) {
687111ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if (ctxt == NULL)
687211ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard        return(NULL);
687311ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if ((left == NULL) || (right == NULL)) {
6874ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        xmlExpFree(ctxt, left);
6875ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        xmlExpFree(ctxt, right);
6876ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6877ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    }
6878ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, left, right, NULL, 0, 0));
6879ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard}
6880ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard
6881ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard/**
6882ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * xmlExpNewRange:
6883ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @ctxt: the expression context
6884ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @subset: the expression to be repeated
6885ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @min: the lower bound for the repetition
6886ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * @max: the upper bound for the repetition, -1 means infinite
6887ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6888ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Get the atom associated to the range (@subset){@min, @max}
6889ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Note that @subset is consumed in the operation, to keep
6890ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * an handle on it use xmlExpRef() and use xmlExpFree() to release it,
6891ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * this is true even in case of failure (unless ctxt == NULL).
6892ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard *
6893ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard * Returns the node or NULL in case of error
6894ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard */
6895ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNodePtr
6896ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel VeillardxmlExpNewRange(xmlExpCtxtPtr ctxt, xmlExpNodePtr subset, int min, int max) {
689711ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if (ctxt == NULL)
689811ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard        return(NULL);
689911ce4004d86bb4b317c48b7d5124ba33e40e10f5Daniel Veillard    if ((subset == NULL) || (min < 0) || (max < -1) ||
6900ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        ((max >= 0) && (min > max))) {
6901ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	xmlExpFree(ctxt, subset);
6902ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        return(NULL);
6903ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    }
6904ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    return(xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, subset,
6905ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard                              NULL, NULL, min, max));
6906ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard}
6907ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard
690881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/************************************************************************
690981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
691081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *		Public API for operations on expressions		*
691181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *									*
691281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard ************************************************************************/
691381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
691481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic int
691581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpGetLanguageInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
691681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                     const xmlChar**list, int len, int nb) {
691781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int tmp, tmp2;
691881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardtail:
691981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (exp->type) {
692081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_EMPTY:
692181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(0);
692281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_ATOM:
692381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    for (tmp = 0;tmp < nb;tmp++)
692481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (list[tmp] == exp->exp_str)
692581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(0);
692681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            if (nb >= len)
692781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(-2);
692813cee4e37ba9f2a401f976e069539514ebfce7bcDaniel Veillard	    list[nb] = exp->exp_str;
692981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(1);
693081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_COUNT:
693181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    exp = exp->exp_left;
693281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    goto tail;
693381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_SEQ:
693481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_OR:
693581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpGetLanguageInt(ctxt, exp->exp_left, list, len, nb);
693681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp < 0)
693781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp);
693881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp2 = xmlExpGetLanguageInt(ctxt, exp->exp_right, list, len,
693981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                                nb + tmp);
694081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp2 < 0)
694181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp2);
694281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            return(tmp + tmp2);
694381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
694481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(-1);
694581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
694681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
694781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
694881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpGetLanguage:
694981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expression context
695081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
69517802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard * @langList: where to store the tokens
695281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @len: the allocated lenght of @list
695381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
695481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Find all the strings used in @exp and store them in @list
695581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
695681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the number of unique strings found, -1 in case of errors and
695781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *         -2 if there is more than @len strings
695881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
695981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardint
696081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
69617802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard                  const xmlChar**langList, int len) {
69627802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard    if ((ctxt == NULL) || (exp == NULL) || (langList == NULL) || (len <= 0))
696381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
69647802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard    return(xmlExpGetLanguageInt(ctxt, exp, langList, len, 0));
696581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
696681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
696781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic int
696881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpGetStartInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
696981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                  const xmlChar**list, int len, int nb) {
697081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int tmp, tmp2;
697181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardtail:
697281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (exp->type) {
697381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_FORBID:
697481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(0);
697581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_EMPTY:
697681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(0);
697781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_ATOM:
697881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    for (tmp = 0;tmp < nb;tmp++)
697981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (list[tmp] == exp->exp_str)
698081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(0);
698181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            if (nb >= len)
698281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(-2);
698313cee4e37ba9f2a401f976e069539514ebfce7bcDaniel Veillard	    list[nb] = exp->exp_str;
698481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(1);
698581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_COUNT:
698681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    exp = exp->exp_left;
698781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    goto tail;
698881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_SEQ:
698981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb);
699081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp < 0)
699181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp);
699281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (IS_NILLABLE(exp->exp_left)) {
699381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len,
699481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard					    nb + tmp);
699581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (tmp2 < 0)
699681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(tmp2);
699781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp += tmp2;
699881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
699981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            return(tmp);
700081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_OR:
700181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpGetStartInt(ctxt, exp->exp_left, list, len, nb);
700281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp < 0)
700381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp);
700481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp2 = xmlExpGetStartInt(ctxt, exp->exp_right, list, len,
700581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                                nb + tmp);
700681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp2 < 0)
700781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp2);
700881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            return(tmp + tmp2);
700981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
701081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(-1);
701181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
701281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
701381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
701481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpGetStart:
701581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expression context
701681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
70177802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard * @tokList: where to store the tokens
701881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @len: the allocated lenght of @list
701981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
702081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Find all the strings that appears at the start of the languages
702181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * accepted by @exp and store them in @list. E.g. for (a, b) | c
702281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * it will return the list [a, c]
702381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
702481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the number of unique strings found, -1 in case of errors and
702581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *         -2 if there is more than @len strings
702681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
702781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardint
702881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpGetStart(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
70297802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard               const xmlChar**tokList, int len) {
70307802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard    if ((ctxt == NULL) || (exp == NULL) || (tokList == NULL) || (len <= 0))
703181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
70327802ba56ff32eb503ac34885e1ce61b60a01d701Daniel Veillard    return(xmlExpGetStartInt(ctxt, exp, tokList, len, 0));
703381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
703481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
703581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
703681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpIsNillable:
703781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
703881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
703981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Finds if the expression is nillable, i.e. if it accepts the empty sequqnce
704081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
704181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns 1 if nillable, 0 if not and -1 in case of error
704281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
704381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardint
704481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpIsNillable(xmlExpNodePtr exp) {
704581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (exp == NULL)
704681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
704781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(IS_NILLABLE(exp) != 0);
704881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
704981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
705081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr
705181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpStringDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, const xmlChar *str)
705281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard{
705381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr ret;
705481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
705581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (exp->type) {
705681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_EMPTY:
705781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
705881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_FORBID:
705981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
706081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_ATOM:
706181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_str == str) {
706281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
706381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv atom: equal => Empty\n");
706481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
706581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        ret = emptyExp;
706681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    } else {
706781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
706881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv atom: mismatch => forbid\n");
706981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
707081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        /* TODO wildcards here */
707181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		ret = forbiddenExp;
707281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
707381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
707481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_OR: {
707581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp;
707681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
707781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
707881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("deriv or: => or(derivs)\n");
707981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
708081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
708181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp == NULL) {
708281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(NULL);
708381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
708481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str);
708581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL) {
708681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        xmlExpFree(ctxt, tmp);
708781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(NULL);
708881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
708981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard            ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret,
709081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			     NULL, 0, 0);
709181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
709281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
709381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_SEQ:
709481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
709581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("deriv seq: starting with left\n");
709681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
709781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
709881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL) {
709981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
710081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    } else if (ret == forbiddenExp) {
710181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (IS_NILLABLE(exp->exp_left)) {
710281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
710381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("deriv seq: left failed but nillable\n");
710481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
710581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    ret = xmlExpStringDeriveInt(ctxt, exp->exp_right, str);
710681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
710781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    } else {
710881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
710981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv seq: left match => sequence\n");
711081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
711181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        exp->exp_right->ref++;
711281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, exp->exp_right,
711381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         NULL, 0, 0);
711481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
711581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
711681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	case XML_EXP_COUNT: {
711781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    int min, max;
711881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpNodePtr tmp;
711981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
712081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_max == 0)
712181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(forbiddenExp);
712281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpStringDeriveInt(ctxt, exp->exp_left, str);
712381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL)
712481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
712581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == forbiddenExp) {
712681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
712781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv count: pattern mismatch => forbid\n");
712881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
712981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(ret);
713081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
713181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_max == 1)
713281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(ret);
713381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_max < 0) /* unbounded */
713481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		max = -1;
713581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
713681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		max = exp->exp_max - 1;
713781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_min > 0)
713881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		min = exp->exp_min - 1;
713981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
714081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		min = 0;
714181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    exp->exp_left->ref++;
714281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left, NULL,
714381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				     NULL, min, max);
714481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == emptyExp) {
714581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
714681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("deriv count: match to empty => new count\n");
714781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
714881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(tmp);
714981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
715081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
715181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("deriv count: match => sequence with new count\n");
715281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
715381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, tmp,
715481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                              NULL, 0, 0));
715581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
715681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
715781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(NULL);
715881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
715981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
716081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
716181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpStringDerive:
716281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expression context
716381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the expression
716481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @str: the string
716581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @len: the string len in bytes if available
716681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
716781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Do one step of Brzozowski derivation of the expression @exp with
716881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * respect to the input string
716981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
717081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the resulting expression or NULL in case of internal error
717181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
717281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpNodePtr
717381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpStringDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
717481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                   const xmlChar *str, int len) {
717581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    const xmlChar *input;
717681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
717781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((exp == NULL) || (ctxt == NULL) || (str == NULL)) {
717881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(NULL);
717981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
718081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
718181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * check the string is in the dictionnary, if yes use an interned
718281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * copy, otherwise we know it's not an acceptable input
718381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
718481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    input = xmlDictExists(ctxt->dict, str, len);
718581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (input == NULL) {
718681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(forbiddenExp);
718781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
718881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(xmlExpStringDeriveInt(ctxt, exp, input));
718981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
719081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
719181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic int
719281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpCheckCard(xmlExpNodePtr exp, xmlExpNodePtr sub) {
719381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int ret = 1;
719481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
719581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (sub->c_max == -1) {
719681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        if (exp->c_max != -1)
719781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = 0;
719881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    } else if ((exp->c_max >= 0) && (exp->c_max < sub->c_max)) {
719981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ret = 0;
720081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
720181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#if 0
720281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((IS_NILLABLE(sub)) && (!IS_NILLABLE(exp)))
720381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ret = 0;
720481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
720581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
720681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
720781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
720881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
720981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                                        xmlExpNodePtr sub);
721081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
721181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpDivide:
721281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expressions context
721381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the englobing expression
721481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @sub: the subexpression
721581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @mult: the multiple expression
721681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @remain: the remain from the derivation of the multiple
721781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
721881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Check if exp is a multiple of sub, i.e. if there is a finite number n
721981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * so that sub{n} subsume exp
722081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
722181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the multiple value if successful, 0 if it is not a multiple
722281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *         and -1 in case of internel error.
722381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
722481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
722581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic int
722681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpDivide(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub,
722781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard             xmlExpNodePtr *mult, xmlExpNodePtr *remain) {
722881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int i;
722981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr tmp, tmp2;
723081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
723181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (mult != NULL) *mult = NULL;
723281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (remain != NULL) *remain = NULL;
723381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (exp->c_max == -1) return(0);
723481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (IS_NILLABLE(exp) && (!IS_NILLABLE(sub))) return(0);
723581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
723681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    for (i = 1;i <= exp->c_max;i++) {
723781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        sub->ref++;
723881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        tmp = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT,
723981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				 sub, NULL, NULL, i, i);
724081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == NULL) {
724181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(-1);
724281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
724381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (!xmlExpCheckCard(tmp, exp)) {
724481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, tmp);
724581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    continue;
724681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
724781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	tmp2 = xmlExpExpDeriveInt(ctxt, tmp, exp);
724881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp2 == NULL) {
724981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, tmp);
725081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(-1);
725181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
725281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((tmp2 != forbiddenExp) && (IS_NILLABLE(tmp2))) {
725381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (remain != NULL)
725481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        *remain = tmp2;
725581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
725681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        xmlExpFree(ctxt, tmp2);
725781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (mult != NULL)
725881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        *mult = tmp;
725981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
726081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        xmlExpFree(ctxt, tmp);
726181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
726281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Divide succeeded %d\n", i);
726381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
726481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(i);
726581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
726681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp);
726781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp2);
726881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
726981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
727081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    printf("Divide failed\n");
727181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
727281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(0);
727381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
727481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
727581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
727681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpExpDeriveInt:
727781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expressions context
727881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the englobing expression
727981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @sub: the subexpression
728081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
728181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Try to do a step of Brzozowski derivation but at a higher level
728281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * the input being a subexpression.
728381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
728481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns the resulting expression or NULL in case of internal error
728581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
728681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardstatic xmlExpNodePtr
728781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
728881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr ret, tmp, tmp2, tmp3;
728981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    const xmlChar **tab;
729081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    int len, i;
729181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
729281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
729381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * In case of equality and if the expression can only consume a finite
729481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * amount, then the derivation is empty
729581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
729681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((exp == sub) && (exp->c_max >= 0)) {
729781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
729881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("Equal(exp, sub) and finite -> Empty\n");
729981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
730081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(emptyExp);
730181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
730281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
730381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * decompose sub sequence first
730481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
730581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (sub->type == XML_EXP_EMPTY) {
730681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
730781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("Empty(sub) -> Empty\n");
730881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
730981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	exp->ref++;
731081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(exp);
731181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
731281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (sub->type == XML_EXP_SEQ) {
731381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
731481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("Seq(sub) -> decompose\n");
731581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
731681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left);
731781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == NULL)
731881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(NULL);
731981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == forbiddenExp)
732081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
732181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	ret = xmlExpExpDeriveInt(ctxt, tmp, sub->exp_right);
732281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp);
732381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(ret);
732481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
732581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (sub->type == XML_EXP_OR) {
732681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
732781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("Or(sub) -> decompose\n");
732881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
732981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        tmp = xmlExpExpDeriveInt(ctxt, exp, sub->exp_left);
733081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == forbiddenExp)
733181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
733281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (tmp == NULL)
733381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(NULL);
733481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	ret = xmlExpExpDeriveInt(ctxt, exp, sub->exp_right);
733581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((ret == NULL) || (ret == forbiddenExp)) {
733681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, tmp);
733781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
733881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
733981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, tmp, ret, NULL, 0, 0));
734081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
734181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (!xmlExpCheckCard(exp, sub)) {
734281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
734381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        printf("CheckCard(exp, sub) failed -> Forbid\n");
734481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
734581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(forbiddenExp);
734681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
734781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    switch (exp->type) {
734881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_EMPTY:
734981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (sub == emptyExp)
735081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(emptyExp);
735181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
735281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Empty(exp) -> Forbid\n");
735381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
735481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
735581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_FORBID:
735681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
735781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Forbid(exp) -> Forbid\n");
735881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
735981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
736081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_ATOM:
736181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (sub->type == XML_EXP_ATOM) {
736281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        /* TODO: handle wildcards */
736381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (exp->exp_str == sub->exp_str) {
736481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
736581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Atom match -> Empty\n");
736681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
736781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(emptyExp);
736881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                }
736981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
737081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Atom mismatch -> Forbid\n");
737181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
737281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(forbiddenExp);
737381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
737481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if ((sub->type == XML_EXP_COUNT) &&
737581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (sub->exp_max == 1) &&
737681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        (sub->exp_left->type == XML_EXP_ATOM)) {
737781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        /* TODO: handle wildcards */
737881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        if (exp->exp_str == sub->exp_left->exp_str) {
737981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
738081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Atom match -> Empty\n");
738181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
738281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(emptyExp);
738381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
738481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
738581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Atom mismatch -> Forbid\n");
738681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
738781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(forbiddenExp);
738881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
738981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
739081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Compex exp vs Atom -> Forbid\n");
739181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
739281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(forbiddenExp);
739381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_SEQ:
739481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* try to get the sequence consumed only if possible */
739581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (xmlExpCheckCard(exp->exp_left, sub)) {
739681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		/* See if the sequence can be consumed directly */
739781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
739881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Seq trying left only\n");
739981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
740081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
740181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if ((ret != forbiddenExp) && (ret != NULL)) {
740281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
740381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Seq trying left only worked\n");
740481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
740581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    /*
740681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     * TODO: assumption here that we are determinist
740781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     *       i.e. we won't get to a nillable exp left
740881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     *       subset which could be matched by the right
740981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     *       part too.
741081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     * e.g.: (a | b)+,(a | c) and 'a+,a'
741181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     */
741281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    exp->exp_right->ref++;
741381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret,
741481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard					      exp->exp_right, NULL, 0, 0));
741581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
741681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
741781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    } else {
741881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Seq: left too short\n");
741981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
742081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
742181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* Try instead to decompose */
742281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (sub->type == XML_EXP_COUNT) {
742381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		int min, max;
742481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
742581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
742681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("Seq: sub is a count\n");
742781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
742881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left);
742981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (ret == NULL)
743081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(NULL);
743181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (ret != forbiddenExp) {
743281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
743381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Seq , Count match on left\n");
743481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
743581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (sub->exp_max < 0)
743681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        max = -1;
743781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	            else
743881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        max = sub->exp_max -1;
743981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (sub->exp_min > 0)
744081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        min = sub->exp_min -1;
744181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    else
744281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        min = 0;
744381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    exp->exp_right->ref++;
744481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    tmp = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret,
744581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                             exp->exp_right, NULL, 0, 0);
744681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (tmp == NULL)
744781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        return(NULL);
744881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
744981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    sub->exp_left->ref++;
745081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT,
745181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				      sub->exp_left, NULL, NULL, min, max);
745281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (tmp2 == NULL) {
745381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        xmlExpFree(ctxt, tmp);
745481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			return(NULL);
745581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
745681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    ret = xmlExpExpDeriveInt(ctxt, tmp, tmp2);
745781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    xmlExpFree(ctxt, tmp);
745881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    xmlExpFree(ctxt, tmp2);
745981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(ret);
746081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
746181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
746281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    /* we made no progress on structured operations */
746381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    break;
746481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_OR:
746581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
746681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("Or , trying both side\n");
746781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
746881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
746981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL)
747081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
747181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpExpDeriveInt(ctxt, exp->exp_right, sub);
747281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp == NULL) {
747381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		xmlExpFree(ctxt, ret);
747481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
747581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
747681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, tmp, NULL, 0, 0));
747781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        case XML_EXP_COUNT: {
747881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    int min, max;
747981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
748081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (sub->type == XML_EXP_COUNT) {
748181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        /*
748281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		 * Try to see if the loop is completely subsumed
748381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		 */
748481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        tmp = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub->exp_left);
748581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (tmp == NULL)
748681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(NULL);
748781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (tmp == forbiddenExp) {
748881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    int mult;
748981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
749081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
749181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Count, Count inner don't subsume\n");
749281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
749381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    mult = xmlExpDivide(ctxt, sub->exp_left, exp->exp_left,
749481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                        NULL, &tmp);
749581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (mult <= 0) {
749681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
749781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			printf("Count, Count not multiple => forbidden\n");
749881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
749981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                        return(forbiddenExp);
750081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
750181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (sub->exp_max == -1) {
750281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        max = -1;
750381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			if (exp->exp_max == -1) {
750481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    if (exp->exp_min <= sub->exp_min * mult)
750581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			        min = 0;
750681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    else
750781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			        min = exp->exp_min - sub->exp_min * mult;
750881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			} else {
750981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
751081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("Count, Count finite can't subsume infinite\n");
751181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
751281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                            xmlExpFree(ctxt, tmp);
751381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    return(forbiddenExp);
751481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
751581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    } else {
751681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			if (exp->exp_max == -1) {
751781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
751881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("Infinite loop consume mult finite loop\n");
751981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
752081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    if (exp->exp_min > sub->exp_min * mult) {
752181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				max = -1;
752281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				min = exp->exp_min - sub->exp_min * mult;
752381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    } else {
752481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				max = -1;
752581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				min = 0;
752681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    }
752781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			} else {
752881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    if (exp->exp_max < sub->exp_max * mult) {
752981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
753081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				printf("loops max mult mismatch => forbidden\n");
753181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
753281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				xmlExpFree(ctxt, tmp);
753381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				return(forbiddenExp);
753481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    }
753581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    if (sub->exp_max * mult > exp->exp_min)
753681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				min = 0;
753781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    else
753881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				min = exp->exp_min - sub->exp_max * mult;
753981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    max = exp->exp_max - sub->exp_max * mult;
754081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
754181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
754281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else if (!IS_NILLABLE(tmp)) {
754381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    /*
754481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     * TODO: loop here to try to grow if working on finite
754581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     *       blocks.
754681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		     */
754781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
754881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    printf("Count, Count remain not nillable => forbidden\n");
754981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
755081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    xmlExpFree(ctxt, tmp);
755181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(forbiddenExp);
755281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else if (sub->exp_max == -1) {
755381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (exp->exp_max == -1) {
755481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        if (exp->exp_min <= sub->exp_min) {
755581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
755681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("Infinite loops Okay => COUNT(0,Inf)\n");
755781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
755881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                            max = -1;
755981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = 0;
756081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			} else {
756181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
756281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("Infinite loops min => Count(X,Inf)\n");
756381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
756481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                            max = -1;
756581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = exp->exp_min - sub->exp_min;
756681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
756781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    } else if (exp->exp_min > sub->exp_min) {
756881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
756981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			printf("loops min mismatch 1 => forbidden ???\n");
757081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
757181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        xmlExpFree(ctxt, tmp);
757281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        return(forbiddenExp);
757381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    } else {
757481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			max = -1;
757581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			min = 0;
757681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
757781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		} else {
757881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    if (exp->exp_max == -1) {
757981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
758081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			printf("Infinite loop consume finite loop\n");
758181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
758281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        if (exp->exp_min > sub->exp_min) {
758381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    max = -1;
758481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = exp->exp_min - sub->exp_min;
758581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			} else {
758681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    max = -1;
758781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = 0;
758881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
758981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    } else {
759081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		        if (exp->exp_max < sub->exp_max) {
759181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
759281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    printf("loops max mismatch => forbidden\n");
759381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
759481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    xmlExpFree(ctxt, tmp);
759581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    return(forbiddenExp);
759681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			}
759781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			if (sub->exp_max > exp->exp_min)
759881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = 0;
759981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			else
760081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			    min = exp->exp_min - sub->exp_max;
760181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard			max = exp->exp_max - sub->exp_max;
760281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    }
760381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
760481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
760581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("loops match => SEQ(COUNT())\n");
760681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
760781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		exp->exp_left->ref++;
760881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left,
760981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                          NULL, NULL, min, max);
761081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		if (tmp2 == NULL) {
761181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		    return(NULL);
761281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		}
761381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard                ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, tmp, tmp2,
761481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		                         NULL, 0, 0);
761581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(ret);
761681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
761781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp = xmlExpExpDeriveInt(ctxt, exp->exp_left, sub);
761881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp == NULL)
761981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(NULL);
762081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp == forbiddenExp) {
762181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
762281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		printf("loop mismatch => forbidden\n");
762381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
762481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(forbiddenExp);
762581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
762681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_min > 0)
762781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		min = exp->exp_min - 1;
762881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
762981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		min = 0;
763081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (exp->exp_max < 0)
763181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		max = -1;
763281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    else
763381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		max = exp->exp_max - 1;
763481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
763581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
763681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    printf("loop match => SEQ(COUNT())\n");
763781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
763881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    exp->exp_left->ref++;
763981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    tmp2 = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, exp->exp_left,
764081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				      NULL, NULL, min, max);
764181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (tmp2 == NULL)
764281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard		return(NULL);
764381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, tmp, tmp2,
764481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard				     NULL, 0, 0);
764581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(ret);
764681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
764781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
764881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
7649ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard#ifdef DEBUG_DERIV
7650ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    printf("Fallback to derivative\n");
7651ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard#endif
7652ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    if (IS_NILLABLE(sub)) {
7653ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard        if (!(IS_NILLABLE(exp)))
7654ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	    return(forbiddenExp);
7655ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	else
7656ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	    ret = emptyExp;
7657ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard    } else
7658ccb4d41c13bea3c81cf074ed43b84bd686c7d124Daniel Veillard	ret = NULL;
765981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
766081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * here the structured derivation made no progress so
766181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * we use the default token based derivation to force one more step
766281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
766381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (ctxt->tabSize == 0)
766481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        ctxt->tabSize = 40;
766581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
766681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    tab = (const xmlChar **) xmlMalloc(ctxt->tabSize *
766781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                               sizeof(const xmlChar *));
766881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (tab == NULL) {
766981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(NULL);
767081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
767181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
767281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
767381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * collect all the strings accepted by the subexpression on input
767481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
767581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0);
767681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    while (len < 0) {
767781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        const xmlChar **temp;
767854a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	temp = (const xmlChar **) xmlRealloc((xmlChar **) tab, ctxt->tabSize * 2 *
767981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	                                     sizeof(const xmlChar *));
768081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (temp == NULL) {
768154a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	    xmlFree((xmlChar **) tab);
768281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(NULL);
768381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
768481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	tab = temp;
768581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	ctxt->tabSize *= 2;
768681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	len = xmlExpGetStartInt(ctxt, sub, tab, ctxt->tabSize, 0);
768781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
768881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    for (i = 0;i < len;i++) {
768981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        tmp = xmlExpStringDeriveInt(ctxt, exp, tab[i]);
769081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((tmp == NULL) || (tmp == forbiddenExp)) {
769181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, ret);
769254a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	    xmlFree((xmlChar **) tab);
769381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
769481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
769581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	tmp2 = xmlExpStringDeriveInt(ctxt, sub, tab[i]);
769681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((tmp2 == NULL) || (tmp2 == forbiddenExp)) {
769781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, tmp);
769881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, ret);
769954a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	    xmlFree((xmlChar **) tab);
770081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp);
770181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
770281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	tmp3 = xmlExpExpDeriveInt(ctxt, tmp, tmp2);
770381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp);
770481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	xmlExpFree(ctxt, tmp2);
770581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
770681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if ((tmp3 == NULL) || (tmp3 == forbiddenExp)) {
770781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    xmlExpFree(ctxt, ret);
770854a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards	    xmlFree((xmlChar **) tab);
770981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    return(tmp3);
771081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
771181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
771281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	if (ret == NULL)
771381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = tmp3;
771481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	else {
771581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, tmp3, NULL, 0, 0);
771681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    if (ret == NULL) {
771754a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards		xmlFree((xmlChar **) tab);
771881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	        return(NULL);
771981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	    }
772081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	}
772181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
772254a8f67c0504bb1bc17a2e5f139f3128953915d1Rob Richards    xmlFree((xmlChar **) tab);
772381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(ret);
772481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
772581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
772681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard/**
77270090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * xmlExpExpDerive:
77280090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * @ctxt: the expressions context
77290090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * @exp: the englobing expression
77300090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * @sub: the subexpression
77310090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard *
77320090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * Evaluates the expression resulting from @exp consuming a sub expression @sub
77330090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * Based on algebraic derivation and sometimes direct Brzozowski derivation
77340090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * it usually tatkes less than linear time and can handle expressions generating
77350090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * infinite languages.
77360090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard *
77370090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard * Returns the resulting expression or NULL in case of internal error, the
77380090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard *         result must be freed
77390090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard */
77400090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel VeillardxmlExpNodePtr
77410090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel VeillardxmlExpExpDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
77420090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if ((exp == NULL) || (ctxt == NULL) || (sub == NULL))
77430090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        return(NULL);
77440090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
77450090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    /*
77460090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard     * O(1) speedups
77470090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard     */
77480090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) {
77490090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#ifdef DEBUG_DERIV
77500090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	printf("Sub nillable and not exp : can't subsume\n");
77510090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#endif
77520090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        return(forbiddenExp);
77530090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    }
77540090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    if (xmlExpCheckCard(exp, sub) == 0) {
77550090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#ifdef DEBUG_DERIV
77560090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard	printf("sub generate longuer sequances than exp : can't subsume\n");
77570090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard#endif
77580090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard        return(forbiddenExp);
77590090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    }
77600090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard    return(xmlExpExpDeriveInt(ctxt, exp, sub));
77610090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard}
77620090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard
77630090bd524f6dee77bc4bbcad8e2158c5783f35a1Daniel Veillard/**
776481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * xmlExpSubsume:
776581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @ctxt: the expressions context
776681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @exp: the englobing expression
776781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * @sub: the subexpression
776881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
776981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Check whether @exp accepts all the languages accexpted by @sub
777081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * the input being a subexpression.
777181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard *
777281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard * Returns 1 if true 0 if false and -1 in case of failure.
777381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard */
777481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillardint
777581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel VeillardxmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) {
777681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpNodePtr tmp;
777781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
777881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((exp == NULL) || (ctxt == NULL) || (sub == NULL))
777981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
778081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard
778181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
778281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * TODO: speedup by checking the language of sub is a subset of the
778381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     *       language of exp
778481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
778581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    /*
778681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     * O(1) speedups
778781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard     */
778881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (IS_NILLABLE(sub) && (!IS_NILLABLE(exp))) {
778981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
779081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	printf("Sub nillable and not exp : can't subsume\n");
779181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
779281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(0);
779381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
779481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (xmlExpCheckCard(exp, sub) == 0) {
779581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
779681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	printf("sub generate longuer sequances than exp : can't subsume\n");
779781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
779881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(0);
779981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
780081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    tmp = xmlExpExpDeriveInt(ctxt, exp, sub);
780181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#ifdef DEBUG_DERIV
780281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    printf("Result derivation :\n");
780381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    PRINT_EXP(tmp);
780481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif
780581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (tmp == NULL)
780681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(-1);
780781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (tmp == forbiddenExp)
780881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(0);
780981a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if (tmp == emptyExp)
781081a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard	return(1);
781181a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    if ((tmp != NULL) && (IS_NILLABLE(tmp))) {
781281a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        xmlExpFree(ctxt, tmp);
781381a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard        return(1);
781481a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    }
781581a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    xmlExpFree(ctxt, tmp);
781681a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard    return(0);
781781a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard}
7818465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7819465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/************************************************************************
7820465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *									*
7821465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *			Parsing expression 				*
7822465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *									*
7823465a000b1080427bd62d89a925409b7db78616acDaniel Veillard ************************************************************************/
7824465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7825465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic xmlExpNodePtr xmlExpParseExpr(xmlExpCtxtPtr ctxt);
7826465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7827465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#undef CUR
7828465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define CUR (*ctxt->cur)
7829465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#undef NEXT
7830465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define NEXT ctxt->cur++;
7831465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#undef IS_BLANK
7832465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define IS_BLANK(c) ((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))
7833465a000b1080427bd62d89a925409b7db78616acDaniel Veillard#define SKIP_BLANKS while (IS_BLANK(*ctxt->cur)) ctxt->cur++;
7834465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7835465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic int
7836465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParseNumber(xmlExpCtxtPtr ctxt) {
7837465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    int ret = 0;
7838465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7839465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7840465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (CUR == '*') {
7841465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	NEXT
7842465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	return(-1);
7843465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7844465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if ((CUR < '0') || (CUR > '9'))
7845465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(-1);
7846465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while ((CUR >= '0') && (CUR <= '9')) {
7847465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        ret = ret * 10 + (CUR - '0');
7848465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	NEXT
7849465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7850465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
7851465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
7852465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7853465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic xmlExpNodePtr
7854465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParseOr(xmlExpCtxtPtr ctxt) {
7855465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    const char *base;
7856465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr ret;
7857465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    const xmlChar *val;
7858465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7859465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7860465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    base = ctxt->cur;
7861465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (*ctxt->cur == '(') {
7862465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7863465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpParseExpr(ctxt);
7864465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7865465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (*ctxt->cur != ')') {
7866465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    fprintf(stderr, "unbalanced '(' : %s\n", base);
7867465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7868465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7869465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7870465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	NEXT;
7871465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7872465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	goto parse_quantifier;
7873465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7874465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while ((CUR != 0) && (!(IS_BLANK(CUR))) && (CUR != '(') &&
7875465a000b1080427bd62d89a925409b7db78616acDaniel Veillard           (CUR != ')') && (CUR != '|') && (CUR != ',') && (CUR != '{') &&
7876465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	   (CUR != '*') && (CUR != '+') && (CUR != '?') && (CUR != '}'))
7877465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	NEXT;
7878465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    val = xmlDictLookup(ctxt->dict, BAD_CAST base, ctxt->cur - base);
7879465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (val == NULL)
7880465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(NULL);
7881465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ret = xmlExpHashGetEntry(ctxt, XML_EXP_ATOM, NULL, NULL, val, 0, 0);
7882465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (ret == NULL)
7883465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(NULL);
7884465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7885465a000b1080427bd62d89a925409b7db78616acDaniel Veillardparse_quantifier:
7886465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (CUR == '{') {
7887465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        int min, max;
7888465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7889465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7890465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	min = xmlExpParseNumber(ctxt);
7891465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (min < 0) {
7892465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7893465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7894465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7895465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7896465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (CUR == ',') {
7897465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    NEXT
7898465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    max = xmlExpParseNumber(ctxt);
7899465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    SKIP_BLANKS
7900465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	} else
7901465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    max = min;
7902465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (CUR != '}') {
7903465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7904465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7905465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7906465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7907465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7908465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	                         min, max);
7909465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7910465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    } else if (CUR == '?') {
7911465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7912465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7913465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	                         0, 1);
7914465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7915465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    } else if (CUR == '+') {
7916465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7917465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7918465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	                         1, -1);
7919465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7920465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    } else if (CUR == '*') {
7921465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7922465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL,
7923465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	                         0, -1);
7924465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	SKIP_BLANKS
7925465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7926465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
7927465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
7928465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7929465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7930465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic xmlExpNodePtr
7931465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParseSeq(xmlExpCtxtPtr ctxt) {
7932465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr ret, right;
7933465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7934465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ret = xmlExpParseOr(ctxt);
7935465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7936465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while (CUR == '|') {
7937465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7938465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	right = xmlExpParseOr(ctxt);
7939465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (right == NULL) {
7940465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7941465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7942465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7943465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_OR, ret, right, NULL, 0, 0);
7944465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (ret == NULL)
7945465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7946465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7947465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
7948465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
7949465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7950465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic xmlExpNodePtr
7951465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParseExpr(xmlExpCtxtPtr ctxt) {
7952465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr ret, right;
7953465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7954465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ret = xmlExpParseSeq(ctxt);
7955465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7956465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    while (CUR == ',') {
7957465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        NEXT
7958465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	right = xmlExpParseSeq(ctxt);
7959465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (right == NULL) {
7960465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlExpFree(ctxt, ret);
7961465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7962465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
7963465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	ret = xmlExpHashGetEntry(ctxt, XML_EXP_SEQ, ret, right, NULL, 0, 0);
7964465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	if (ret == NULL)
7965465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    return(NULL);
7966465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
7967465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
7968465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
7969465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7970465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
7971465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpParse:
7972465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @ctxt: the expressions context
7973465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @expr: the 0 terminated string
7974465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
7975465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Minimal parser for regexps, it understand the following constructs
7976465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - string terminals
7977465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - choice operator |
7978465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - sequence operator ,
7979465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - subexpressions (...)
7980465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - usual cardinality operators + * and ?
7981465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - finite sequences  { min, max }
7982465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *  - infinite sequences { min, * }
7983465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * There is minimal checkings made especially no checking on strings values
7984465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
7985465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Returns a new expression or NULL in case of failure
7986465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
7987465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpNodePtr
7988465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpParse(xmlExpCtxtPtr ctxt, const char *expr) {
7989465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr ret;
7990465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7991465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ctxt->expr = expr;
7992465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ctxt->cur = expr;
7993465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
7994465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    ret = xmlExpParseExpr(ctxt);
7995465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    SKIP_BLANKS
7996465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (*ctxt->cur != 0) {
7997465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        xmlExpFree(ctxt, ret);
7998465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(NULL);
7999465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
8000465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ret);
8001465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8002465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8003465a000b1080427bd62d89a925409b7db78616acDaniel Veillardstatic void
8004465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpDumpInt(xmlBufferPtr buf, xmlExpNodePtr expr, int glob) {
8005465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    xmlExpNodePtr c;
8006465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8007465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (expr == NULL) return;
8008465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (glob) xmlBufferWriteChar(buf, "(");
8009465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    switch (expr->type) {
8010465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_EMPTY:
8011465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, "empty");
8012465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    break;
8013465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_FORBID:
8014465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, "forbidden");
8015465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    break;
8016465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_ATOM:
8017465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteCHAR(buf, expr->exp_str);
8018465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    break;
8019465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_SEQ:
8020465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_left;
8021465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8022465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8023465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8024465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8025465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, " , ");
8026465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_right;
8027465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8028465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8029465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8030465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8031465a000b1080427bd62d89a925409b7db78616acDaniel Veillard            break;
8032465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_OR:
8033465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_left;
8034465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8035465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8036465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8037465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8038465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, " | ");
8039465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_right;
8040465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8041465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8042465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8043465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8044465a000b1080427bd62d89a925409b7db78616acDaniel Veillard            break;
8045465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        case XML_EXP_COUNT: {
8046465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    char rep[40];
8047465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8048465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    c = expr->exp_left;
8049465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR))
8050465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 1);
8051465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    else
8052465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        xmlExpDumpInt(buf, c, 0);
8053465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    if ((expr->exp_min == 0) && (expr->exp_max == 1)) {
8054465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[0] = '?';
8055465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[1] = 0;
8056465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if ((expr->exp_min == 0) && (expr->exp_max == -1)) {
8057465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[0] = '*';
8058465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[1] = 0;
8059465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if ((expr->exp_min == 1) && (expr->exp_max == -1)) {
8060465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[0] = '+';
8061465a000b1080427bd62d89a925409b7db78616acDaniel Veillard		rep[1] = 0;
8062465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if (expr->exp_max == expr->exp_min) {
8063465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        snprintf(rep, 39, "{%d}", expr->exp_min);
8064465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else if (expr->exp_max < 0) {
8065465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        snprintf(rep, 39, "{%d,inf}", expr->exp_min);
8066465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    } else {
8067465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	        snprintf(rep, 39, "{%d,%d}", expr->exp_min, expr->exp_max);
8068465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    }
8069465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    rep[39] = 0;
8070465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    xmlBufferWriteChar(buf, rep);
8071465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    break;
8072465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	}
8073465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	default:
8074465a000b1080427bd62d89a925409b7db78616acDaniel Veillard	    fprintf(stderr, "Error in tree\n");
8075465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    }
8076465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (glob)
8077465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        xmlBufferWriteChar(buf, ")");
8078465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8079465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
8080465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpDump:
8081465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @buf:  a buffer to receive the output
8082465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @expr:  the compiled expression
8083465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8084465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Serialize the expression as compiled to the buffer
8085465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
8086465a000b1080427bd62d89a925409b7db78616acDaniel Veillardvoid
80875eee767ca9b30a8e8c54808c82060ceb41630d6aDaniel VeillardxmlExpDump(xmlBufferPtr buf, xmlExpNodePtr expr) {
80885eee767ca9b30a8e8c54808c82060ceb41630d6aDaniel Veillard    if ((buf == NULL) || (expr == NULL))
8089465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return;
80905eee767ca9b30a8e8c54808c82060ceb41630d6aDaniel Veillard    xmlExpDumpInt(buf, expr, 0);
8091465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8092465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8093465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
8094465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpMaxToken:
8095465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @expr: a compiled expression
8096465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8097465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Indicate the maximum number of input a expression can accept
8098465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8099465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Returns the maximum length or -1 in case of error
8100465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
8101465a000b1080427bd62d89a925409b7db78616acDaniel Veillardint
8102465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpMaxToken(xmlExpNodePtr expr) {
8103465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (expr == NULL)
8104465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(-1);
8105465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(expr->c_max);
8106465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8107465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8108465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
8109465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpCtxtNbNodes:
8110465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @ctxt: an expression context
8111465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8112465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Debugging facility provides the number of allocated nodes at a that point
8113465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8114465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Returns the number of nodes in use or -1 in case of error
8115465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
8116465a000b1080427bd62d89a925409b7db78616acDaniel Veillardint
8117465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt) {
8118465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (ctxt == NULL)
8119465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(-1);
8120465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ctxt->nb_nodes);
8121465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8122465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
8123465a000b1080427bd62d89a925409b7db78616acDaniel Veillard/**
8124465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * xmlExpCtxtNbCons:
8125465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * @ctxt: an expression context
8126465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8127465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Debugging facility provides the number of allocated nodes over lifetime
8128465a000b1080427bd62d89a925409b7db78616acDaniel Veillard *
8129465a000b1080427bd62d89a925409b7db78616acDaniel Veillard * Returns the number of nodes ever allocated or -1 in case of error
8130465a000b1080427bd62d89a925409b7db78616acDaniel Veillard */
8131465a000b1080427bd62d89a925409b7db78616acDaniel Veillardint
8132465a000b1080427bd62d89a925409b7db78616acDaniel VeillardxmlExpCtxtNbCons(xmlExpCtxtPtr ctxt) {
8133465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    if (ctxt == NULL)
8134465a000b1080427bd62d89a925409b7db78616acDaniel Veillard        return(-1);
8135465a000b1080427bd62d89a925409b7db78616acDaniel Veillard    return(ctxt->nb_cons);
8136465a000b1080427bd62d89a925409b7db78616acDaniel Veillard}
8137465a000b1080427bd62d89a925409b7db78616acDaniel Veillard
813881a8ec6b1315a9c14ce648de9c3a949ea62e48cfDaniel Veillard#endif /* LIBXML_EXPR_ENABLED */
81395d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#define bottom_xmlregexp
81405d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#include "elfgcchack.h"
81414255d504151db75c17f85192ce74f45dd2d65533Daniel Veillard#endif /* LIBXML_REGEXP_ENABLED */
8142