version 1.1.1.1, 2012/02/21 23:37:58
|
version 1.1.1.3, 2014/06/15 19:53:28
|
Line 1
|
Line 1
|
/* |
/* |
* regexp.c: generic and extensible Regular Expression engine |
* regexp.c: generic and extensible Regular Expression engine |
* |
* |
* Basically designed with the purpose of compiling regexps for | * Basically designed with the purpose of compiling regexps for |
* the variety of validation/shemas mechanisms now available in |
* the variety of validation/shemas mechanisms now available in |
* XML related specifications these include: |
* XML related specifications these include: |
* - XML-1.0 DTD validation |
* - XML-1.0 DTD validation |
Line 44
|
Line 44
|
|
|
#define MAX_PUSH 10000000 |
#define MAX_PUSH 10000000 |
|
|
|
#ifdef ERROR |
|
#undef ERROR |
|
#endif |
#define ERROR(str) \ |
#define ERROR(str) \ |
ctxt->error = XML_REGEXP_COMPILE_ERROR; \ |
ctxt->error = XML_REGEXP_COMPILE_ERROR; \ |
xmlRegexpErrCompile(ctxt, str); |
xmlRegexpErrCompile(ctxt, str); |
Line 65
|
Line 68
|
* |
* |
* macro to flag unimplemented blocks |
* macro to flag unimplemented blocks |
*/ |
*/ |
#define TODO \ | #define TODO \ |
xmlGenericError(xmlGenericErrorContext, \ |
xmlGenericError(xmlGenericErrorContext, \ |
"Unimplemented block at %s:%d\n", \ |
"Unimplemented block at %s:%d\n", \ |
__FILE__, __LINE__); |
__FILE__, __LINE__); |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Datatypes and structures * | * Datatypes and structures * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
/* |
/* |
Line 219 struct _xmlRegTrans {
|
Line 222 struct _xmlRegTrans {
|
struct _xmlAutomataState { |
struct _xmlAutomataState { |
xmlRegStateType type; |
xmlRegStateType type; |
xmlRegMarkedType mark; |
xmlRegMarkedType mark; |
|
xmlRegMarkedType markd; |
xmlRegMarkedType reached; |
xmlRegMarkedType reached; |
int no; |
int no; |
int maxTrans; |
int maxTrans; |
Line 361 void xmlAutomataSetFlags(xmlAutomataPtr am, int flags)
|
Line 365 void xmlAutomataSetFlags(xmlAutomataPtr am, int flags)
|
|
|
/************************************************************************ |
/************************************************************************ |
* * |
* * |
* Regexp memory error handler * | * Regexp memory error handler * |
* * |
* * |
************************************************************************/ |
************************************************************************/ |
/** |
/** |
Line 408 xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const ch
|
Line 412 xmlRegexpErrCompile(xmlRegParserCtxtPtr ctxt, const ch
|
} |
} |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Allocation/Deallocation * | * Allocation/Deallocation * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
static int xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt); |
static int xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt); |
Line 931 xmlRegFreeParserCtxt(xmlRegParserCtxtPtr ctxt) {
|
Line 935 xmlRegFreeParserCtxt(xmlRegParserCtxtPtr ctxt) {
|
} |
} |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Display of Data structures * | * Display of Data structures * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
static void |
static void |
Line 1140 xmlRegPrintTrans(FILE *output, xmlRegTransPtr trans) {
|
Line 1144 xmlRegPrintTrans(FILE *output, xmlRegTransPtr trans) {
|
fprintf(output, "char %c ", trans->atom->codepoint); |
fprintf(output, "char %c ", trans->atom->codepoint); |
fprintf(output, "atom %d, to %d\n", trans->atom->no, trans->to); |
fprintf(output, "atom %d, to %d\n", trans->atom->no, trans->to); |
} |
} |
| |
static void |
static void |
xmlRegPrintState(FILE *output, xmlRegStatePtr state) { |
xmlRegPrintState(FILE *output, xmlRegStatePtr state) { |
int i; |
int i; |
Line 1154 xmlRegPrintState(FILE *output, xmlRegStatePtr state) {
|
Line 1158 xmlRegPrintState(FILE *output, xmlRegStatePtr state) {
|
fprintf(output, "START "); |
fprintf(output, "START "); |
if (state->type == XML_REGEXP_FINAL_STATE) |
if (state->type == XML_REGEXP_FINAL_STATE) |
fprintf(output, "FINAL "); |
fprintf(output, "FINAL "); |
| |
fprintf(output, "%d, %d transitions:\n", state->no, state->nbTrans); |
fprintf(output, "%d, %d transitions:\n", state->no, state->nbTrans); |
for (i = 0;i < state->nbTrans; i++) { |
for (i = 0;i < state->nbTrans; i++) { |
xmlRegPrintTrans(output, &(state->trans[i])); |
xmlRegPrintTrans(output, &(state->trans[i])); |
Line 1204 xmlRegPrintCtxt(FILE *output, xmlRegParserCtxtPtr ctxt
|
Line 1208 xmlRegPrintCtxt(FILE *output, xmlRegParserCtxtPtr ctxt
|
#endif |
#endif |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Finite Automata structures manipulations * |
* Finite Automata structures manipulations * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
static void | static void |
xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom, |
xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom, |
int neg, xmlRegAtomType type, int start, int end, |
int neg, xmlRegAtomType type, int start, int end, |
xmlChar *blockName) { |
xmlChar *blockName) { |
Line 1249 xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAto
|
Line 1253 xmlRegAtomAddRange(xmlRegParserCtxtPtr ctxt, xmlRegAto
|
return; |
return; |
range->blockName = blockName; |
range->blockName = blockName; |
atom->ranges[atom->nbRanges++] = range; |
atom->ranges[atom->nbRanges++] = range; |
| |
} |
} |
|
|
static int |
static int |
Line 1280 xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) {
|
Line 1284 xmlRegGetCounter(xmlRegParserCtxtPtr ctxt) {
|
return(ctxt->nbCounters++); |
return(ctxt->nbCounters++); |
} |
} |
|
|
static int | static int |
xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) { |
xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) { |
if (atom == NULL) { |
if (atom == NULL) { |
ERROR("atom push: atom is NULL"); |
ERROR("atom push: atom is NULL"); |
Line 1312 xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr
|
Line 1316 xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr
|
return(0); |
return(0); |
} |
} |
|
|
static void | static void |
xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target, |
xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr target, |
int from) { |
int from) { |
if (target->maxTransTo == 0) { |
if (target->maxTransTo == 0) { |
Line 1340 xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlReg
|
Line 1344 xmlRegStateAddTransTo(xmlRegParserCtxtPtr ctxt, xmlReg
|
target->nbTransTo++; |
target->nbTransTo++; |
} |
} |
|
|
static void | static void |
xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, |
xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state, |
xmlRegAtomPtr atom, xmlRegStatePtr target, |
xmlRegAtomPtr atom, xmlRegStatePtr target, |
int counter, int count) { |
int counter, int count) { |
Line 1406 xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegSt
|
Line 1410 xmlRegStateAddTrans(xmlRegParserCtxtPtr ctxt, xmlRegSt
|
printf("counted %d\n", counter); |
printf("counted %d\n", counter); |
else if (atom == NULL) |
else if (atom == NULL) |
printf("epsilon transition\n"); |
printf("epsilon transition\n"); |
else if (atom != NULL) | else if (atom != NULL) |
xmlRegPrintAtom(stdout, atom); |
xmlRegPrintAtom(stdout, atom); |
#endif |
#endif |
|
|
Line 1560 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
Line 1564 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
*/ |
*/ |
xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to); |
xmlFAGenerateEpsilonTransition(ctxt, atom->stop, to); |
#ifdef DV |
#ifdef DV |
} else if ((to == NULL) && (atom->quant != XML_REGEXP_QUANT_RANGE) && | } else if ((to == NULL) && (atom->quant != XML_REGEXP_QUANT_RANGE) && |
(atom->quant != XML_REGEXP_QUANT_ONCE)) { |
(atom->quant != XML_REGEXP_QUANT_ONCE)) { |
to = xmlRegNewState(ctxt); |
to = xmlRegNewState(ctxt); |
xmlRegStatePush(ctxt, to); |
xmlRegStatePush(ctxt, to); |
Line 1574 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
Line 1578 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
/* |
/* |
* transition done to the state after end of atom. |
* transition done to the state after end of atom. |
* 1. set transition from atom start to new state |
* 1. set transition from atom start to new state |
* 2. set transition from atom end to this state. | * 2. set transition from atom end to this state. |
*/ |
*/ |
if (to == NULL) { |
if (to == NULL) { |
xmlFAGenerateEpsilonTransition(ctxt, atom->start, 0); |
xmlFAGenerateEpsilonTransition(ctxt, atom->start, 0); |
Line 1618 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
Line 1622 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
/* |
/* |
* duplicate a transition based on atom to count next |
* duplicate a transition based on atom to count next |
* occurences after 1. We cannot loop to atom->start |
* occurences after 1. We cannot loop to atom->start |
* directly because we need an epsilon transition to | * directly because we need an epsilon transition to |
* newstate. |
* newstate. |
*/ |
*/ |
/* ???? For some reason it seems we never reach that |
/* ???? For some reason it seems we never reach that |
Line 1677 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
Line 1681 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
break; |
break; |
} |
} |
return(0); |
return(0); |
} | } |
if ((atom->min == 0) && (atom->max == 0) && |
if ((atom->min == 0) && (atom->max == 0) && |
(atom->quant == XML_REGEXP_QUANT_RANGE)) { |
(atom->quant == XML_REGEXP_QUANT_RANGE)) { |
/* |
/* |
Line 1703 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
Line 1707 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
else { |
else { |
return(-1); |
return(-1); |
} |
} |
} | } |
end = to; |
end = to; |
if ((atom->quant == XML_REGEXP_QUANT_MULT) || | if ((atom->quant == XML_REGEXP_QUANT_MULT) || |
(atom->quant == XML_REGEXP_QUANT_PLUS)) { |
(atom->quant == XML_REGEXP_QUANT_PLUS)) { |
/* |
/* |
* Do not pollute the target state by adding transitions from |
* Do not pollute the target state by adding transitions from |
Line 1713 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
Line 1717 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
* So isolate with an epsilon transition. |
* So isolate with an epsilon transition. |
*/ |
*/ |
xmlRegStatePtr tmp; |
xmlRegStatePtr tmp; |
| |
tmp = xmlRegNewState(ctxt); |
tmp = xmlRegNewState(ctxt); |
if (tmp != NULL) |
if (tmp != NULL) |
xmlRegStatePush(ctxt, tmp); |
xmlRegStatePush(ctxt, tmp); |
Line 1742 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
Line 1746 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
atom->quant = XML_REGEXP_QUANT_ONCE; |
atom->quant = XML_REGEXP_QUANT_ONCE; |
xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1); |
xmlRegStateAddTrans(ctxt, to, atom, to, -1, -1); |
break; |
break; |
case XML_REGEXP_QUANT_RANGE: | case XML_REGEXP_QUANT_RANGE: |
#if DV_test |
#if DV_test |
if (atom->min == 0) { |
if (atom->min == 0) { |
xmlFAGenerateEpsilonTransition(ctxt, from, to); |
xmlFAGenerateEpsilonTransition(ctxt, from, to); |
Line 1759 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
Line 1763 xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xml
|
* xmlFAReduceEpsilonTransitions: |
* xmlFAReduceEpsilonTransitions: |
* @ctxt: a regexp parser context |
* @ctxt: a regexp parser context |
* @fromnr: the from state |
* @fromnr: the from state |
* @tonr: the to state | * @tonr: the to state |
* @counter: should that transition be associated to a counted |
* @counter: should that transition be associated to a counted |
* |
* |
*/ |
*/ |
Line 1803 xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt
|
Line 1807 xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt
|
int newto = to->trans[transnr].to; |
int newto = to->trans[transnr].to; |
|
|
xmlRegStateAddTrans(ctxt, from, NULL, |
xmlRegStateAddTrans(ctxt, from, NULL, |
ctxt->states[newto], | ctxt->states[newto], |
-1, to->trans[transnr].count); |
-1, to->trans[transnr].count); |
} else { |
} else { |
#ifdef DEBUG_REGEXP_GRAPH |
#ifdef DEBUG_REGEXP_GRAPH |
Line 1825 xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt
|
Line 1829 xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt
|
int newto = to->trans[transnr].to; |
int newto = to->trans[transnr].to; |
|
|
if (to->trans[transnr].counter >= 0) { |
if (to->trans[transnr].counter >= 0) { |
xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom, | xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom, |
ctxt->states[newto], | ctxt->states[newto], |
to->trans[transnr].counter, -1); |
to->trans[transnr].counter, -1); |
} else { |
} else { |
xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom, | xmlRegStateAddTrans(ctxt, from, to->trans[transnr].atom, |
ctxt->states[newto], counter, -1); |
ctxt->states[newto], counter, -1); |
} |
} |
} |
} |
Line 1841 xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt
|
Line 1845 xmlFAReduceEpsilonTransitions(xmlRegParserCtxtPtr ctxt
|
* xmlFAEliminateSimpleEpsilonTransitions: |
* xmlFAEliminateSimpleEpsilonTransitions: |
* @ctxt: a regexp parser context |
* @ctxt: a regexp parser context |
* |
* |
* Eliminating general epsilon transitions can get costly in the general | * Eliminating general epsilon transitions can get costly in the general |
* algorithm due to the large amount of generated new transitions and |
* algorithm due to the large amount of generated new transitions and |
* associated comparisons. However for simple epsilon transition used just |
* associated comparisons. However for simple epsilon transition used just |
* to separate building blocks when generating the automata this can be |
* to separate building blocks when generating the automata this can be |
Line 1877 xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtx
|
Line 1881 xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtx
|
#ifdef DEBUG_REGEXP_GRAPH |
#ifdef DEBUG_REGEXP_GRAPH |
printf("Found simple epsilon trans from start %d to %d\n", |
printf("Found simple epsilon trans from start %d to %d\n", |
statenr, newto); |
statenr, newto); |
#endif | #endif |
} else { |
} else { |
#ifdef DEBUG_REGEXP_GRAPH |
#ifdef DEBUG_REGEXP_GRAPH |
printf("Found simple epsilon trans from %d to %d\n", |
printf("Found simple epsilon trans from %d to %d\n", |
statenr, newto); |
statenr, newto); |
#endif | #endif |
for (i = 0;i < state->nbTransTo;i++) { |
for (i = 0;i < state->nbTransTo;i++) { |
tmp = ctxt->states[state->transTo[i]]; |
tmp = ctxt->states[state->transTo[i]]; |
for (j = 0;j < tmp->nbTrans;j++) { |
for (j = 0;j < tmp->nbTrans;j++) { |
Line 1890 xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtx
|
Line 1894 xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtx
|
#ifdef DEBUG_REGEXP_GRAPH |
#ifdef DEBUG_REGEXP_GRAPH |
printf("Changed transition %d on %d to go to %d\n", |
printf("Changed transition %d on %d to go to %d\n", |
j, tmp->no, newto); |
j, tmp->no, newto); |
#endif | #endif |
tmp->trans[j].to = -1; |
tmp->trans[j].to = -1; |
xmlRegStateAddTrans(ctxt, tmp, tmp->trans[j].atom, |
xmlRegStateAddTrans(ctxt, tmp, tmp->trans[j].atom, |
ctxt->states[newto], | ctxt->states[newto], |
tmp->trans[j].counter, |
tmp->trans[j].counter, |
tmp->trans[j].count); |
tmp->trans[j].count); |
} |
} |
Line 1907 xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtx
|
Line 1911 xmlFAEliminateSimpleEpsilonTransitions(xmlRegParserCtx
|
state->type = XML_REGEXP_UNREACH_STATE; |
state->type = XML_REGEXP_UNREACH_STATE; |
|
|
} |
} |
| |
} |
} |
} |
} |
} |
} |
Line 2109 xmlFACompareRanges(xmlRegRangePtr range1, xmlRegRangeP
|
Line 2113 xmlFACompareRanges(xmlRegRangePtr range1, xmlRegRangeP
|
/* |
/* |
* just check all codepoints in the range for acceptance, |
* just check all codepoints in the range for acceptance, |
* this is usually way cheaper since done only once at |
* this is usually way cheaper since done only once at |
* compilation than testing over and over at runtime or | * compilation than testing over and over at runtime or |
* pushing too many states when evaluating. |
* pushing too many states when evaluating. |
*/ |
*/ |
if (((range1->neg == 0) && (range2->neg != 0)) || |
if (((range1->neg == 0) && (range2->neg != 0)) || |
Line 2586 xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlR
|
Line 2590 xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlR
|
|
|
if (state == NULL) |
if (state == NULL) |
return(ret); |
return(ret); |
|
if (state->markd == XML_REGEXP_MARK_VISITED) |
|
return(ret); |
|
|
if (ctxt->flags & AM_AUTOMATA_RNG) |
if (ctxt->flags & AM_AUTOMATA_RNG) |
deep = 0; |
deep = 0; |
Line 2603 xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlR
|
Line 2609 xmlFARecurseDeterminism(xmlRegParserCtxtPtr ctxt, xmlR
|
if (t1->atom == NULL) { |
if (t1->atom == NULL) { |
if (t1->to < 0) |
if (t1->to < 0) |
continue; |
continue; |
|
state->markd = XML_REGEXP_MARK_VISITED; |
res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to], |
res = xmlFARecurseDeterminism(ctxt, ctxt->states[t1->to], |
to, atom); |
to, atom); |
|
state->markd = 0; |
if (res == 0) { |
if (res == 0) { |
ret = 0; |
ret = 0; |
/* t1->nd = 1; */ |
/* t1->nd = 1; */ |
Line 2773 xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
|
Line 2781 xmlFAComputesDeterminism(xmlRegParserCtxtPtr ctxt) {
|
} |
} |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Routines to check input against transition atoms * |
* Routines to check input against transition atoms * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
static int |
static int |
Line 2804 xmlRegCheckCharacterRange(xmlRegAtomType type, int cod
|
Line 2812 xmlRegCheckCharacterRange(xmlRegAtomType type, int cod
|
case XML_REGEXP_NOTINITNAME: |
case XML_REGEXP_NOTINITNAME: |
neg = !neg; |
neg = !neg; |
case XML_REGEXP_INITNAME: |
case XML_REGEXP_INITNAME: |
ret = (IS_LETTER(codepoint) || | ret = (IS_LETTER(codepoint) || |
(codepoint == '_') || (codepoint == ':')); |
(codepoint == '_') || (codepoint == ':')); |
break; |
break; |
case XML_REGEXP_NOTNAMECHAR: |
case XML_REGEXP_NOTNAMECHAR: |
Line 3052 xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint
|
Line 3060 xmlRegCheckCharacter(xmlRegAtomPtr atom, int codepoint
|
} |
} |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Saving and restoring state of an execution context * |
* Saving and restoring state of an execution context * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
#ifdef DEBUG_REGEXP_EXEC |
#ifdef DEBUG_REGEXP_EXEC |
Line 3165 xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) {
|
Line 3173 xmlFARegExecRollBack(xmlRegExecCtxtPtr exec) {
|
} |
} |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Verifier, running an input against a compiled regexp * |
* Verifier, running an input against a compiled regexp * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
static int |
static int |
Line 3199 xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content
|
Line 3207 xmlFARegExec(xmlRegexpPtr comp, const xmlChar *content
|
memset(exec->counts, 0, comp->nbCounters * sizeof(int)); |
memset(exec->counts, 0, comp->nbCounters * sizeof(int)); |
} else |
} else |
exec->counts = NULL; |
exec->counts = NULL; |
while ((exec->status == 0) && | while ((exec->status == 0) && (exec->state != NULL) && |
((exec->inputString[exec->index] != 0) || |
((exec->inputString[exec->index] != 0) || |
((exec->state != NULL) && |
((exec->state != NULL) && |
(exec->state->type != XML_REGEXP_FINAL_STATE)))) { |
(exec->state->type != XML_REGEXP_FINAL_STATE)))) { |
Line 3453 error:
|
Line 3461 error:
|
} |
} |
xmlFree(exec->rollbacks); |
xmlFree(exec->rollbacks); |
} |
} |
|
if (exec->state == NULL) |
|
return(-1); |
if (exec->counts != NULL) |
if (exec->counts != NULL) |
xmlFree(exec->counts); |
xmlFree(exec->counts); |
if (exec->status == 0) |
if (exec->status == 0) |
Line 3466 error:
|
Line 3476 error:
|
} |
} |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Progressive interface to the verifier one atom at a time * |
* Progressive interface to the verifier one atom at a time * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
#ifdef DEBUG_ERR |
#ifdef DEBUG_ERR |
static void testerr(xmlRegExecCtxtPtr exec); |
static void testerr(xmlRegExecCtxtPtr exec); |
Line 3585 xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, co
|
Line 3595 xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, co
|
#endif |
#endif |
if (exec->inputStackMax == 0) { |
if (exec->inputStackMax == 0) { |
exec->inputStackMax = 4; |
exec->inputStackMax = 4; |
exec->inputStack = (xmlRegInputTokenPtr) | exec->inputStack = (xmlRegInputTokenPtr) |
xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken)); |
xmlMalloc(exec->inputStackMax * sizeof(xmlRegInputToken)); |
if (exec->inputStack == NULL) { |
if (exec->inputStack == NULL) { |
xmlRegexpErrMemory(NULL, "pushing input string"); |
xmlRegexpErrMemory(NULL, "pushing input string"); |
Line 3614 xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, co
|
Line 3624 xmlFARegExecSaveInputString(xmlRegExecCtxtPtr exec, co
|
|
|
/** |
/** |
* xmlRegStrEqualWildcard: |
* xmlRegStrEqualWildcard: |
* @expStr: the string to be evaluated | * @expStr: the string to be evaluated |
* @valStr: the validation string |
* @valStr: the validation string |
* |
* |
* Checks if both strings are equal or have the same content. "*" |
* Checks if both strings are equal or have the same content. "*" |
* can be used as a wildcard in @valStr; "|" is used as a seperator of | * can be used as a wildcard in @valStr; "|" is used as a seperator of |
* substrings in both @expStr and @valStr. |
* substrings in both @expStr and @valStr. |
* |
* |
* Returns 1 if the comparison is satisfied and the number of substrings |
* Returns 1 if the comparison is satisfied and the number of substrings |
Line 3684 xmlRegCompactPushString(xmlRegExecCtxtPtr exec,
|
Line 3694 xmlRegCompactPushString(xmlRegExecCtxtPtr exec,
|
|
|
if ((comp == NULL) || (comp->compact == NULL) || (comp->stringMap == NULL)) |
if ((comp == NULL) || (comp->compact == NULL) || (comp->stringMap == NULL)) |
return(-1); |
return(-1); |
| |
if (value == NULL) { |
if (value == NULL) { |
/* |
/* |
* are we at a final state ? |
* are we at a final state ? |
Line 3705 xmlRegCompactPushString(xmlRegExecCtxtPtr exec,
|
Line 3715 xmlRegCompactPushString(xmlRegExecCtxtPtr exec,
|
for (i = 0;i < comp->nbstrings;i++) { |
for (i = 0;i < comp->nbstrings;i++) { |
target = comp->compact[state * (comp->nbstrings + 1) + i + 1]; |
target = comp->compact[state * (comp->nbstrings + 1) + i + 1]; |
if ((target > 0) && (target <= comp->nbstates)) { |
if ((target > 0) && (target <= comp->nbstates)) { |
target--; /* to avoid 0 */ | target--; /* to avoid 0 */ |
if (xmlRegStrEqualWildcard(comp->stringMap[i], value)) { |
if (xmlRegStrEqualWildcard(comp->stringMap[i], value)) { |
exec->index = target; | exec->index = target; |
if ((exec->callback != NULL) && (comp->transdata != NULL)) { |
if ((exec->callback != NULL) && (comp->transdata != NULL)) { |
exec->callback(exec->data, value, |
exec->callback(exec->data, value, |
comp->transdata[state * comp->nbstrings + i], data); |
comp->transdata[state * comp->nbstrings + i], data); |
Line 3841 xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, c
|
Line 3851 xmlRegExecPushStringInternal(xmlRegExecCtxtPtr exec, c
|
continue; |
continue; |
counter = &exec->comp->counters[t->counter]; |
counter = &exec->comp->counters[t->counter]; |
count = exec->counts[t->counter]; |
count = exec->counts[t->counter]; |
if ((count < counter->max) && | if ((count < counter->max) && |
(t->atom != NULL) && |
(t->atom != NULL) && |
(xmlStrEqual(value, t->atom->valuep))) { |
(xmlStrEqual(value, t->atom->valuep))) { |
ret = 0; |
ret = 0; |
Line 4199 xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
|
Line 4209 xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
|
int maxval; |
int maxval; |
int nb = 0; |
int nb = 0; |
|
|
if ((exec == NULL) || (nbval == NULL) || (nbneg == NULL) || | if ((exec == NULL) || (nbval == NULL) || (nbneg == NULL) || |
(values == NULL) || (*nbval <= 0)) |
(values == NULL) || (*nbval <= 0)) |
return(-1); |
return(-1); |
|
|
Line 4305 xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
|
Line 4315 xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
|
values[nb++] = (xmlChar *) atom->valuep; |
values[nb++] = (xmlChar *) atom->valuep; |
(*nbval)++; |
(*nbval)++; |
} |
} |
} | } |
} |
} |
for (transno = 0; |
for (transno = 0; |
(transno < state->nbTrans) && (nb < maxval); |
(transno < state->nbTrans) && (nb < maxval); |
Line 4332 xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
|
Line 4342 xmlRegExecGetValues(xmlRegExecCtxtPtr exec, int err,
|
values[nb++] = (xmlChar *) atom->valuep; |
values[nb++] = (xmlChar *) atom->valuep; |
(*nbneg)++; |
(*nbneg)++; |
} |
} |
} | } |
} |
} |
} |
} |
return(0); |
return(0); |
Line 4563 progress:
|
Line 4573 progress:
|
} |
} |
#endif |
#endif |
/************************************************************************ |
/************************************************************************ |
* * | * * |
* Parser for the Schemas Datatype Regular Expressions * |
* Parser for the Schemas Datatype Regular Expressions * |
* http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#regexs * |
* http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#regexs * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
/** |
/** |
Line 4595 xmlFAIsChar(xmlRegParserCtxtPtr ctxt) {
|
Line 4605 xmlFAIsChar(xmlRegParserCtxtPtr ctxt) {
|
* |
* |
* [27] charProp ::= IsCategory | IsBlock |
* [27] charProp ::= IsCategory | IsBlock |
* [28] IsCategory ::= Letters | Marks | Numbers | Punctuation | |
* [28] IsCategory ::= Letters | Marks | Numbers | Punctuation | |
* Separators | Symbols | Others | * Separators | Symbols | Others |
* [29] Letters ::= 'L' [ultmo]? |
* [29] Letters ::= 'L' [ultmo]? |
* [30] Marks ::= 'M' [nce]? |
* [30] Marks ::= 'M' [nce]? |
* [31] Numbers ::= 'N' [dlo]? |
* [31] Numbers ::= 'N' [dlo]? |
Line 4610 xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
|
Line 4620 xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
|
int cur; |
int cur; |
xmlRegAtomType type = (xmlRegAtomType) 0; |
xmlRegAtomType type = (xmlRegAtomType) 0; |
xmlChar *blockName = NULL; |
xmlChar *blockName = NULL; |
| |
cur = CUR; |
cur = CUR; |
if (cur == 'L') { |
if (cur == 'L') { |
NEXT; |
NEXT; |
Line 4782 xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
|
Line 4792 xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
|
NEXT; |
NEXT; |
start = ctxt->cur; |
start = ctxt->cur; |
cur = CUR; |
cur = CUR; |
if (((cur >= 'a') && (cur <= 'z')) || | if (((cur >= 'a') && (cur <= 'z')) || |
((cur >= 'A') && (cur <= 'Z')) || | ((cur >= 'A') && (cur <= 'Z')) || |
((cur >= '0') && (cur <= '9')) || | ((cur >= '0') && (cur <= '9')) || |
(cur == 0x2D)) { |
(cur == 0x2D)) { |
NEXT; |
NEXT; |
cur = CUR; |
cur = CUR; |
while (((cur >= 'a') && (cur <= 'z')) || | while (((cur >= 'a') && (cur <= 'z')) || |
((cur >= 'A') && (cur <= 'Z')) || | ((cur >= 'A') && (cur <= 'Z')) || |
((cur >= '0') && (cur <= '9')) || | ((cur >= '0') && (cur <= '9')) || |
(cur == 0x2D)) { |
(cur == 0x2D)) { |
NEXT; |
NEXT; |
cur = CUR; |
cur = CUR; |
Line 4816 xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
|
Line 4826 xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
|
* xmlFAParseCharClassEsc: |
* xmlFAParseCharClassEsc: |
* @ctxt: a regexp parser context |
* @ctxt: a regexp parser context |
* |
* |
* [23] charClassEsc ::= ( SingleCharEsc | MultiCharEsc | catEsc | complEsc ) | * [23] charClassEsc ::= ( SingleCharEsc | MultiCharEsc | catEsc | complEsc ) |
* [24] SingleCharEsc ::= '\' [nrt\|.?*+(){}#x2D#x5B#x5D#x5E] |
* [24] SingleCharEsc ::= '\' [nrt\|.?*+(){}#x2D#x5B#x5D#x5E] |
* [25] catEsc ::= '\p{' charProp '}' |
* [25] catEsc ::= '\p{' charProp '}' |
* [26] complEsc ::= '\P{' charProp '}' |
* [26] complEsc ::= '\P{' charProp '}' |
Line 4913 xmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) {
|
Line 4923 xmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) {
|
xmlRegAtomType type = XML_REGEXP_ANYSPACE; |
xmlRegAtomType type = XML_REGEXP_ANYSPACE; |
|
|
switch (cur) { |
switch (cur) { |
case 's': | case 's': |
type = XML_REGEXP_ANYSPACE; |
type = XML_REGEXP_ANYSPACE; |
break; |
break; |
case 'S': | case 'S': |
type = XML_REGEXP_NOTSPACE; |
type = XML_REGEXP_NOTSPACE; |
break; |
break; |
case 'i': | case 'i': |
type = XML_REGEXP_INITNAME; |
type = XML_REGEXP_INITNAME; |
break; |
break; |
case 'I': | case 'I': |
type = XML_REGEXP_NOTINITNAME; |
type = XML_REGEXP_NOTINITNAME; |
break; |
break; |
case 'c': | case 'c': |
type = XML_REGEXP_NAMECHAR; |
type = XML_REGEXP_NAMECHAR; |
break; |
break; |
case 'C': | case 'C': |
type = XML_REGEXP_NOTNAMECHAR; |
type = XML_REGEXP_NOTNAMECHAR; |
break; |
break; |
case 'd': | case 'd': |
type = XML_REGEXP_DECIMAL; |
type = XML_REGEXP_DECIMAL; |
break; |
break; |
case 'D': | case 'D': |
type = XML_REGEXP_NOTDECIMAL; |
type = XML_REGEXP_NOTDECIMAL; |
break; |
break; |
case 'w': | case 'w': |
type = XML_REGEXP_REALCHAR; |
type = XML_REGEXP_REALCHAR; |
break; |
break; |
case 'W': | case 'W': |
type = XML_REGEXP_NOTREALCHAR; |
type = XML_REGEXP_NOTREALCHAR; |
break; |
break; |
} |
} |
Line 4960 xmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) {
|
Line 4970 xmlFAParseCharClassEsc(xmlRegParserCtxtPtr ctxt) {
|
* xmlFAParseCharRange: |
* xmlFAParseCharRange: |
* @ctxt: a regexp parser context |
* @ctxt: a regexp parser context |
* |
* |
* [17] charRange ::= seRange | XmlCharRef | XmlCharIncDash | * [17] charRange ::= seRange | XmlCharRef | XmlCharIncDash |
* [18] seRange ::= charOrEsc '-' charOrEsc |
* [18] seRange ::= charOrEsc '-' charOrEsc |
* [20] charOrEsc ::= XmlChar | SingleCharEsc |
* [20] charOrEsc ::= XmlChar | SingleCharEsc |
* [21] XmlChar ::= [^\#x2D#x5B#x5D] |
* [21] XmlChar ::= [^\#x2D#x5B#x5D] |
Line 5075 xmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) {
|
Line 5085 xmlFAParsePosCharGroup(xmlRegParserCtxtPtr ctxt) {
|
* |
* |
* [13] charGroup ::= posCharGroup | negCharGroup | charClassSub |
* [13] charGroup ::= posCharGroup | negCharGroup | charClassSub |
* [15] negCharGroup ::= '^' posCharGroup |
* [15] negCharGroup ::= '^' posCharGroup |
* [16] charClassSub ::= ( posCharGroup | negCharGroup ) '-' charClassExpr | * [16] charClassSub ::= ( posCharGroup | negCharGroup ) '-' charClassExpr |
* [12] charClassExpr ::= '[' charGroup ']' |
* [12] charClassExpr ::= '[' charGroup ']' |
*/ |
*/ |
static void |
static void |
Line 5323 xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegState
|
Line 5333 xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegState
|
previous = ctxt->state; |
previous = ctxt->state; |
ret = xmlFAParsePiece(ctxt); |
ret = xmlFAParsePiece(ctxt); |
if (ret != 0) { |
if (ret != 0) { |
if (xmlFAGenerateTransitions(ctxt, previous, | if (xmlFAGenerateTransitions(ctxt, previous, |
(CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0) |
(CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0) |
return(-1); |
return(-1); |
previous = ctxt->state; |
previous = ctxt->state; |
Line 5332 xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegState
|
Line 5342 xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, xmlRegState
|
while ((ret != 0) && (ctxt->error == 0)) { |
while ((ret != 0) && (ctxt->error == 0)) { |
ret = xmlFAParsePiece(ctxt); |
ret = xmlFAParsePiece(ctxt); |
if (ret != 0) { |
if (ret != 0) { |
if (xmlFAGenerateTransitions(ctxt, previous, | if (xmlFAGenerateTransitions(ctxt, previous, |
(CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0) |
(CUR=='|' || CUR==')') ? to : NULL, ctxt->atom) < 0) |
return(-1); |
return(-1); |
previous = ctxt->state; |
previous = ctxt->state; |
Line 5370 xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
|
Line 5380 xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
|
end = ctxt->state; |
end = ctxt->state; |
while ((CUR == '|') && (ctxt->error == 0)) { |
while ((CUR == '|') && (ctxt->error == 0)) { |
NEXT; |
NEXT; |
|
if (CUR == 0) { |
|
ERROR("expecting a branch after |") |
|
return; |
|
} |
ctxt->state = start; |
ctxt->state = start; |
ctxt->end = NULL; |
ctxt->end = NULL; |
xmlFAParseBranch(ctxt, end); |
xmlFAParseBranch(ctxt, end); |
Line 5381 xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
|
Line 5395 xmlFAParseRegExp(xmlRegParserCtxtPtr ctxt, int top) {
|
} |
} |
|
|
/************************************************************************ |
/************************************************************************ |
* * | * * |
* The basic API * | * The basic API * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
/** |
/** |
Line 5570 xmlRegFreeRegexp(xmlRegexpPtr regexp) {
|
Line 5584 xmlRegFreeRegexp(xmlRegexpPtr regexp) {
|
|
|
#ifdef LIBXML_AUTOMATA_ENABLED |
#ifdef LIBXML_AUTOMATA_ENABLED |
/************************************************************************ |
/************************************************************************ |
* * | * * |
* The Automata interface * | * The Automata interface * |
* * | * * |
************************************************************************/ |
************************************************************************/ |
|
|
/** |
/** |
Line 5843 xmlAutomataNewNegTrans(xmlAutomataPtr am, xmlAutomataS
|
Line 5857 xmlAutomataNewNegTrans(xmlAutomataPtr am, xmlAutomataS
|
* |
* |
* If @to is NULL, this creates first a new target state in the automata |
* If @to is NULL, this creates first a new target state in the automata |
* and then adds a transition from the @from state to the target state |
* and then adds a transition from the @from state to the target state |
* activated by a succession of input of value @token and @token2 and | * activated by a succession of input of value @token and @token2 and |
* whose number is between @min and @max |
* whose number is between @min and @max |
* |
* |
* Returns the target state or NULL in case of error |
* Returns the target state or NULL in case of error |
Line 5997 xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomat
|
Line 6011 xmlAutomataNewCountTrans(xmlAutomataPtr am, xmlAutomat
|
* |
* |
* If @to is NULL, this creates first a new target state in the automata |
* If @to is NULL, this creates first a new target state in the automata |
* and then adds a transition from the @from state to the target state |
* and then adds a transition from the @from state to the target state |
* activated by a succession of input of value @token and @token2 and whose | * activated by a succession of input of value @token and @token2 and whose |
* number is between @min and @max, moreover that transition can only be | * number is between @min and @max, moreover that transition can only be |
* crossed once. |
* crossed once. |
* |
* |
* Returns the target state or NULL in case of error |
* Returns the target state or NULL in case of error |
Line 6040 xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomat
|
Line 6054 xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomat
|
str[lenn + lenp + 1] = 0; |
str[lenn + lenp + 1] = 0; |
|
|
atom->valuep = str; |
atom->valuep = str; |
} | } |
atom->data = data; |
atom->data = data; |
atom->quant = XML_REGEXP_QUANT_ONCEONLY; |
atom->quant = XML_REGEXP_QUANT_ONCEONLY; |
atom->min = min; |
atom->min = min; |
Line 6063 xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomat
|
Line 6077 xmlAutomataNewOnceTrans2(xmlAutomataPtr am, xmlAutomat
|
return(to); |
return(to); |
} |
} |
|
|
|
|
|
|
|
|
/** |
/** |
* xmlAutomataNewOnceTrans: |
* xmlAutomataNewOnceTrans: |
* @am: an automata |
* @am: an automata |
Line 6132 xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomata
|
Line 6146 xmlAutomataNewOnceTrans(xmlAutomataPtr am, xmlAutomata
|
*/ |
*/ |
xmlAutomataStatePtr |
xmlAutomataStatePtr |
xmlAutomataNewState(xmlAutomataPtr am) { |
xmlAutomataNewState(xmlAutomataPtr am) { |
xmlAutomataStatePtr to; | xmlAutomataStatePtr to; |
|
|
if (am == NULL) |
if (am == NULL) |
return(NULL); |
return(NULL); |
Line 6199 xmlAutomataNewAllTrans(xmlAutomataPtr am, xmlAutomataS
|
Line 6213 xmlAutomataNewAllTrans(xmlAutomataPtr am, xmlAutomataS
|
* |
* |
* Returns the counter number or -1 in case of error |
* Returns the counter number or -1 in case of error |
*/ |
*/ |
int | int |
xmlAutomataNewCounter(xmlAutomataPtr am, int min, int max) { |
xmlAutomataNewCounter(xmlAutomataPtr am, int min, int max) { |
int ret; |
int ret; |
|
|
Line 6271 xmlAutomataNewCounterTrans(xmlAutomataPtr am, xmlAutom
|
Line 6285 xmlAutomataNewCounterTrans(xmlAutomataPtr am, xmlAutom
|
* |
* |
* Returns the compiled regexp or NULL in case of error |
* Returns the compiled regexp or NULL in case of error |
*/ |
*/ |
xmlRegexpPtr | xmlRegexpPtr |
xmlAutomataCompile(xmlAutomataPtr am) { |
xmlAutomataCompile(xmlAutomataPtr am) { |
xmlRegexpPtr ret; |
xmlRegexpPtr ret; |
|
|
Line 6291 xmlAutomataCompile(xmlAutomataPtr am) {
|
Line 6305 xmlAutomataCompile(xmlAutomataPtr am) {
|
* |
* |
* Returns 1 if true, 0 if not, and -1 in case of error |
* Returns 1 if true, 0 if not, and -1 in case of error |
*/ |
*/ |
int | int |
xmlAutomataIsDeterminist(xmlAutomataPtr am) { |
xmlAutomataIsDeterminist(xmlAutomataPtr am) { |
int ret; |
int ret; |
|
|
Line 6344 xmlExpNewCtxt(int maxNodes, xmlDictPtr dict) {
|
Line 6358 xmlExpNewCtxt(int maxNodes, xmlDictPtr dict) {
|
|
|
if (maxNodes <= 4096) |
if (maxNodes <= 4096) |
maxNodes = 4096; |
maxNodes = 4096; |
| |
ret = (xmlExpCtxtPtr) xmlMalloc(sizeof(xmlExpCtxt)); |
ret = (xmlExpCtxtPtr) xmlMalloc(sizeof(xmlExpCtxt)); |
if (ret == NULL) |
if (ret == NULL) |
return(NULL); |
return(NULL); |
Line 6398 xmlExpFreeCtxt(xmlExpCtxtPtr ctxt) {
|
Line 6412 xmlExpFreeCtxt(xmlExpCtxtPtr ctxt) {
|
/* #define DEBUG_DERIV */ |
/* #define DEBUG_DERIV */ |
|
|
/* |
/* |
* TODO: | * TODO: |
* - Wildcards |
* - Wildcards |
* - public API for creation |
* - public API for creation |
* |
* |
Line 6466 static unsigned short
|
Line 6480 static unsigned short
|
xmlExpHashNameComputeKey(const xmlChar *name) { |
xmlExpHashNameComputeKey(const xmlChar *name) { |
unsigned short value = 0L; |
unsigned short value = 0L; |
char ch; |
char ch; |
| |
if (name != NULL) { |
if (name != NULL) { |
value += 30 * (*name); |
value += 30 * (*name); |
while ((ch = *name++) != 0) { |
while ((ch = *name++) != 0) { |
Line 6485 xmlExpHashComputeKey(xmlExpNodeType type, xmlExpNodePt
|
Line 6499 xmlExpHashComputeKey(xmlExpNodeType type, xmlExpNodePt
|
xmlExpNodePtr right) { |
xmlExpNodePtr right) { |
unsigned long value; |
unsigned long value; |
unsigned short ret; |
unsigned short ret; |
| |
switch (type) { |
switch (type) { |
case XML_EXP_SEQ: |
case XML_EXP_SEQ: |
value = left->key; |
value = left->key; |
Line 6626 xmlExpHashGetEntry(xmlExpCtxtPtr ctxt, xmlExpNodeType
|
Line 6640 xmlExpHashGetEntry(xmlExpCtxtPtr ctxt, xmlExpNodeType
|
left->exp_left->ref++; |
left->exp_left->ref++; |
tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_left, tmp, |
tmp = xmlExpHashGetEntry(ctxt, XML_EXP_OR, left->exp_left, tmp, |
NULL, 0, 0); |
NULL, 0, 0); |
| |
xmlExpFree(ctxt, left); |
xmlExpFree(ctxt, left); |
return(tmp); |
return(tmp); |
} |
} |
Line 6683 xmlExpHashGetEntry(xmlExpCtxtPtr ctxt, xmlExpNodeType
|
Line 6697 xmlExpHashGetEntry(xmlExpCtxtPtr ctxt, xmlExpNodeType
|
return(right); |
return(right); |
} |
} |
kbase = xmlExpHashComputeKey(type, left, right); |
kbase = xmlExpHashComputeKey(type, left, right); |
} else | } else |
return(NULL); |
return(NULL); |
|
|
key = kbase % ctxt->size; |
key = kbase % ctxt->size; |
Line 6824 xmlExpRef(xmlExpNodePtr exp) {
|
Line 6838 xmlExpRef(xmlExpNodePtr exp) {
|
* xmlExpNewAtom: |
* xmlExpNewAtom: |
* @ctxt: the expression context |
* @ctxt: the expression context |
* @name: the atom name |
* @name: the atom name |
* @len: the atom name lenght in byte (or -1); | * @len: the atom name length in byte (or -1); |
* |
* |
* Get the atom associated to this name from that context |
* Get the atom associated to this name from that context |
* |
* |
Line 6924 xmlExpNewRange(xmlExpCtxtPtr ctxt, xmlExpNodePtr subse
|
Line 6938 xmlExpNewRange(xmlExpCtxtPtr ctxt, xmlExpNodePtr subse
|
************************************************************************/ |
************************************************************************/ |
|
|
static int |
static int |
xmlExpGetLanguageInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, | xmlExpGetLanguageInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, |
const xmlChar**list, int len, int nb) { |
const xmlChar**list, int len, int nb) { |
int tmp, tmp2; |
int tmp, tmp2; |
tail: |
tail: |
Line 6961 tail:
|
Line 6975 tail:
|
* @ctxt: the expression context |
* @ctxt: the expression context |
* @exp: the expression |
* @exp: the expression |
* @langList: where to store the tokens |
* @langList: where to store the tokens |
* @len: the allocated lenght of @list | * @len: the allocated length of @list |
* |
* |
* Find all the strings used in @exp and store them in @list |
* Find all the strings used in @exp and store them in @list |
* |
* |
Line 6969 tail:
|
Line 6983 tail:
|
* -2 if there is more than @len strings |
* -2 if there is more than @len strings |
*/ |
*/ |
int |
int |
xmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, | xmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, |
const xmlChar**langList, int len) { |
const xmlChar**langList, int len) { |
if ((ctxt == NULL) || (exp == NULL) || (langList == NULL) || (len <= 0)) |
if ((ctxt == NULL) || (exp == NULL) || (langList == NULL) || (len <= 0)) |
return(-1); |
return(-1); |
Line 6977 xmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr ex
|
Line 6991 xmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr ex
|
} |
} |
|
|
static int |
static int |
xmlExpGetStartInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, | xmlExpGetStartInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, |
const xmlChar**list, int len, int nb) { |
const xmlChar**list, int len, int nb) { |
int tmp, tmp2; |
int tmp, tmp2; |
tail: |
tail: |
Line 7027 tail:
|
Line 7041 tail:
|
* @ctxt: the expression context |
* @ctxt: the expression context |
* @exp: the expression |
* @exp: the expression |
* @tokList: where to store the tokens |
* @tokList: where to store the tokens |
* @len: the allocated lenght of @list | * @len: the allocated length of @list |
* |
* |
* Find all the strings that appears at the start of the languages |
* Find all the strings that appears at the start of the languages |
* accepted by @exp and store them in @list. E.g. for (a, b) | c |
* accepted by @exp and store them in @list. E.g. for (a, b) | c |
Line 7037 tail:
|
Line 7051 tail:
|
* -2 if there is more than @len strings |
* -2 if there is more than @len strings |
*/ |
*/ |
int |
int |
xmlExpGetStart(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, | xmlExpGetStart(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, |
const xmlChar**tokList, int len) { |
const xmlChar**tokList, int len) { |
if ((ctxt == NULL) || (exp == NULL) || (tokList == NULL) || (len <= 0)) |
if ((ctxt == NULL) || (exp == NULL) || (tokList == NULL) || (len <= 0)) |
return(-1); |
return(-1); |
Line 7734 xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr e
|
Line 7748 xmlExpExpDeriveInt(xmlExpCtxtPtr ctxt, xmlExpNodePtr e
|
xmlFree((xmlChar **) tab); |
xmlFree((xmlChar **) tab); |
return(ret); |
return(ret); |
} |
} |
| |
/** |
/** |
* xmlExpExpDerive: |
* xmlExpExpDerive: |
* @ctxt: the expressions context |
* @ctxt: the expressions context |
Line 7786 xmlExpExpDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
|
Line 7800 xmlExpExpDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp,
|
int |
int |
xmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { |
xmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, xmlExpNodePtr sub) { |
xmlExpNodePtr tmp; |
xmlExpNodePtr tmp; |
| |
if ((exp == NULL) || (ctxt == NULL) || (sub == NULL)) |
if ((exp == NULL) || (ctxt == NULL) || (sub == NULL)) |
return(-1); |
return(-1); |
|
|
Line 7830 xmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, x
|
Line 7844 xmlExpSubsume(xmlExpCtxtPtr ctxt, xmlExpNodePtr exp, x
|
|
|
/************************************************************************ |
/************************************************************************ |
* * |
* * |
* Parsing expression * | * Parsing expression * |
* * |
* * |
************************************************************************/ |
************************************************************************/ |
|
|
Line 7934 parse_quantifier:
|
Line 7948 parse_quantifier:
|
ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL, |
ret = xmlExpHashGetEntry(ctxt, XML_EXP_COUNT, ret, NULL, NULL, |
0, -1); |
0, -1); |
SKIP_BLANKS |
SKIP_BLANKS |
} | } |
return(ret); |
return(ret); |
} |
} |
|
|
Line 8056 xmlExpDumpInt(xmlBufferPtr buf, xmlExpNodePtr expr, in
|
Line 8070 xmlExpDumpInt(xmlBufferPtr buf, xmlExpNodePtr expr, in
|
break; |
break; |
case XML_EXP_COUNT: { |
case XML_EXP_COUNT: { |
char rep[40]; |
char rep[40]; |
| |
c = expr->exp_left; |
c = expr->exp_left; |
if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR)) |
if ((c->type == XML_EXP_SEQ) || (c->type == XML_EXP_OR)) |
xmlExpDumpInt(buf, c, 1); |
xmlExpDumpInt(buf, c, 1); |