/*
* Optimisations for count
*/
- xmlNodePtr previous;
- int index;
- int len;
+ int previousExtra;
+ int indexExtra;
+ int lenExtra;
};
struct _xsltCompMatch {
typedef struct _xsltParserContext xsltParserContext;
typedef xsltParserContext *xsltParserContextPtr;
struct _xsltParserContext {
+ xsltStylesheetPtr style; /* the stylesheet */
+ xsltTransformContextPtr ctxt; /* the transformation or NULL */
const xmlChar *cur; /* the current char being parsed */
const xmlChar *base; /* the full expression */
xmlDocPtr doc; /* the source document */
/**
* xsltNewParserContext:
+ * @style: the stylesheet
+ * @ctxt: the transformation context, if done at run-time
*
* Create a new XSLT ParserContext
*
* Returns the newly allocated xsltParserContextPtr or NULL in case of error
*/
static xsltParserContextPtr
-xsltNewParserContext(void) {
+xsltNewParserContext(xsltStylesheetPtr style, xsltTransformContextPtr ctxt) {
xsltParserContextPtr cur;
cur = (xsltParserContextPtr) xmlMalloc(sizeof(xsltParserContext));
return(NULL);
}
memset(cur, 0, sizeof(xsltParserContext));
+ cur->style = style;
+ cur->ctxt = ctxt;
return(cur);
}
* Returns -1 in case of failure, 0 otherwise.
*/
static int
-xsltCompMatchAdd(xsltCompMatchPtr comp, xsltOp op, xmlChar *value,
- xmlChar *value2) {
+xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp,
+ xsltOp op, xmlChar * value, xmlChar * value2)
+{
if (comp->nbStep >= 40) {
- xsltPrintErrorContext(NULL, NULL, NULL); /* TODO */
+ xsltPrintErrorContext(NULL, NULL, NULL); /* TODO */
xsltGenericError(xsltGenericErrorContext,
- "xsltCompMatchAdd: overflow\n");
- return(-1);
+ "xsltCompMatchAdd: overflow\n");
+ return (-1);
}
comp->steps[comp->nbStep].op = op;
comp->steps[comp->nbStep].value = value;
comp->steps[comp->nbStep].value2 = value2;
+ if (ctxt->ctxt != NULL) {
+ comp->steps[comp->nbStep].previousExtra =
+ xsltAllocateExtraCtxt(ctxt->ctxt);
+ comp->steps[comp->nbStep].indexExtra =
+ xsltAllocateExtraCtxt(ctxt->ctxt);
+ comp->steps[comp->nbStep].lenExtra =
+ xsltAllocateExtraCtxt(ctxt->ctxt);
+ } else {
+ comp->steps[comp->nbStep].previousExtra =
+ xsltAllocateExtra(ctxt->style);
+ comp->steps[comp->nbStep].indexExtra =
+ xsltAllocateExtra(ctxt->style);
+ comp->steps[comp->nbStep].lenExtra =
+ xsltAllocateExtra(ctxt->style);
+ }
comp->nbStep++;
- return(0);
+ return (0);
}
/**
comp->steps[comp->nbStep++].op = XSLT_OP_END;
}
-/**
- * xsltCleanupCompMatch:
- * @comp: the compiled match expression
- *
- * remove all computation state from the pattern
- */
-static void
-xsltCleanupCompMatch(xsltCompMatchPtr comp) {
- int i;
-
- for (i = 0;i < comp->nbStep;i++) {
- comp->steps[i].previous = NULL;
- }
-}
-
/************************************************************************
* *
* The interpreter for the precompiled patterns *
(select->value != NULL) &&
(node->type == XML_ELEMENT_NODE) &&
(node->parent != NULL)) {
-
- if ((select->previous != NULL) &&
- (select->previous->parent == node->parent)) {
+ xmlNodePtr previous;
+ int index;
+
+ previous = (xmlNodePtr)
+ XSLT_RUNTIME_EXTRA(ctxt, select->previousExtra);
+ index = (int)
+ XSLT_RUNTIME_EXTRA(ctxt, select->indexExtra);
+ if ((previous != NULL) &&
+ (previous->parent == node->parent)) {
/*
* just walk back to adjust the index
*/
xmlNodePtr sibling = node;
while (sibling != NULL) {
- if (sibling == select->previous)
+ if (sibling == previous)
break;
if (xmlStrEqual(node->name, sibling->name)) {
if ((select->value2 == NULL) ||
indx = 0;
sibling = node;
while (sibling != NULL) {
- if (sibling == select->previous)
+ if (sibling == previous)
break;
if ((select->value2 == NULL) ||
((sibling->ns != NULL) &&
}
}
if (sibling != NULL) {
- pos = select->index + indx;
- len = select->len;
- select->previous = node;
- select->index = pos;
+ pos = index + indx;
+ len = (int)
+ XSLT_RUNTIME_EXTRA(ctxt, select->lenExtra);
+ XSLT_RUNTIME_EXTRA(ctxt, select->previousExtra) =
+ node;
+ XSLT_RUNTIME_EXTRA(ctxt, select->indexExtra) =
+ (void *) pos;
+ index = pos;
} else
pos = 0;
} else {
if (pos != 0) {
ctxt->xpathCtxt->contextSize = len;
ctxt->xpathCtxt->proximityPosition = pos;
- select->previous = node;
- select->index = pos;
- select->len = len;
+ XSLT_RUNTIME_EXTRA(ctxt, select->previousExtra) =
+ node;
+ XSLT_RUNTIME_EXTRA(ctxt, select->indexExtra) =
+ (void *) pos;
+ XSLT_RUNTIME_EXTRA(ctxt, select->lenExtra) =
+ (void *) len;
}
} else if ((select != NULL) && (select->op == XSLT_OP_ALL) &&
(node->type == XML_ELEMENT_NODE)) {
- if ((select->previous != NULL) &&
- (select->previous->parent == node->parent)) {
+ xmlNodePtr previous;
+ int index;
+
+ previous = (xmlNodePtr)
+ XSLT_RUNTIME_EXTRA(ctxt, select->previousExtra);
+ index = (int)
+ XSLT_RUNTIME_EXTRA(ctxt, select->indexExtra);
+ if ((previous != NULL) &&
+ (previous->parent == node->parent)) {
/*
* just walk back to adjust the index
*/
xmlNodePtr sibling = node;
while (sibling != NULL) {
- if (sibling == select->previous)
+ if (sibling == previous)
break;
if (sibling->type == XML_ELEMENT_NODE)
indx++;
indx = 0;
sibling = node;
while (sibling != NULL) {
- if (sibling == select->previous)
+ if (sibling == previous)
break;
if (sibling->type == XML_ELEMENT_NODE)
indx--;
}
}
if (sibling != NULL) {
- pos = select->index + indx;
- len = select->len;
- select->previous = node;
- select->index = pos;
+ pos = index + indx;
+ len = (int)
+ XSLT_RUNTIME_EXTRA(ctxt, select->lenExtra);
+ XSLT_RUNTIME_EXTRA(ctxt, select->previousExtra) =
+ node;
+ XSLT_RUNTIME_EXTRA(ctxt, select->indexExtra) =
+ (void *) pos;
} else
pos = 0;
} else {
if (pos != 0) {
ctxt->xpathCtxt->contextSize = len;
ctxt->xpathCtxt->proximityPosition = pos;
- select->previous = node;
- select->index = pos;
- select->len = len;
+ XSLT_RUNTIME_EXTRA(ctxt, select->previousExtra) =
+ node;
+ XSLT_RUNTIME_EXTRA(ctxt, select->indexExtra) =
+ (void *) pos;
+ XSLT_RUNTIME_EXTRA(ctxt, select->lenExtra) =
+ (void *) len;
}
}
oldNode = ctxt->node;
#define PUSH(op, val, val2) \
- if (xsltCompMatchAdd(ctxt->comp, (op), (val), (val2))) goto error;
+ if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error;
#define SWAP() \
xsltSwapTopCompMatch(ctxt->comp);
* @pattern: an XSLT pattern
* @doc: the containing document
* @node: the containing element
+ * @style: the stylesheet
+ * @runtime: the transformation context, if done at run-time
*
* Compile the XSLT pattern and generates a list of precompiled form suitable
* for fast matching.
*/
xsltCompMatchPtr
-xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node) {
+xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc,
+ xmlNodePtr node, xsltStylesheetPtr style,
+ xsltTransformContextPtr runtime) {
xsltParserContextPtr ctxt = NULL;
xsltCompMatchPtr element, first = NULL, previous = NULL;
int current, start, end;
return(NULL);
}
- ctxt = xsltNewParserContext();
+ ctxt = xsltNewParserContext(style, runtime);
if (ctxt == NULL)
return(NULL);
ctxt->doc = doc;
return(-1);
priority = cur->priority;
- pat = xsltCompilePattern(cur->match, style->doc, cur->elem);
+ pat = xsltCompilePattern(cur->match, style->doc, cur->elem, style, NULL);
while (pat) {
next = pat->next;
pat->next = NULL;
* the ones it imports.
*/
void
-xsltCleanupTemplates(xsltStylesheetPtr style) {
- while (style != NULL) {
- xmlHashScan((xmlHashTablePtr) style->templatesHash,
- (xmlHashScanner) xsltCleanupCompMatch, NULL);
-
- style = xsltNextImport(style);
- }
+xsltCleanupTemplates(xsltStylesheetPtr style ATTRIBUTE_UNUSED) {
}
/**
xsltFreeCompMatchList(style->commentMatch);
}
+#if 0
/**
* xsltMatchPattern
* @node: a node in the source tree
}
return match;
}
+#endif
cur->exclPrefixMax = 0;
cur->exclPrefixTab = NULL;
cur->extInfos = NULL;
+ cur->extrasNr = 0;
xsltInit();
}
/**
+ * xsltAllocateExtra:
+ * @style: an XSLT stylesheet
+ *
+ * Allocate an extra runtime information slot statically while compiling
+ * the stylesheet and return its number
+ *
+ * Returns the number of the slot
+ */
+int
+xsltAllocateExtra(xsltStylesheetPtr style)
+{
+ return(style->extrasNr++);
+}
+
+/**
+ * xsltAllocateExtraCtxt:
+ * @ctxt: an XSLT transformation context
+ *
+ * Allocate an extra runtime information slot at run-time
+ * and return its number
+ * This make sure there is a slot ready in the transformation context
+ *
+ * Returns the number of the slot
+ */
+int
+xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
+{
+ if (ctxt->extrasNr >= ctxt->extrasMax) {
+ int i;
+ if (ctxt->extrasNr == 0) {
+ ctxt->extrasMax = 20;
+ ctxt->extras = (xsltRuntimeExtraPtr)
+ xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));
+ if (ctxt->extras == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xsltAllocateExtraCtxt: out of memory\n");
+ ctxt->state = XSLT_STATE_ERROR;
+ return(0);
+ }
+ for (i = 0;i < ctxt->extrasMax;i++) {
+ ctxt->extras[i].info = NULL;
+ ctxt->extras[i].deallocate = NULL;
+ }
+
+ } else {
+ xsltRuntimeExtraPtr tmp;
+
+ ctxt->extrasMax += 100;
+ tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras,
+ ctxt->extrasMax * sizeof(xsltRuntimeExtra));
+ if (tmp == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xsltAllocateExtraCtxt: out of memory\n");
+ ctxt->state = XSLT_STATE_ERROR;
+ return(0);
+ }
+ ctxt->extras = tmp;
+ for (i = ctxt->extrasNr;i < ctxt->extrasMax;i++) {
+ ctxt->extras[i].info = NULL;
+ ctxt->extras[i].deallocate = NULL;
+ }
+ }
+ }
+ return(ctxt->extrasNr++);
+}
+
+/**
* xsltFreeStylesheetList:
* @sheet: an XSLT stylesheet list
*