xmlRegexpPtr ret;
ret = (xmlRegexpPtr) xmlMalloc(sizeof(xmlRegexp));
- if (ret == NULL)
+ if (ret == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "out of memory compiling regexp\n");
return(NULL);
+ }
memset(ret, 0, sizeof(xmlRegexp));
ret->string = ctxt->string;
- ctxt->string = NULL;
ret->nbStates = ctxt->nbStates;
- ctxt->nbStates = 0;
ret->states = ctxt->states;
- ctxt->states = NULL;
ret->nbAtoms = ctxt->nbAtoms;
- ctxt->nbAtoms = 0;
ret->atoms = ctxt->atoms;
- ctxt->atoms = NULL;
ret->nbCounters = ctxt->nbCounters;
- ctxt->nbCounters = 0;
ret->counters = ctxt->counters;
- ctxt->counters = NULL;
ret->determinist = ctxt->determinist;
if ((ret->determinist != 0) &&
*/
stateRemap = xmlMalloc(ret->nbStates * sizeof(int));
+ if (stateRemap == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "out of memory compiling regexp\n");
+ xmlFree(ret);
+ return(NULL);
+ }
for (i = 0;i < ret->nbStates;i++) {
if (ret->states[i] != NULL) {
stateRemap[i] = nbstates;
printf("Final: %d states\n", nbstates);
#endif
stringMap = xmlMalloc(ret->nbAtoms * sizeof(char *));
+ if (stringMap == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "out of memory compiling regexp\n");
+ xmlFree(stateRemap);
+ xmlFree(ret);
+ return(NULL);
+ }
stringRemap = xmlMalloc(ret->nbAtoms * sizeof(int));
+ if (stringRemap == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "out of memory compiling regexp\n");
+ xmlFree(stringMap);
+ xmlFree(stateRemap);
+ xmlFree(ret);
+ return(NULL);
+ }
for (i = 0;i < ret->nbAtoms;i++) {
if ((ret->atoms[i]->type == XML_REGEXP_STRING) &&
(ret->atoms[i]->quant == XML_REGEXP_QUANT_ONCE)) {
if (j >= nbatoms) {
stringRemap[i] = nbatoms;
stringMap[nbatoms] = xmlStrdup(value);
+ if (stringMap[nbatoms] == NULL) {
+ for (i = 0;i < nbatoms;i++)
+ xmlFree(stringMap[i]);
+ xmlFree(stringRemap);
+ xmlFree(stringMap);
+ xmlFree(stateRemap);
+ xmlFree(ret);
+ return(NULL);
+ }
nbatoms++;
}
} else {
for (i = 0;i < nbatoms;i++)
xmlFree(stringMap[i]);
xmlFree(stringMap);
- goto fail_compact;
+ xmlFree(ret);
+ return(NULL);
}
}
#ifdef DEBUG_COMPACTION
printf("Final: %d atoms\n", nbatoms);
#endif
+ transitions = (int *) xmlMalloc((nbstates + 1) *
+ (nbatoms + 1) * sizeof(int));
+ if (transitions == NULL) {
+ xmlFree(stateRemap);
+ xmlFree(stringRemap);
+ xmlFree(stringMap);
+ xmlFree(ret);
+ return(NULL);
+ }
+ memset(transitions, 0, (nbstates + 1) * (nbatoms + 1) * sizeof(int));
/*
* Allocate the transition table. The first entry for each
* state correspond to the state type.
*/
- transitions = (int *) xmlMalloc(nbstates * (nbatoms + 1) * sizeof(int));
transdata = NULL;
- memset(transitions, 0, nbstates * (nbatoms + 1) * sizeof(int));
for (i = 0;i < ret->nbStates;i++) {
int stateno, atomno, targetno, prev;
if (transdata != NULL)
memset(transdata, 0,
nbstates * nbatoms * sizeof(void *));
+ else {
+ xmlGenericError(xmlGenericErrorContext,
+ "out of memory compiling regexp\n");
+ break;
+ }
}
targetno = stateRemap[trans->to];
/*
prev = transitions[stateno * (nbatoms + 1) + atomno + 1];
if (prev != 0) {
if (prev != targetno + 1) {
- printf("not determinist\n");
ret->determinist = 0;
#ifdef DEBUG_COMPACTION
printf("Indet: state %d trans %d, atom %d to %d : %d to %d\n",
for (i = 0;i < nbatoms;i++)
xmlFree(stringMap[i]);
xmlFree(stringMap);
- goto fail_compact;
+ goto not_determ;
}
} else {
#if 0
xmlFree(stateRemap);
xmlFree(stringRemap);
}
-fail_compact:
+not_determ:
+ ctxt->string = NULL;
+ ctxt->nbStates = 0;
+ ctxt->states = NULL;
+ ctxt->nbAtoms = 0;
+ ctxt->atoms = NULL;
+ ctxt->nbCounters = 0;
+ ctxt->counters = NULL;
return(ret);
}
return(ctxt->nbCounters++);
}
-static void
+static int
xmlRegAtomPush(xmlRegParserCtxtPtr ctxt, xmlRegAtomPtr atom) {
if (atom == NULL) {
ERROR("atom push: atom is NULL");
- return;
+ return(-1);
}
if (ctxt->maxAtoms == 0) {
ctxt->maxAtoms = 4;
if (ctxt->atoms == NULL) {
ERROR("atom push: allocation failed");
ctxt->maxAtoms = 0;
- return;
+ return(-1);
}
} else if (ctxt->nbAtoms >= ctxt->maxAtoms) {
xmlRegAtomPtr *tmp;
if (tmp == NULL) {
ERROR("atom push: allocation failed");
ctxt->maxAtoms /= 2;
- return;
+ return(-1);
}
ctxt->atoms = tmp;
}
atom->no = ctxt->nbAtoms;
ctxt->atoms[ctxt->nbAtoms++] = atom;
+ return(0);
}
static void
state->nbTrans++;
}
-static void
+static int
xmlRegStatePush(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr state) {
+ if (state == NULL) return(-1);
if (ctxt->maxStates == 0) {
ctxt->maxStates = 4;
ctxt->states = (xmlRegStatePtr *) xmlMalloc(ctxt->maxStates *
if (ctxt->states == NULL) {
ERROR("add range: allocation failed");
ctxt->maxStates = 0;
- return;
+ return(-1);
}
} else if (ctxt->nbStates >= ctxt->maxStates) {
xmlRegStatePtr *tmp;
if (tmp == NULL) {
ERROR("add range: allocation failed");
ctxt->maxStates /= 2;
- return;
+ return(-1);
}
ctxt->states = tmp;
}
state->no = ctxt->nbStates;
ctxt->states[ctxt->nbStates++] = state;
+ return(0);
}
/**
* @to: the target state or NULL for building a new one
* @atom: the atom generating the transition
*
+ * Returns 0 if succes and -1 in case of error.
*/
-static void
+static int
xmlFAGenerateTransitions(xmlRegParserCtxtPtr ctxt, xmlRegStatePtr from,
xmlRegStatePtr to, xmlRegAtomPtr atom) {
if (atom == NULL) {
ERROR("genrate transition: atom == NULL");
- return;
+ return(-1);
}
if (atom->type == XML_REGEXP_SUBREG) {
/*
* this is a subexpression handling one should not need to
* create a new node excep for XML_REGEXP_QUANT_RANGE.
*/
- xmlRegAtomPush(ctxt, atom);
+ if (xmlRegAtomPush(ctxt, atom) < 0) {
+ return(-1);
+ }
if ((to != NULL) && (atom->stop != to) &&
(atom->quant != XML_REGEXP_QUANT_RANGE)) {
/*
default:
break;
}
- return;
+ return(0);
} else {
if (to == NULL) {
to = xmlRegNewState(ctxt);
- xmlRegStatePush(ctxt, to);
+ if (to != NULL)
+ xmlRegStatePush(ctxt, to);
+ else {
+ return(-1);
+ }
+ }
+ if (xmlRegAtomPush(ctxt, atom) < 0) {
+ return(-1);
}
xmlRegStateAddTrans(ctxt, from, atom, to, -1, -1);
- xmlRegAtomPush(ctxt, atom);
ctxt->state = to;
}
switch (atom->quant) {
default:
break;
}
+ return(0);
}
/**
int statenr, transnr;
xmlRegStatePtr state;
+ if (ctxt->states == NULL) return;
+
+
/*
* build the completed transitions bypassing the epsilons
* Use a marking algorithm to avoid loops
for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
state = ctxt->states[statenr];
if (state != NULL)
- state->reached = 0;
+ state->reached = XML_REGEXP_MARK_NORMAL;
}
state = ctxt->states[0];
if (state != NULL)
- state->reached = 1;
+ state->reached = XML_REGEXP_MARK_START;
while (state != NULL) {
xmlRegStatePtr target = NULL;
- state->reached = 2;
+ state->reached = XML_REGEXP_MARK_VISITED;
/*
* Mark all state reachable from the current reachable state
*/
if (ctxt->states[newto] == NULL)
continue;
- if (ctxt->states[newto]->reached == 0) {
- ctxt->states[newto]->reached = 1;
+ if (ctxt->states[newto]->reached == XML_REGEXP_MARK_NORMAL) {
+ ctxt->states[newto]->reached = XML_REGEXP_MARK_START;
target = ctxt->states[newto];
}
}
if (target == NULL) {
for (statenr = 1;statenr < ctxt->nbStates;statenr++) {
state = ctxt->states[statenr];
- if ((state != NULL) && (state->reached == 1)) {
+ if ((state != NULL) && (state->reached ==
+ XML_REGEXP_MARK_START)) {
target = state;
break;
}
}
for (statenr = 0;statenr < ctxt->nbStates;statenr++) {
state = ctxt->states[statenr];
- if ((state != NULL) && (state->reached == 0)) {
+ if ((state != NULL) && (state->reached == XML_REGEXP_MARK_NORMAL)) {
#ifdef DEBUG_REGEXP_GRAPH
printf("Removed unreachable state %d\n", statenr);
#endif
if (comp == NULL)
return(NULL);
+ if ((comp->compact == NULL) && (comp->states == NULL))
+ return(NULL);
exec = (xmlRegExecCtxtPtr) xmlMalloc(sizeof(xmlRegExecCtxt));
if (exec == NULL) {
return(NULL);
return(exec->status);
}
+/**
+ * xmlRegExecPushString2:
+ * @exec: a regexp execution context or NULL to indicate the end
+ * @value: the first string token input
+ * @value2: the second string token input
+ * @data: data associated to the token to reuse in callbacks
+ *
+ * Push one input token in the execution context
+ *
+ * Returns: 1 if the regexp reached a final state, 0 if non-final, and
+ * a negative value in case of error.
+ */
+int
+xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value,
+ const xmlChar *value2, void *data) {
+ xmlChar buf[150];
+ int lenn, lenp, ret;
+ xmlChar *str;
+
+ if (exec == NULL)
+ return(-1);
+ if (exec->comp == NULL)
+ return(-1);
+ if (exec->status != 0)
+ return(exec->status);
+
+ if (value2 == NULL)
+ return(xmlRegExecPushString(exec, value, data));
+
+ lenn = strlen((char *) value2);
+ lenp = strlen((char *) value);
+
+ if (150 < lenn + lenp + 2) {
+ str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
+ if (str == NULL) {
+ exec->status = -1;
+ return(-1);
+ }
+ } else {
+ str = buf;
+ }
+ memcpy(&str[0], value, lenp);
+ str[lenp] = '|';
+ memcpy(&str[lenp + 1], value2, lenn);
+ str[lenn + lenp + 1] = 0;
+
+ if (exec->comp->compact != NULL)
+ ret = xmlRegCompactPushString(exec, exec->comp, str, data);
+ else
+ ret = xmlRegExecPushString(exec, str, data);
+
+ if (str != buf)
+ xmlFree(buf);
+ return(ret);
+}
+
#if 0
static int
xmlRegExecPushChar(xmlRegExecCtxtPtr exec, int UCS) {
static void
xmlFAParseCharProp(xmlRegParserCtxtPtr ctxt) {
int cur;
- xmlRegAtomType type = 0;
+ xmlRegAtomType type = (xmlRegAtomType) 0;
xmlChar *blockName = NULL;
cur = CUR;
* @ctxt: a regexp parser context
*
* [8] QuantExact ::= [0-9]+
+ *
+ * Returns 0 if success or -1 in case of error
*/
static int
xmlFAParseQuantExact(xmlRegParserCtxtPtr ctxt) {
* @first: is taht the first
*
* [2] branch ::= piece*
+ 8
*/
-static void
+static int
xmlFAParseBranch(xmlRegParserCtxtPtr ctxt, int first) {
xmlRegStatePtr previous;
xmlRegAtomPtr prevatom = NULL;
ret = xmlFAParsePiece(ctxt);
if (ret != 0) {
if (first) {
- xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom);
+ if (xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom) < 0)
+ return(-1);
previous = ctxt->state;
} else {
prevatom = ctxt->atom;
ret = xmlFAParsePiece(ctxt);
if (ret != 0) {
if (first) {
- xmlFAGenerateTransitions(ctxt, previous, NULL, ctxt->atom);
+ if (xmlFAGenerateTransitions(ctxt, previous, NULL,
+ ctxt->atom) < 0)
+ return(-1);
} else {
- xmlFAGenerateTransitions(ctxt, previous, NULL, prevatom);
+ if (xmlFAGenerateTransitions(ctxt, previous, NULL,
+ prevatom) < 0)
+ return(-1);
prevatom = ctxt->atom;
}
previous = ctxt->state;
}
}
if (!first) {
- xmlFAGenerateTransitions(ctxt, previous, ctxt->end, prevatom);
+ if (xmlFAGenerateTransitions(ctxt, previous, ctxt->end, prevatom) < 0)
+ return(-1);
}
+ return(0);
}
/**
/* initialize the parser */
ctxt->end = NULL;
ctxt->start = ctxt->state = xmlRegNewState(ctxt);
- xmlRegStatePush(ctxt, ctxt->start);
+ if (ctxt->start == NULL) {
+ xmlFreeAutomata(ctxt);
+ return(NULL);
+ }
+ if (xmlRegStatePush(ctxt, ctxt->start) < 0) {
+ xmlRegFreeState(ctxt->start);
+ xmlFreeAutomata(ctxt);
+ return(NULL);
+ }
return(ctxt);
}
if ((am == NULL) || (from == NULL) || (token == NULL))
return(NULL);
atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
+ if (atom == NULL)
+ return(NULL);
atom->data = data;
if (atom == NULL)
return(NULL);
atom->valuep = xmlStrdup(token);
- xmlFAGenerateTransitions(am, from, to, atom);
+ if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
+ xmlRegFreeAtom(atom);
+ return(NULL);
+ }
+ if (to == NULL)
+ return(am->state);
+ return(to);
+}
+
+/**
+ * xmlAutomataNewTransition2:
+ * @am: an automata
+ * @from: the starting point of the transition
+ * @to: the target point of the transition or NULL
+ * @token: the first input string associated to that transition
+ * @token2: the second input string associated to that transition
+ * @data: data passed to the callback function if the transition is activated
+ *
+ * If @to is NULL, this create first a new target state in the automata
+ * and then adds a transition from the @from state to the target state
+ * activated by the value of @token
+ *
+ * Returns the target state or NULL in case of error
+ */
+xmlAutomataStatePtr
+xmlAutomataNewTransition2(xmlAutomataPtr am, xmlAutomataStatePtr from,
+ xmlAutomataStatePtr to, const xmlChar *token,
+ const xmlChar *token2, void *data) {
+ xmlRegAtomPtr atom;
+
+ if ((am == NULL) || (from == NULL) || (token == NULL))
+ return(NULL);
+ atom = xmlRegNewAtom(am, XML_REGEXP_STRING);
+ atom->data = data;
+ if (atom == NULL)
+ return(NULL);
+ if ((token2 == NULL) || (*token2 == 0)) {
+ atom->valuep = xmlStrdup(token);
+ } else {
+ int lenn, lenp;
+ xmlChar *str;
+
+ lenn = strlen((char *) token2);
+ lenp = strlen((char *) token);
+
+ str = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2);
+ if (str == NULL) {
+ xmlRegFreeAtom(atom);
+ return(NULL);
+ }
+ memcpy(&str[0], token, lenp);
+ str[lenp] = '|';
+ memcpy(&str[lenp + 1], token2, lenn);
+ str[lenn + lenp + 1] = 0;
+
+ atom->valuep = str;
+ }
+
+ if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
+ xmlRegFreeAtom(atom);
+ return(NULL);
+ }
if (to == NULL)
return(am->state);
return(to);
atom->min = min;
atom->max = max;
- xmlFAGenerateTransitions(am, from, to, atom);
+ if (xmlFAGenerateTransitions(am, from, to, atom) < 0) {
+ xmlRegFreeAtom(atom);
+ return(NULL);
+ }
if (to == NULL)
to = am->state;
if (to == NULL)
xmlAutomataCompile(xmlAutomataPtr am) {
xmlRegexpPtr ret;
+ if ((am == NULL) || (am->error != 0)) return(NULL);
xmlFAEliminateEpsilonTransitions(am);
/* xmlFAComputesDeterminism(am); */
ret = xmlRegEpxFromParse(am);