Commit 9ca11bfc authored by Kasimier T. Buchcik's avatar Kasimier T. Buchcik
Browse files

Some changes/fixes to the streaming evaluation. A bit of support for

* pattern.c: Some changes/fixes to the streaming evaluation.
* xmlschemas.c: A bit of support for parsing the schema for
  schema. Fixed attribute derivation when the use is
  "prohibited" and was "optional". Fixed an attribute construction
  bug, a left-over from the time, where <complexContent>,
  <extension>, etc. where created as structs.
parent 9ea5565f
Tue Jun 14 21:19:16 CEST 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
* pattern.c: Some changes/fixes to the streaming evaluation.
* xmlschemas.c: A bit of support for parsing the schema for
schema. Fixed attribute derivation when the use is
"prohibited" and was "optional". Fixed an attribute construction
bug, a left-over from the time, where <complexContent>,
<extension>, etc. where created as structs.
Tue Jun 14 12:35:12 CEST 2005 Daniel Veillard <daniel@veillard.com> Tue Jun 14 12:35:12 CEST 2005 Daniel Veillard <daniel@veillard.com>
* libxml-2.0.pc.in: removed a redundant include path * libxml-2.0.pc.in: removed a redundant include path
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#ifdef LIBXML_PATTERN_ENABLED #ifdef LIBXML_PATTERN_ENABLED
/* #define DEBUG_STREAMING */ /* #define DEBUG_STREAMING */
#define SUPPORT_IDC
#define ERROR(a, b, c, d) #define ERROR(a, b, c, d)
#define ERROR5(a, b, c, d, e) #define ERROR5(a, b, c, d, e)
...@@ -48,10 +47,18 @@ ...@@ -48,10 +47,18 @@
#define XML_STREAM_STEP_ROOT 4 #define XML_STREAM_STEP_ROOT 4
#define XML_STREAM_STEP_ATTR 8 #define XML_STREAM_STEP_ATTR 8
/*
* TODO: This is used on _xmlStreamCtxt, so don't use any values
* from xmlPatternFlags.
*/
#define XML_STREAM_DESC 1<<16
#define XML_PATTERN_NOTPATTERN (XML_PATTERN_XPATH | \ #define XML_PATTERN_NOTPATTERN (XML_PATTERN_XPATH | \
XML_PATTERN_XSSEL | \ XML_PATTERN_XSSEL | \
XML_PATTERN_XSFIELD) XML_PATTERN_XSFIELD)
#define XML_PATTERN_XSD (XML_PATTERN_XSSEL | XML_PATTERN_XSFIELD)
#define XML_STREAM_XS_IDC(item) (item->flags & \
(XML_PATTERN_XSSEL | XML_PATTERN_XSFIELD))
typedef struct _xmlStreamStep xmlStreamStep; typedef struct _xmlStreamStep xmlStreamStep;
typedef xmlStreamStep *xmlStreamStepPtr; typedef xmlStreamStep *xmlStreamStepPtr;
...@@ -68,6 +75,7 @@ struct _xmlStreamComp { ...@@ -68,6 +75,7 @@ struct _xmlStreamComp {
int nbStep; /* number of steps in the automata */ int nbStep; /* number of steps in the automata */
int maxStep; /* allocated number of steps */ int maxStep; /* allocated number of steps */
xmlStreamStepPtr steps; /* the array of steps */ xmlStreamStepPtr steps; /* the array of steps */
int flags;
}; };
struct _xmlStreamCtxt { struct _xmlStreamCtxt {
...@@ -78,6 +86,7 @@ struct _xmlStreamCtxt { ...@@ -78,6 +86,7 @@ struct _xmlStreamCtxt {
int level; /* how deep are we ? */ int level; /* how deep are we ? */
int *states; /* the array of step indexes */ int *states; /* the array of step indexes */
int flags; /* validation options */ int flags; /* validation options */
int blockLevel;
}; };
static void xmlFreeStreamComp(xmlStreamCompPtr comp); static void xmlFreeStreamComp(xmlStreamCompPtr comp);
...@@ -879,6 +888,7 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { ...@@ -879,6 +888,7 @@ xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
if (name == NULL) { if (name == NULL) {
if (CUR == '*') { if (CUR == '*') {
PUSH(XML_OP_ATTR, NULL, NULL); PUSH(XML_OP_ATTR, NULL, NULL);
NEXT;
} else { } else {
ERROR(NULL, NULL, NULL, ERROR(NULL, NULL, NULL,
"xmlCompileAttributeTest : Name expected\n"); "xmlCompileAttributeTest : Name expected\n");
...@@ -1122,7 +1132,7 @@ error: ...@@ -1122,7 +1132,7 @@ error:
static void static void
xmlCompilePathPattern(xmlPatParserContextPtr ctxt) { xmlCompilePathPattern(xmlPatParserContextPtr ctxt) {
SKIP_BLANKS; SKIP_BLANKS;
if (CUR == '/') { if ((CUR == '/') && (NXT(1) != '/')) {
ctxt->comp->flags |= PAT_FROM_ROOT; ctxt->comp->flags |= PAT_FROM_ROOT;
} else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) { } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) {
ctxt->comp->flags |= PAT_FROM_CUR; ctxt->comp->flags |= PAT_FROM_CUR;
...@@ -1429,8 +1439,27 @@ xmlStreamCompile(xmlPatternPtr comp) { ...@@ -1429,8 +1439,27 @@ xmlStreamCompile(xmlPatternPtr comp) {
break; break;
case XML_OP_ANCESTOR: case XML_OP_ANCESTOR:
flags |= XML_STREAM_STEP_DESC; flags |= XML_STREAM_STEP_DESC;
/*
* Mark the expression as having "//".
*/
if ((stream->flags & XML_STREAM_DESC) == 0)
stream->flags |= XML_STREAM_DESC;
break; break;
} }
}
if ((! root) && (comp->flags & XML_PATTERN_NOTPATTERN) == 0) {
/*
* If this should behave like a real pattern, we will mark
* the first step as having "//", to be reentrant on every
* tree level.
*/
if ((stream->flags & XML_STREAM_DESC) == 0)
stream->flags |= XML_STREAM_DESC;
if (stream->nbStep > 0) {
if ((stream->steps[0].flags & XML_STREAM_STEP_DESC) == 0)
stream->steps[0].flags |= XML_STREAM_STEP_DESC;
}
} }
stream->steps[s].flags |= XML_STREAM_STEP_FINAL; stream->steps[s].flags |= XML_STREAM_STEP_FINAL;
if (root) if (root)
...@@ -1475,6 +1504,7 @@ xmlNewStreamCtxt(xmlStreamCompPtr stream) { ...@@ -1475,6 +1504,7 @@ xmlNewStreamCtxt(xmlStreamCompPtr stream) {
cur->maxState = 4; cur->maxState = 4;
cur->level = 0; cur->level = 0;
cur->comp = stream; cur->comp = stream;
cur->blockLevel = -1;
return(cur); return(cur);
} }
...@@ -1568,6 +1598,7 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, ...@@ -1568,6 +1598,7 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
if ((name == NULL) && (ns == NULL)) { if ((name == NULL) && (ns == NULL)) {
stream->nbState = 0; stream->nbState = 0;
stream->level = 0; stream->level = 0;
stream->blockLevel = -1;
if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) { if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {
tmp = xmlStreamCtxtAddState(stream, 0, 0); tmp = xmlStreamCtxtAddState(stream, 0, 0);
if (tmp < 0) if (tmp < 0)
...@@ -1596,47 +1627,68 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, ...@@ -1596,47 +1627,68 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
stream->level++; stream->level++;
goto stream_next; goto stream_next;
} }
if ((stream->flags & XML_PATTERN_NOTPATTERN) != 0) { if (stream->blockLevel != -1) {
tmp = stream->level; /*
for (i = 0; i < comp->nbStep; i++) { * Skip blocked expressions.
if (comp->steps[i].flags & XML_STREAM_STEP_DESC) { */
tmp = -2; stream->level++;
break; goto stream_next;
}
}
if (comp->nbStep <= tmp) {
stream->level++;
goto stream_next;
}
} }
/* /*
* Check evolution of existing states * Check evolution of existing states
*/ */
i = 0;
m = stream->nbState; m = stream->nbState;
for (i = 0;i < m;i++) { while (i < m) {
match = 0; if ((comp->flags & XML_STREAM_DESC) == 0) {
step = stream->states[2 * i]; /*
/* dead states */ * If there is no "//", then only the last
if (step < 0) continue; * added state is of interest.
/* skip new states just added */ */
if (stream->states[(2 * i) + 1] > stream->level) step = stream->states[2 * (stream->nbState -1)];
continue; /*
/* skip continuations */ * TODO: Security check, should not happen, remove it.
desc = comp->steps[step].flags & XML_STREAM_STEP_DESC; */
if ((stream->states[(2 * i) + 1] < stream->level) && (!desc)) if (stream->states[(2 * (stream->nbState -1)) + 1] <
continue; stream->level) {
return (-1);
/* discard old states */ }
/* something needed about old level discarded */ desc = 0;
/* loop-stopper */
i = m;
} else {
/*
* If there are "//", then we need to process every "//"
* occuring in the states, plus any other state for this
* level.
*/
step = stream->states[2 * i];
/* TODO: should not happen anymore: dead states */
if (step < 0)
goto next_state;
tmp = stream->states[(2 * i) + 1];
/* skip new states just added */
if (tmp > stream->level)
goto next_state;
/* skip states at ancestor levels, except if "//" */
desc = comp->steps[step].flags & XML_STREAM_STEP_DESC;
if ((tmp < stream->level) && (!desc))
goto next_state;
}
/* /*
* Check for correct node-type. * Check for correct node-type.
*/ */
if ((comp->steps[step].flags & XML_STREAM_STEP_ATTR) && if ((nodeType == XML_ATTRIBUTE_NODE) &&
(nodeType != XML_ATTRIBUTE_NODE)) ((comp->steps[0].flags & XML_STREAM_STEP_ATTR) == 0))
continue; goto next_state;
/*
* Compare local/namespace-name.
*/
match = 0;
if (comp->dict) { if (comp->dict) {
if (comp->steps[step].name == NULL) { if (comp->steps[step].name == NULL) {
if (comp->steps[step].ns == NULL) if (comp->steps[step].ns == NULL)
...@@ -1677,76 +1729,105 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream, ...@@ -1677,76 +1729,105 @@ xmlStreamPushInternal(xmlStreamCtxtPtr stream,
} }
} }
} }
if (((comp->flags & XML_STREAM_DESC) == 0) &&
((! match) || final)) {
/*
* Mark this expression as blocked for any evaluation at
* deeper levels. Note that this includes "/foo"
* expressions if the *pattern* behaviour is used.
*/
stream->blockLevel = stream->level +1;
}
next_state:
i++;
} }
/*
* Check creating a new state.
*/
stream->level++; stream->level++;
/* /*
* Check the start only if this is a "desc" evaluation * Re/enter the expression.
* or if we are at the first level of evaluation.
*/ */
if (comp->steps[0].flags & XML_STREAM_STEP_ROOT)
goto stream_next;
desc = comp->steps[0].flags & XML_STREAM_STEP_DESC; desc = comp->steps[0].flags & XML_STREAM_STEP_DESC;
if ( ((comp->steps[0].flags & XML_STREAM_STEP_ROOT) == 0) && if (stream->flags & XML_PATTERN_NOTPATTERN) {
( ((stream->flags & XML_PATTERN_XSD) == 0) || /*
( (desc || (stream->level == 1)) ) * Re/enter the expression if it is a "descendant" one,
) * or if we are at the 1st level of evaluation.
) { */
if (stream->level == 1) {
if (XML_STREAM_XS_IDC(stream)) {
/*
* XS-IDC: The missing "self::node()" will always
* match the first given node.
*/
goto stream_next;
} else
goto compare;
}
/*
* A "//" is always reentrant.
*/
if (desc)
goto compare;
/* /*
#ifdef SUPPORT_IDC * XS-IDC: Process the 2nd level, since the missing
* "self::node()" is responsible for the 2nd level being
* the real start level.
*/
if ((stream->level == 2) && XML_STREAM_XS_IDC(stream))
goto compare;
goto stream_next;
}
if ((desc || (stream->level == 1)) && compare:
(!(comp->steps[0].flags & XML_STREAM_STEP_ROOT))) { /*
* Check expected node-type.
*
* Workaround for missing "self::node()" on "@foo".
*
if (comp->steps[0].flags & XML_STREAM_STEP_ATTR) {
xmlStreamCtxtAddState(stream, 0, stream->level);
goto stream_next;
}
#else
if (!(comp->steps[0].flags & XML_STREAM_STEP_ROOT)) {
#endif
*/ */
if (comp->steps[0].name == NULL) { if ((nodeType == XML_ATTRIBUTE_NODE) &&
if (comp->steps[0].ns == NULL) ((comp->steps[0].flags & XML_STREAM_STEP_ATTR) == 0))
match = 1; goto stream_next;
else { /*
if (comp->dict) * Compare local/namespace-name.
match = (comp->steps[0].ns == ns); */
else match = 0;
match = xmlStrEqual(comp->steps[0].ns, ns); if (comp->steps[0].name == NULL) {
} if (comp->steps[0].ns == NULL)
} else { match = 1;
if ((stream->flags & XML_PATTERN_XSD) && (!desc)) { else {
/* if (comp->dict)
* Workaround for missing "self::node() on "foo". match = (comp->steps[0].ns == ns);
*/
xmlStreamCtxtAddState(stream, 0, stream->level);
goto stream_next;
} else {
if (comp->dict) {
match = ((comp->steps[0].name == name) &&
(comp->steps[0].ns == ns));
} else {
match = ((xmlStrEqual(comp->steps[0].name, name)) &&
(xmlStrEqual(comp->steps[0].ns, ns)));
}
}
}
if (match) {
if (comp->steps[0].flags & XML_STREAM_STEP_FINAL)
ret = 1;
else else
xmlStreamCtxtAddState(stream, 1, stream->level); match = xmlStrEqual(comp->steps[0].ns, ns);
} }
} else {
if (comp->dict)
match = ((comp->steps[0].name == name) &&
(comp->steps[0].ns == ns));
else
match = ((xmlStrEqual(comp->steps[0].name, name)) &&
(xmlStrEqual(comp->steps[0].ns, ns)));
} }
if (match) {
final = comp->steps[0].flags & XML_STREAM_STEP_FINAL;
if (final)
ret = 1;
else
xmlStreamCtxtAddState(stream, 1, stream->level);
}
if (((comp->flags & XML_STREAM_DESC) == 0) &&
((! match) || final)) {
/*
* Mark this expression as blocked for any evaluation at
* deeper levels.
*/
stream->blockLevel = stream->level;
}
stream_next: stream_next:
stream = stream->next; stream = stream->next;
} /* while stream != NULL */ } /* while stream != NULL */
...@@ -1811,26 +1892,32 @@ xmlStreamPushAttr(xmlStreamCtxtPtr stream, ...@@ -1811,26 +1892,32 @@ xmlStreamPushAttr(xmlStreamCtxtPtr stream,
*/ */
int int
xmlStreamPop(xmlStreamCtxtPtr stream) { xmlStreamPop(xmlStreamCtxtPtr stream) {
int i, m; int i, lev;
int ret; int ret;
if (stream == NULL) if (stream == NULL)
return(-1); return(-1);
ret = 0; ret = 0;
while (stream != NULL) { while (stream != NULL) {
/*
* Reset block-level.
*/
if (stream->blockLevel == stream->level)
stream->blockLevel = -1;
stream->level--; stream->level--;
if (stream->level < 0) if (stream->level < 0)
ret = -1; ret = -1;
/* /*
* Check evolution of existing states * Check evolution of existing states
*/ */
m = stream->nbState; for (i = stream->nbState -1; i >= 0; i--) {
for (i = 0;i < m;i++) {
if (stream->states[(2 * i)] < 0) break;
/* discard obsoleted states */ /* discard obsoleted states */
if (stream->states[(2 * i) + 1] > stream->level) lev = stream->states[(2 * i) + 1];
stream->states[(2 * i)] = -1; if (lev > stream->level)
stream->nbState--;
if (lev <= stream->level)
break;
} }
stream = stream->next; stream = stream->next;
} }
......
...@@ -256,6 +256,7 @@ struct _xmlSchemaParserCtxt { ...@@ -256,6 +256,7 @@ struct _xmlSchemaParserCtxt {
int sizeLocalImports; int sizeLocalImports;
int nbLocalImports; int nbLocalImports;
xmlHashTablePtr substGroups; xmlHashTablePtr substGroups;
int isS4S;
}; };
#define XML_SCHEMAS_ATTR_UNKNOWN 1 #define XML_SCHEMAS_ATTR_UNKNOWN 1
...@@ -6914,10 +6915,10 @@ xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt, ...@@ -6914,10 +6915,10 @@ xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
*/ */
if (isField) if (isField)
selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
NULL, 1, nsArray); NULL, XML_PATTERN_XSFIELD, nsArray);
else else
selector->xpathComp = (void *) xmlPatterncompile(selector->xpath, selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
NULL, 1, nsArray); NULL, XML_PATTERN_XSSEL, nsArray);
if (nsArray != NULL) if (nsArray != NULL)
xmlFree((xmlChar **) nsArray); xmlFree((xmlChar **) nsArray);
...@@ -8046,10 +8047,21 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema, ...@@ -8046,10 +8047,21 @@ xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
NULL, node, NULL, node,
"name", NULL); "name", NULL);
return (NULL); return (NULL);
} else if (xmlSchemaPValAttrNode(ctxt, } else {
NULL, NULL, attr, if (xmlSchemaPValAttrNode(ctxt,
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) { NULL, NULL, attr,
return (NULL); xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
return (NULL);
/*
* Skip built-in types.
*/
if (ctxt->isS4S) {
xmlSchemaTypePtr biType;
biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
if (biType != NULL)
return (biType);
}
} }
} }
...@@ -9020,7 +9032,7 @@ xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt, ...@@ -9020,7 +9032,7 @@ xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
xmlNodePtr node) xmlNodePtr node)
{ {
const xmlChar *oldURL, **oldLocImps, *oldTNS; const xmlChar *oldURL, **oldLocImps, *oldTNS;
int oldFlags, oldNumLocImps, oldSizeLocImps; int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
/* /*
* Save and reset the context & schema. * Save and reset the context & schema.
...@@ -9035,9 +9047,17 @@ xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt, ...@@ -9035,9 +9047,17 @@ xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
oldSizeLocImps = pctxt->sizeLocalImports; oldSizeLocImps = pctxt->sizeLocalImports;
pctxt->sizeLocalImports = 0; pctxt->sizeLocalImports = 0;
oldFlags = schema->flags; oldFlags = schema->flags;
oldIsS4S = pctxt->isS4S;
xmlSchemaClearSchemaDefaults(schema); xmlSchemaClearSchemaDefaults(schema);
oldTNS = schema->targetNamespace; oldTNS = schema->targetNamespace;
schema->targetNamespace = targetNamespace; schema->targetNamespace = targetNamespace;
if ((targetNamespace != NULL) &&
xmlStrEqual(targetNamespace, xmlSchemaNs)) {
/*
* We are parsing the schema for schema!
*/
pctxt->isS4S = 1;
}
/* /*
* Parse the schema. * Parse the schema.
*/ */
...@@ -9054,6 +9074,7 @@ xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt, ...@@ -9054,6 +9074,7 @@ xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
pctxt->nbLocalImports = oldNumLocImps; pctxt->nbLocalImports = oldNumLocImps;
pctxt->sizeLocalImports = oldSizeLocImps; pctxt->sizeLocalImports = oldSizeLocImps;
pctxt->URL = oldURL; pctxt->URL = oldURL;
pctxt->isS4S = oldIsS4S;
} }
/** /**
...@@ -10568,15 +10589,13 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) ...@@ -10568,15 +10589,13 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
return (NULL); return (NULL);
nberrors = ctxt->nberrors; nberrors = ctxt->nberrors;
ctxt->nberrors = 0; ctxt->nberrors = 0;
ctxt->isS4S = 0;
if (IS_SCHEMA(node, "schema")) { if (IS_SCHEMA(node, "schema")) {
xmlSchemaImportPtr import; xmlSchemaImportPtr import;
schema = xmlSchemaNewSchema(ctxt); schema = xmlSchemaNewSchema(ctxt);
if (schema == NULL) if (schema == NULL)
return (NULL); return (NULL);
/*
* Disable build of list of items.
*/
attr = xmlSchemaGetPropNode(node, "targetNamespace"); attr = xmlSchemaGetPropNode(node, "targetNamespace");
if (attr != NULL) { if (attr != NULL) {
xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr, xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
...@@ -10585,6 +10604,12 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node) ...@@ -10585,6 +10604,12 @@ xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
* TODO: Should we proceed with an invalid target namespace? * TODO: Should we proceed with an invalid target namespace?
*/ */
schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1); schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
/*