XML C parser available under the MIT license. http://xmlsoft.org/

Dependents:   libiio

Committer:
pcercuei
Date:
Thu Aug 25 10:07:34 2016 +0000
Revision:
1:26f20484cbdc
Parent:
0:03b5121a232e
Add config.h and dummy.c containing empty functions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pcercuei 0:03b5121a232e 1 /*
pcercuei 0:03b5121a232e 2 * pattern.c: Implemetation of selectors for nodes
pcercuei 0:03b5121a232e 3 *
pcercuei 0:03b5121a232e 4 * Reference:
pcercuei 0:03b5121a232e 5 * http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/
pcercuei 0:03b5121a232e 6 * to some extent
pcercuei 0:03b5121a232e 7 * http://www.w3.org/TR/1999/REC-xml-19991116
pcercuei 0:03b5121a232e 8 *
pcercuei 0:03b5121a232e 9 * See Copyright for the status of this software.
pcercuei 0:03b5121a232e 10 *
pcercuei 0:03b5121a232e 11 * daniel@veillard.com
pcercuei 0:03b5121a232e 12 */
pcercuei 0:03b5121a232e 13
pcercuei 0:03b5121a232e 14 /*
pcercuei 0:03b5121a232e 15 * TODO:
pcercuei 0:03b5121a232e 16 * - compilation flags to check for specific syntaxes
pcercuei 0:03b5121a232e 17 * using flags of xmlPatterncompile()
pcercuei 0:03b5121a232e 18 * - making clear how pattern starting with / or . need to be handled,
pcercuei 0:03b5121a232e 19 * currently push(NULL, NULL) means a reset of the streaming context
pcercuei 0:03b5121a232e 20 * and indicating we are on / (the document node), probably need
pcercuei 0:03b5121a232e 21 * something similar for .
pcercuei 0:03b5121a232e 22 * - get rid of the "compile" starting with lowercase
pcercuei 0:03b5121a232e 23 * - DONE (2006-05-16): get rid of the Strdup/Strndup in case of dictionary
pcercuei 0:03b5121a232e 24 */
pcercuei 0:03b5121a232e 25
pcercuei 0:03b5121a232e 26 #define IN_LIBXML
pcercuei 0:03b5121a232e 27 #include "libxml.h"
pcercuei 0:03b5121a232e 28
pcercuei 0:03b5121a232e 29 #include <string.h>
pcercuei 0:03b5121a232e 30 #include <libxml/xmlmemory.h>
pcercuei 0:03b5121a232e 31 #include <libxml/tree.h>
pcercuei 0:03b5121a232e 32 #include <libxml/hash.h>
pcercuei 0:03b5121a232e 33 #include <libxml/dict.h>
pcercuei 0:03b5121a232e 34 #include <libxml/xmlerror.h>
pcercuei 0:03b5121a232e 35 #include <libxml/parserInternals.h>
pcercuei 0:03b5121a232e 36 #include <libxml/pattern.h>
pcercuei 0:03b5121a232e 37
pcercuei 0:03b5121a232e 38 #ifdef LIBXML_PATTERN_ENABLED
pcercuei 0:03b5121a232e 39
pcercuei 0:03b5121a232e 40 /* #define DEBUG_STREAMING */
pcercuei 0:03b5121a232e 41
pcercuei 0:03b5121a232e 42 #ifdef ERROR
pcercuei 0:03b5121a232e 43 #undef ERROR
pcercuei 0:03b5121a232e 44 #endif
pcercuei 0:03b5121a232e 45 #define ERROR(a, b, c, d)
pcercuei 0:03b5121a232e 46 #define ERROR5(a, b, c, d, e)
pcercuei 0:03b5121a232e 47
pcercuei 0:03b5121a232e 48 #define XML_STREAM_STEP_DESC 1
pcercuei 0:03b5121a232e 49 #define XML_STREAM_STEP_FINAL 2
pcercuei 0:03b5121a232e 50 #define XML_STREAM_STEP_ROOT 4
pcercuei 0:03b5121a232e 51 #define XML_STREAM_STEP_ATTR 8
pcercuei 0:03b5121a232e 52 #define XML_STREAM_STEP_NODE 16
pcercuei 0:03b5121a232e 53 #define XML_STREAM_STEP_IN_SET 32
pcercuei 0:03b5121a232e 54
pcercuei 0:03b5121a232e 55 /*
pcercuei 0:03b5121a232e 56 * NOTE: Those private flags (XML_STREAM_xxx) are used
pcercuei 0:03b5121a232e 57 * in _xmlStreamCtxt->flag. They extend the public
pcercuei 0:03b5121a232e 58 * xmlPatternFlags, so be carefull not to interfere with the
pcercuei 0:03b5121a232e 59 * reserved values for xmlPatternFlags.
pcercuei 0:03b5121a232e 60 */
pcercuei 0:03b5121a232e 61 #define XML_STREAM_FINAL_IS_ANY_NODE 1<<14
pcercuei 0:03b5121a232e 62 #define XML_STREAM_FROM_ROOT 1<<15
pcercuei 0:03b5121a232e 63 #define XML_STREAM_DESC 1<<16
pcercuei 0:03b5121a232e 64
pcercuei 0:03b5121a232e 65 /*
pcercuei 0:03b5121a232e 66 * XML_STREAM_ANY_NODE is used for comparison against
pcercuei 0:03b5121a232e 67 * xmlElementType enums, to indicate a node of any type.
pcercuei 0:03b5121a232e 68 */
pcercuei 0:03b5121a232e 69 #define XML_STREAM_ANY_NODE 100
pcercuei 0:03b5121a232e 70
pcercuei 0:03b5121a232e 71 #define XML_PATTERN_NOTPATTERN (XML_PATTERN_XPATH | \
pcercuei 0:03b5121a232e 72 XML_PATTERN_XSSEL | \
pcercuei 0:03b5121a232e 73 XML_PATTERN_XSFIELD)
pcercuei 0:03b5121a232e 74
pcercuei 0:03b5121a232e 75 #define XML_STREAM_XS_IDC(c) ((c)->flags & \
pcercuei 0:03b5121a232e 76 (XML_PATTERN_XSSEL | XML_PATTERN_XSFIELD))
pcercuei 0:03b5121a232e 77
pcercuei 0:03b5121a232e 78 #define XML_STREAM_XS_IDC_SEL(c) ((c)->flags & XML_PATTERN_XSSEL)
pcercuei 0:03b5121a232e 79
pcercuei 0:03b5121a232e 80 #define XML_STREAM_XS_IDC_FIELD(c) ((c)->flags & XML_PATTERN_XSFIELD)
pcercuei 0:03b5121a232e 81
pcercuei 0:03b5121a232e 82 #define XML_PAT_COPY_NSNAME(c, r, nsname) \
pcercuei 0:03b5121a232e 83 if ((c)->comp->dict) \
pcercuei 0:03b5121a232e 84 r = (xmlChar *) xmlDictLookup((c)->comp->dict, BAD_CAST nsname, -1); \
pcercuei 0:03b5121a232e 85 else r = xmlStrdup(BAD_CAST nsname);
pcercuei 0:03b5121a232e 86
pcercuei 0:03b5121a232e 87 #define XML_PAT_FREE_STRING(c, r) if ((c)->comp->dict == NULL) xmlFree(r);
pcercuei 0:03b5121a232e 88
pcercuei 0:03b5121a232e 89 typedef struct _xmlStreamStep xmlStreamStep;
pcercuei 0:03b5121a232e 90 typedef xmlStreamStep *xmlStreamStepPtr;
pcercuei 0:03b5121a232e 91 struct _xmlStreamStep {
pcercuei 0:03b5121a232e 92 int flags; /* properties of that step */
pcercuei 0:03b5121a232e 93 const xmlChar *name; /* first string value if NULL accept all */
pcercuei 0:03b5121a232e 94 const xmlChar *ns; /* second string value */
pcercuei 0:03b5121a232e 95 int nodeType; /* type of node */
pcercuei 0:03b5121a232e 96 };
pcercuei 0:03b5121a232e 97
pcercuei 0:03b5121a232e 98 typedef struct _xmlStreamComp xmlStreamComp;
pcercuei 0:03b5121a232e 99 typedef xmlStreamComp *xmlStreamCompPtr;
pcercuei 0:03b5121a232e 100 struct _xmlStreamComp {
pcercuei 0:03b5121a232e 101 xmlDict *dict; /* the dictionary if any */
pcercuei 0:03b5121a232e 102 int nbStep; /* number of steps in the automata */
pcercuei 0:03b5121a232e 103 int maxStep; /* allocated number of steps */
pcercuei 0:03b5121a232e 104 xmlStreamStepPtr steps; /* the array of steps */
pcercuei 0:03b5121a232e 105 int flags;
pcercuei 0:03b5121a232e 106 };
pcercuei 0:03b5121a232e 107
pcercuei 0:03b5121a232e 108 struct _xmlStreamCtxt {
pcercuei 0:03b5121a232e 109 struct _xmlStreamCtxt *next;/* link to next sub pattern if | */
pcercuei 0:03b5121a232e 110 xmlStreamCompPtr comp; /* the compiled stream */
pcercuei 0:03b5121a232e 111 int nbState; /* number of states in the automata */
pcercuei 0:03b5121a232e 112 int maxState; /* allocated number of states */
pcercuei 0:03b5121a232e 113 int level; /* how deep are we ? */
pcercuei 0:03b5121a232e 114 int *states; /* the array of step indexes */
pcercuei 0:03b5121a232e 115 int flags; /* validation options */
pcercuei 0:03b5121a232e 116 int blockLevel;
pcercuei 0:03b5121a232e 117 };
pcercuei 0:03b5121a232e 118
pcercuei 0:03b5121a232e 119 static void xmlFreeStreamComp(xmlStreamCompPtr comp);
pcercuei 0:03b5121a232e 120
pcercuei 0:03b5121a232e 121 /*
pcercuei 0:03b5121a232e 122 * Types are private:
pcercuei 0:03b5121a232e 123 */
pcercuei 0:03b5121a232e 124
pcercuei 0:03b5121a232e 125 typedef enum {
pcercuei 0:03b5121a232e 126 XML_OP_END=0,
pcercuei 0:03b5121a232e 127 XML_OP_ROOT,
pcercuei 0:03b5121a232e 128 XML_OP_ELEM,
pcercuei 0:03b5121a232e 129 XML_OP_CHILD,
pcercuei 0:03b5121a232e 130 XML_OP_ATTR,
pcercuei 0:03b5121a232e 131 XML_OP_PARENT,
pcercuei 0:03b5121a232e 132 XML_OP_ANCESTOR,
pcercuei 0:03b5121a232e 133 XML_OP_NS,
pcercuei 0:03b5121a232e 134 XML_OP_ALL
pcercuei 0:03b5121a232e 135 } xmlPatOp;
pcercuei 0:03b5121a232e 136
pcercuei 0:03b5121a232e 137
pcercuei 0:03b5121a232e 138 typedef struct _xmlStepState xmlStepState;
pcercuei 0:03b5121a232e 139 typedef xmlStepState *xmlStepStatePtr;
pcercuei 0:03b5121a232e 140 struct _xmlStepState {
pcercuei 0:03b5121a232e 141 int step;
pcercuei 0:03b5121a232e 142 xmlNodePtr node;
pcercuei 0:03b5121a232e 143 };
pcercuei 0:03b5121a232e 144
pcercuei 0:03b5121a232e 145 typedef struct _xmlStepStates xmlStepStates;
pcercuei 0:03b5121a232e 146 typedef xmlStepStates *xmlStepStatesPtr;
pcercuei 0:03b5121a232e 147 struct _xmlStepStates {
pcercuei 0:03b5121a232e 148 int nbstates;
pcercuei 0:03b5121a232e 149 int maxstates;
pcercuei 0:03b5121a232e 150 xmlStepStatePtr states;
pcercuei 0:03b5121a232e 151 };
pcercuei 0:03b5121a232e 152
pcercuei 0:03b5121a232e 153 typedef struct _xmlStepOp xmlStepOp;
pcercuei 0:03b5121a232e 154 typedef xmlStepOp *xmlStepOpPtr;
pcercuei 0:03b5121a232e 155 struct _xmlStepOp {
pcercuei 0:03b5121a232e 156 xmlPatOp op;
pcercuei 0:03b5121a232e 157 const xmlChar *value;
pcercuei 0:03b5121a232e 158 const xmlChar *value2; /* The namespace name */
pcercuei 0:03b5121a232e 159 };
pcercuei 0:03b5121a232e 160
pcercuei 0:03b5121a232e 161 #define PAT_FROM_ROOT (1<<8)
pcercuei 0:03b5121a232e 162 #define PAT_FROM_CUR (1<<9)
pcercuei 0:03b5121a232e 163
pcercuei 0:03b5121a232e 164 struct _xmlPattern {
pcercuei 0:03b5121a232e 165 void *data; /* the associated template */
pcercuei 0:03b5121a232e 166 xmlDictPtr dict; /* the optional dictionary */
pcercuei 0:03b5121a232e 167 struct _xmlPattern *next; /* next pattern if | is used */
pcercuei 0:03b5121a232e 168 const xmlChar *pattern; /* the pattern */
pcercuei 0:03b5121a232e 169 int flags; /* flags */
pcercuei 0:03b5121a232e 170 int nbStep;
pcercuei 0:03b5121a232e 171 int maxStep;
pcercuei 0:03b5121a232e 172 xmlStepOpPtr steps; /* ops for computation */
pcercuei 0:03b5121a232e 173 xmlStreamCompPtr stream; /* the streaming data if any */
pcercuei 0:03b5121a232e 174 };
pcercuei 0:03b5121a232e 175
pcercuei 0:03b5121a232e 176 typedef struct _xmlPatParserContext xmlPatParserContext;
pcercuei 0:03b5121a232e 177 typedef xmlPatParserContext *xmlPatParserContextPtr;
pcercuei 0:03b5121a232e 178 struct _xmlPatParserContext {
pcercuei 0:03b5121a232e 179 const xmlChar *cur; /* the current char being parsed */
pcercuei 0:03b5121a232e 180 const xmlChar *base; /* the full expression */
pcercuei 0:03b5121a232e 181 int error; /* error code */
pcercuei 0:03b5121a232e 182 xmlDictPtr dict; /* the dictionary if any */
pcercuei 0:03b5121a232e 183 xmlPatternPtr comp; /* the result */
pcercuei 0:03b5121a232e 184 xmlNodePtr elem; /* the current node if any */
pcercuei 0:03b5121a232e 185 const xmlChar **namespaces; /* the namespaces definitions */
pcercuei 0:03b5121a232e 186 int nb_namespaces; /* the number of namespaces */
pcercuei 0:03b5121a232e 187 };
pcercuei 0:03b5121a232e 188
pcercuei 0:03b5121a232e 189 /************************************************************************
pcercuei 0:03b5121a232e 190 * *
pcercuei 0:03b5121a232e 191 * Type functions *
pcercuei 0:03b5121a232e 192 * *
pcercuei 0:03b5121a232e 193 ************************************************************************/
pcercuei 0:03b5121a232e 194
pcercuei 0:03b5121a232e 195 /**
pcercuei 0:03b5121a232e 196 * xmlNewPattern:
pcercuei 0:03b5121a232e 197 *
pcercuei 0:03b5121a232e 198 * Create a new XSLT Pattern
pcercuei 0:03b5121a232e 199 *
pcercuei 0:03b5121a232e 200 * Returns the newly allocated xmlPatternPtr or NULL in case of error
pcercuei 0:03b5121a232e 201 */
pcercuei 0:03b5121a232e 202 static xmlPatternPtr
pcercuei 0:03b5121a232e 203 xmlNewPattern(void) {
pcercuei 0:03b5121a232e 204 xmlPatternPtr cur;
pcercuei 0:03b5121a232e 205
pcercuei 0:03b5121a232e 206 cur = (xmlPatternPtr) xmlMalloc(sizeof(xmlPattern));
pcercuei 0:03b5121a232e 207 if (cur == NULL) {
pcercuei 0:03b5121a232e 208 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 209 "xmlNewPattern : malloc failed\n");
pcercuei 0:03b5121a232e 210 return(NULL);
pcercuei 0:03b5121a232e 211 }
pcercuei 0:03b5121a232e 212 memset(cur, 0, sizeof(xmlPattern));
pcercuei 0:03b5121a232e 213 cur->maxStep = 10;
pcercuei 0:03b5121a232e 214 cur->steps = (xmlStepOpPtr) xmlMalloc(cur->maxStep * sizeof(xmlStepOp));
pcercuei 0:03b5121a232e 215 if (cur->steps == NULL) {
pcercuei 0:03b5121a232e 216 xmlFree(cur);
pcercuei 0:03b5121a232e 217 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 218 "xmlNewPattern : malloc failed\n");
pcercuei 0:03b5121a232e 219 return(NULL);
pcercuei 0:03b5121a232e 220 }
pcercuei 0:03b5121a232e 221 return(cur);
pcercuei 0:03b5121a232e 222 }
pcercuei 0:03b5121a232e 223
pcercuei 0:03b5121a232e 224 /**
pcercuei 0:03b5121a232e 225 * xmlFreePattern:
pcercuei 0:03b5121a232e 226 * @comp: an XSLT comp
pcercuei 0:03b5121a232e 227 *
pcercuei 0:03b5121a232e 228 * Free up the memory allocated by @comp
pcercuei 0:03b5121a232e 229 */
pcercuei 0:03b5121a232e 230 void
pcercuei 0:03b5121a232e 231 xmlFreePattern(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 232 xmlStepOpPtr op;
pcercuei 0:03b5121a232e 233 int i;
pcercuei 0:03b5121a232e 234
pcercuei 0:03b5121a232e 235 if (comp == NULL)
pcercuei 0:03b5121a232e 236 return;
pcercuei 0:03b5121a232e 237 if (comp->next != NULL)
pcercuei 0:03b5121a232e 238 xmlFreePattern(comp->next);
pcercuei 0:03b5121a232e 239 if (comp->stream != NULL)
pcercuei 0:03b5121a232e 240 xmlFreeStreamComp(comp->stream);
pcercuei 0:03b5121a232e 241 if (comp->pattern != NULL)
pcercuei 0:03b5121a232e 242 xmlFree((xmlChar *)comp->pattern);
pcercuei 0:03b5121a232e 243 if (comp->steps != NULL) {
pcercuei 0:03b5121a232e 244 if (comp->dict == NULL) {
pcercuei 0:03b5121a232e 245 for (i = 0;i < comp->nbStep;i++) {
pcercuei 0:03b5121a232e 246 op = &comp->steps[i];
pcercuei 0:03b5121a232e 247 if (op->value != NULL)
pcercuei 0:03b5121a232e 248 xmlFree((xmlChar *) op->value);
pcercuei 0:03b5121a232e 249 if (op->value2 != NULL)
pcercuei 0:03b5121a232e 250 xmlFree((xmlChar *) op->value2);
pcercuei 0:03b5121a232e 251 }
pcercuei 0:03b5121a232e 252 }
pcercuei 0:03b5121a232e 253 xmlFree(comp->steps);
pcercuei 0:03b5121a232e 254 }
pcercuei 0:03b5121a232e 255 if (comp->dict != NULL)
pcercuei 0:03b5121a232e 256 xmlDictFree(comp->dict);
pcercuei 0:03b5121a232e 257
pcercuei 0:03b5121a232e 258 memset(comp, -1, sizeof(xmlPattern));
pcercuei 0:03b5121a232e 259 xmlFree(comp);
pcercuei 0:03b5121a232e 260 }
pcercuei 0:03b5121a232e 261
pcercuei 0:03b5121a232e 262 /**
pcercuei 0:03b5121a232e 263 * xmlFreePatternList:
pcercuei 0:03b5121a232e 264 * @comp: an XSLT comp list
pcercuei 0:03b5121a232e 265 *
pcercuei 0:03b5121a232e 266 * Free up the memory allocated by all the elements of @comp
pcercuei 0:03b5121a232e 267 */
pcercuei 0:03b5121a232e 268 void
pcercuei 0:03b5121a232e 269 xmlFreePatternList(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 270 xmlPatternPtr cur;
pcercuei 0:03b5121a232e 271
pcercuei 0:03b5121a232e 272 while (comp != NULL) {
pcercuei 0:03b5121a232e 273 cur = comp;
pcercuei 0:03b5121a232e 274 comp = comp->next;
pcercuei 0:03b5121a232e 275 cur->next = NULL;
pcercuei 0:03b5121a232e 276 xmlFreePattern(cur);
pcercuei 0:03b5121a232e 277 }
pcercuei 0:03b5121a232e 278 }
pcercuei 0:03b5121a232e 279
pcercuei 0:03b5121a232e 280 /**
pcercuei 0:03b5121a232e 281 * xmlNewPatParserContext:
pcercuei 0:03b5121a232e 282 * @pattern: the pattern context
pcercuei 0:03b5121a232e 283 * @dict: the inherited dictionary or NULL
pcercuei 0:03b5121a232e 284 * @namespaces: the prefix definitions, array of [URI, prefix] terminated
pcercuei 0:03b5121a232e 285 * with [NULL, NULL] or NULL if no namespace is used
pcercuei 0:03b5121a232e 286 *
pcercuei 0:03b5121a232e 287 * Create a new XML pattern parser context
pcercuei 0:03b5121a232e 288 *
pcercuei 0:03b5121a232e 289 * Returns the newly allocated xmlPatParserContextPtr or NULL in case of error
pcercuei 0:03b5121a232e 290 */
pcercuei 0:03b5121a232e 291 static xmlPatParserContextPtr
pcercuei 0:03b5121a232e 292 xmlNewPatParserContext(const xmlChar *pattern, xmlDictPtr dict,
pcercuei 0:03b5121a232e 293 const xmlChar **namespaces) {
pcercuei 0:03b5121a232e 294 xmlPatParserContextPtr cur;
pcercuei 0:03b5121a232e 295
pcercuei 0:03b5121a232e 296 if (pattern == NULL)
pcercuei 0:03b5121a232e 297 return(NULL);
pcercuei 0:03b5121a232e 298
pcercuei 0:03b5121a232e 299 cur = (xmlPatParserContextPtr) xmlMalloc(sizeof(xmlPatParserContext));
pcercuei 0:03b5121a232e 300 if (cur == NULL) {
pcercuei 0:03b5121a232e 301 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 302 "xmlNewPatParserContext : malloc failed\n");
pcercuei 0:03b5121a232e 303 return(NULL);
pcercuei 0:03b5121a232e 304 }
pcercuei 0:03b5121a232e 305 memset(cur, 0, sizeof(xmlPatParserContext));
pcercuei 0:03b5121a232e 306 cur->dict = dict;
pcercuei 0:03b5121a232e 307 cur->cur = pattern;
pcercuei 0:03b5121a232e 308 cur->base = pattern;
pcercuei 0:03b5121a232e 309 if (namespaces != NULL) {
pcercuei 0:03b5121a232e 310 int i;
pcercuei 0:03b5121a232e 311 for (i = 0;namespaces[2 * i] != NULL;i++)
pcercuei 0:03b5121a232e 312 ;
pcercuei 0:03b5121a232e 313 cur->nb_namespaces = i;
pcercuei 0:03b5121a232e 314 } else {
pcercuei 0:03b5121a232e 315 cur->nb_namespaces = 0;
pcercuei 0:03b5121a232e 316 }
pcercuei 0:03b5121a232e 317 cur->namespaces = namespaces;
pcercuei 0:03b5121a232e 318 return(cur);
pcercuei 0:03b5121a232e 319 }
pcercuei 0:03b5121a232e 320
pcercuei 0:03b5121a232e 321 /**
pcercuei 0:03b5121a232e 322 * xmlFreePatParserContext:
pcercuei 0:03b5121a232e 323 * @ctxt: an XSLT parser context
pcercuei 0:03b5121a232e 324 *
pcercuei 0:03b5121a232e 325 * Free up the memory allocated by @ctxt
pcercuei 0:03b5121a232e 326 */
pcercuei 0:03b5121a232e 327 static void
pcercuei 0:03b5121a232e 328 xmlFreePatParserContext(xmlPatParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 329 if (ctxt == NULL)
pcercuei 0:03b5121a232e 330 return;
pcercuei 0:03b5121a232e 331 memset(ctxt, -1, sizeof(xmlPatParserContext));
pcercuei 0:03b5121a232e 332 xmlFree(ctxt);
pcercuei 0:03b5121a232e 333 }
pcercuei 0:03b5121a232e 334
pcercuei 0:03b5121a232e 335 /**
pcercuei 0:03b5121a232e 336 * xmlPatternAdd:
pcercuei 0:03b5121a232e 337 * @comp: the compiled match expression
pcercuei 0:03b5121a232e 338 * @op: an op
pcercuei 0:03b5121a232e 339 * @value: the first value
pcercuei 0:03b5121a232e 340 * @value2: the second value
pcercuei 0:03b5121a232e 341 *
pcercuei 0:03b5121a232e 342 * Add a step to an XSLT Compiled Match
pcercuei 0:03b5121a232e 343 *
pcercuei 0:03b5121a232e 344 * Returns -1 in case of failure, 0 otherwise.
pcercuei 0:03b5121a232e 345 */
pcercuei 0:03b5121a232e 346 static int
pcercuei 0:03b5121a232e 347 xmlPatternAdd(xmlPatParserContextPtr ctxt ATTRIBUTE_UNUSED,
pcercuei 0:03b5121a232e 348 xmlPatternPtr comp,
pcercuei 0:03b5121a232e 349 xmlPatOp op, xmlChar * value, xmlChar * value2)
pcercuei 0:03b5121a232e 350 {
pcercuei 0:03b5121a232e 351 if (comp->nbStep >= comp->maxStep) {
pcercuei 0:03b5121a232e 352 xmlStepOpPtr temp;
pcercuei 0:03b5121a232e 353 temp = (xmlStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
pcercuei 0:03b5121a232e 354 sizeof(xmlStepOp));
pcercuei 0:03b5121a232e 355 if (temp == NULL) {
pcercuei 0:03b5121a232e 356 ERROR(ctxt, NULL, NULL,
pcercuei 0:03b5121a232e 357 "xmlPatternAdd: realloc failed\n");
pcercuei 0:03b5121a232e 358 return (-1);
pcercuei 0:03b5121a232e 359 }
pcercuei 0:03b5121a232e 360 comp->steps = temp;
pcercuei 0:03b5121a232e 361 comp->maxStep *= 2;
pcercuei 0:03b5121a232e 362 }
pcercuei 0:03b5121a232e 363 comp->steps[comp->nbStep].op = op;
pcercuei 0:03b5121a232e 364 comp->steps[comp->nbStep].value = value;
pcercuei 0:03b5121a232e 365 comp->steps[comp->nbStep].value2 = value2;
pcercuei 0:03b5121a232e 366 comp->nbStep++;
pcercuei 0:03b5121a232e 367 return (0);
pcercuei 0:03b5121a232e 368 }
pcercuei 0:03b5121a232e 369
pcercuei 0:03b5121a232e 370 #if 0
pcercuei 0:03b5121a232e 371 /**
pcercuei 0:03b5121a232e 372 * xsltSwapTopPattern:
pcercuei 0:03b5121a232e 373 * @comp: the compiled match expression
pcercuei 0:03b5121a232e 374 *
pcercuei 0:03b5121a232e 375 * reverse the two top steps.
pcercuei 0:03b5121a232e 376 */
pcercuei 0:03b5121a232e 377 static void
pcercuei 0:03b5121a232e 378 xsltSwapTopPattern(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 379 int i;
pcercuei 0:03b5121a232e 380 int j = comp->nbStep - 1;
pcercuei 0:03b5121a232e 381
pcercuei 0:03b5121a232e 382 if (j > 0) {
pcercuei 0:03b5121a232e 383 register const xmlChar *tmp;
pcercuei 0:03b5121a232e 384 register xmlPatOp op;
pcercuei 0:03b5121a232e 385 i = j - 1;
pcercuei 0:03b5121a232e 386 tmp = comp->steps[i].value;
pcercuei 0:03b5121a232e 387 comp->steps[i].value = comp->steps[j].value;
pcercuei 0:03b5121a232e 388 comp->steps[j].value = tmp;
pcercuei 0:03b5121a232e 389 tmp = comp->steps[i].value2;
pcercuei 0:03b5121a232e 390 comp->steps[i].value2 = comp->steps[j].value2;
pcercuei 0:03b5121a232e 391 comp->steps[j].value2 = tmp;
pcercuei 0:03b5121a232e 392 op = comp->steps[i].op;
pcercuei 0:03b5121a232e 393 comp->steps[i].op = comp->steps[j].op;
pcercuei 0:03b5121a232e 394 comp->steps[j].op = op;
pcercuei 0:03b5121a232e 395 }
pcercuei 0:03b5121a232e 396 }
pcercuei 0:03b5121a232e 397 #endif
pcercuei 0:03b5121a232e 398
pcercuei 0:03b5121a232e 399 /**
pcercuei 0:03b5121a232e 400 * xmlReversePattern:
pcercuei 0:03b5121a232e 401 * @comp: the compiled match expression
pcercuei 0:03b5121a232e 402 *
pcercuei 0:03b5121a232e 403 * reverse all the stack of expressions
pcercuei 0:03b5121a232e 404 *
pcercuei 0:03b5121a232e 405 * returns 0 in case of success and -1 in case of error.
pcercuei 0:03b5121a232e 406 */
pcercuei 0:03b5121a232e 407 static int
pcercuei 0:03b5121a232e 408 xmlReversePattern(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 409 int i, j;
pcercuei 0:03b5121a232e 410
pcercuei 0:03b5121a232e 411 /*
pcercuei 0:03b5121a232e 412 * remove the leading // for //a or .//a
pcercuei 0:03b5121a232e 413 */
pcercuei 0:03b5121a232e 414 if ((comp->nbStep > 0) && (comp->steps[0].op == XML_OP_ANCESTOR)) {
pcercuei 0:03b5121a232e 415 for (i = 0, j = 1;j < comp->nbStep;i++,j++) {
pcercuei 0:03b5121a232e 416 comp->steps[i].value = comp->steps[j].value;
pcercuei 0:03b5121a232e 417 comp->steps[i].value2 = comp->steps[j].value2;
pcercuei 0:03b5121a232e 418 comp->steps[i].op = comp->steps[j].op;
pcercuei 0:03b5121a232e 419 }
pcercuei 0:03b5121a232e 420 comp->nbStep--;
pcercuei 0:03b5121a232e 421 }
pcercuei 0:03b5121a232e 422 if (comp->nbStep >= comp->maxStep) {
pcercuei 0:03b5121a232e 423 xmlStepOpPtr temp;
pcercuei 0:03b5121a232e 424 temp = (xmlStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
pcercuei 0:03b5121a232e 425 sizeof(xmlStepOp));
pcercuei 0:03b5121a232e 426 if (temp == NULL) {
pcercuei 0:03b5121a232e 427 ERROR(ctxt, NULL, NULL,
pcercuei 0:03b5121a232e 428 "xmlReversePattern: realloc failed\n");
pcercuei 0:03b5121a232e 429 return (-1);
pcercuei 0:03b5121a232e 430 }
pcercuei 0:03b5121a232e 431 comp->steps = temp;
pcercuei 0:03b5121a232e 432 comp->maxStep *= 2;
pcercuei 0:03b5121a232e 433 }
pcercuei 0:03b5121a232e 434 i = 0;
pcercuei 0:03b5121a232e 435 j = comp->nbStep - 1;
pcercuei 0:03b5121a232e 436 while (j > i) {
pcercuei 0:03b5121a232e 437 register const xmlChar *tmp;
pcercuei 0:03b5121a232e 438 register xmlPatOp op;
pcercuei 0:03b5121a232e 439 tmp = comp->steps[i].value;
pcercuei 0:03b5121a232e 440 comp->steps[i].value = comp->steps[j].value;
pcercuei 0:03b5121a232e 441 comp->steps[j].value = tmp;
pcercuei 0:03b5121a232e 442 tmp = comp->steps[i].value2;
pcercuei 0:03b5121a232e 443 comp->steps[i].value2 = comp->steps[j].value2;
pcercuei 0:03b5121a232e 444 comp->steps[j].value2 = tmp;
pcercuei 0:03b5121a232e 445 op = comp->steps[i].op;
pcercuei 0:03b5121a232e 446 comp->steps[i].op = comp->steps[j].op;
pcercuei 0:03b5121a232e 447 comp->steps[j].op = op;
pcercuei 0:03b5121a232e 448 j--;
pcercuei 0:03b5121a232e 449 i++;
pcercuei 0:03b5121a232e 450 }
pcercuei 0:03b5121a232e 451 comp->steps[comp->nbStep].value = NULL;
pcercuei 0:03b5121a232e 452 comp->steps[comp->nbStep].value2 = NULL;
pcercuei 0:03b5121a232e 453 comp->steps[comp->nbStep++].op = XML_OP_END;
pcercuei 0:03b5121a232e 454 return(0);
pcercuei 0:03b5121a232e 455 }
pcercuei 0:03b5121a232e 456
pcercuei 0:03b5121a232e 457 /************************************************************************
pcercuei 0:03b5121a232e 458 * *
pcercuei 0:03b5121a232e 459 * The interpreter for the precompiled patterns *
pcercuei 0:03b5121a232e 460 * *
pcercuei 0:03b5121a232e 461 ************************************************************************/
pcercuei 0:03b5121a232e 462
pcercuei 0:03b5121a232e 463 static int
pcercuei 0:03b5121a232e 464 xmlPatPushState(xmlStepStates *states, int step, xmlNodePtr node) {
pcercuei 0:03b5121a232e 465 if ((states->states == NULL) || (states->maxstates <= 0)) {
pcercuei 0:03b5121a232e 466 states->maxstates = 4;
pcercuei 0:03b5121a232e 467 states->nbstates = 0;
pcercuei 0:03b5121a232e 468 states->states = xmlMalloc(4 * sizeof(xmlStepState));
pcercuei 0:03b5121a232e 469 }
pcercuei 0:03b5121a232e 470 else if (states->maxstates <= states->nbstates) {
pcercuei 0:03b5121a232e 471 xmlStepState *tmp;
pcercuei 0:03b5121a232e 472
pcercuei 0:03b5121a232e 473 tmp = (xmlStepStatePtr) xmlRealloc(states->states,
pcercuei 0:03b5121a232e 474 2 * states->maxstates * sizeof(xmlStepState));
pcercuei 0:03b5121a232e 475 if (tmp == NULL)
pcercuei 0:03b5121a232e 476 return(-1);
pcercuei 0:03b5121a232e 477 states->states = tmp;
pcercuei 0:03b5121a232e 478 states->maxstates *= 2;
pcercuei 0:03b5121a232e 479 }
pcercuei 0:03b5121a232e 480 states->states[states->nbstates].step = step;
pcercuei 0:03b5121a232e 481 states->states[states->nbstates++].node = node;
pcercuei 0:03b5121a232e 482 #if 0
pcercuei 0:03b5121a232e 483 fprintf(stderr, "Push: %d, %s\n", step, node->name);
pcercuei 0:03b5121a232e 484 #endif
pcercuei 0:03b5121a232e 485 return(0);
pcercuei 0:03b5121a232e 486 }
pcercuei 0:03b5121a232e 487
pcercuei 0:03b5121a232e 488 /**
pcercuei 0:03b5121a232e 489 * xmlPatMatch:
pcercuei 0:03b5121a232e 490 * @comp: the precompiled pattern
pcercuei 0:03b5121a232e 491 * @node: a node
pcercuei 0:03b5121a232e 492 *
pcercuei 0:03b5121a232e 493 * Test whether the node matches the pattern
pcercuei 0:03b5121a232e 494 *
pcercuei 0:03b5121a232e 495 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
pcercuei 0:03b5121a232e 496 */
pcercuei 0:03b5121a232e 497 static int
pcercuei 0:03b5121a232e 498 xmlPatMatch(xmlPatternPtr comp, xmlNodePtr node) {
pcercuei 0:03b5121a232e 499 int i;
pcercuei 0:03b5121a232e 500 xmlStepOpPtr step;
pcercuei 0:03b5121a232e 501 xmlStepStates states = {0, 0, NULL}; /* // may require backtrack */
pcercuei 0:03b5121a232e 502
pcercuei 0:03b5121a232e 503 if ((comp == NULL) || (node == NULL)) return(-1);
pcercuei 0:03b5121a232e 504 i = 0;
pcercuei 0:03b5121a232e 505 restart:
pcercuei 0:03b5121a232e 506 for (;i < comp->nbStep;i++) {
pcercuei 0:03b5121a232e 507 step = &comp->steps[i];
pcercuei 0:03b5121a232e 508 switch (step->op) {
pcercuei 0:03b5121a232e 509 case XML_OP_END:
pcercuei 0:03b5121a232e 510 goto found;
pcercuei 0:03b5121a232e 511 case XML_OP_ROOT:
pcercuei 0:03b5121a232e 512 if (node->type == XML_NAMESPACE_DECL)
pcercuei 0:03b5121a232e 513 goto rollback;
pcercuei 0:03b5121a232e 514 node = node->parent;
pcercuei 0:03b5121a232e 515 if ((node->type == XML_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 516 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 517 (node->type == XML_DOCB_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 518 #endif
pcercuei 0:03b5121a232e 519 (node->type == XML_HTML_DOCUMENT_NODE))
pcercuei 0:03b5121a232e 520 continue;
pcercuei 0:03b5121a232e 521 goto rollback;
pcercuei 0:03b5121a232e 522 case XML_OP_ELEM:
pcercuei 0:03b5121a232e 523 if (node->type != XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 524 goto rollback;
pcercuei 0:03b5121a232e 525 if (step->value == NULL)
pcercuei 0:03b5121a232e 526 continue;
pcercuei 0:03b5121a232e 527 if (step->value[0] != node->name[0])
pcercuei 0:03b5121a232e 528 goto rollback;
pcercuei 0:03b5121a232e 529 if (!xmlStrEqual(step->value, node->name))
pcercuei 0:03b5121a232e 530 goto rollback;
pcercuei 0:03b5121a232e 531
pcercuei 0:03b5121a232e 532 /* Namespace test */
pcercuei 0:03b5121a232e 533 if (node->ns == NULL) {
pcercuei 0:03b5121a232e 534 if (step->value2 != NULL)
pcercuei 0:03b5121a232e 535 goto rollback;
pcercuei 0:03b5121a232e 536 } else if (node->ns->href != NULL) {
pcercuei 0:03b5121a232e 537 if (step->value2 == NULL)
pcercuei 0:03b5121a232e 538 goto rollback;
pcercuei 0:03b5121a232e 539 if (!xmlStrEqual(step->value2, node->ns->href))
pcercuei 0:03b5121a232e 540 goto rollback;
pcercuei 0:03b5121a232e 541 }
pcercuei 0:03b5121a232e 542 continue;
pcercuei 0:03b5121a232e 543 case XML_OP_CHILD: {
pcercuei 0:03b5121a232e 544 xmlNodePtr lst;
pcercuei 0:03b5121a232e 545
pcercuei 0:03b5121a232e 546 if ((node->type != XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 547 (node->type != XML_DOCUMENT_NODE) &&
pcercuei 0:03b5121a232e 548 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 549 (node->type != XML_DOCB_DOCUMENT_NODE) &&
pcercuei 0:03b5121a232e 550 #endif
pcercuei 0:03b5121a232e 551 (node->type != XML_HTML_DOCUMENT_NODE))
pcercuei 0:03b5121a232e 552 goto rollback;
pcercuei 0:03b5121a232e 553
pcercuei 0:03b5121a232e 554 lst = node->children;
pcercuei 0:03b5121a232e 555
pcercuei 0:03b5121a232e 556 if (step->value != NULL) {
pcercuei 0:03b5121a232e 557 while (lst != NULL) {
pcercuei 0:03b5121a232e 558 if ((lst->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 559 (step->value[0] == lst->name[0]) &&
pcercuei 0:03b5121a232e 560 (xmlStrEqual(step->value, lst->name)))
pcercuei 0:03b5121a232e 561 break;
pcercuei 0:03b5121a232e 562 lst = lst->next;
pcercuei 0:03b5121a232e 563 }
pcercuei 0:03b5121a232e 564 if (lst != NULL)
pcercuei 0:03b5121a232e 565 continue;
pcercuei 0:03b5121a232e 566 }
pcercuei 0:03b5121a232e 567 goto rollback;
pcercuei 0:03b5121a232e 568 }
pcercuei 0:03b5121a232e 569 case XML_OP_ATTR:
pcercuei 0:03b5121a232e 570 if (node->type != XML_ATTRIBUTE_NODE)
pcercuei 0:03b5121a232e 571 goto rollback;
pcercuei 0:03b5121a232e 572 if (step->value != NULL) {
pcercuei 0:03b5121a232e 573 if (step->value[0] != node->name[0])
pcercuei 0:03b5121a232e 574 goto rollback;
pcercuei 0:03b5121a232e 575 if (!xmlStrEqual(step->value, node->name))
pcercuei 0:03b5121a232e 576 goto rollback;
pcercuei 0:03b5121a232e 577 }
pcercuei 0:03b5121a232e 578 /* Namespace test */
pcercuei 0:03b5121a232e 579 if (node->ns == NULL) {
pcercuei 0:03b5121a232e 580 if (step->value2 != NULL)
pcercuei 0:03b5121a232e 581 goto rollback;
pcercuei 0:03b5121a232e 582 } else if (step->value2 != NULL) {
pcercuei 0:03b5121a232e 583 if (!xmlStrEqual(step->value2, node->ns->href))
pcercuei 0:03b5121a232e 584 goto rollback;
pcercuei 0:03b5121a232e 585 }
pcercuei 0:03b5121a232e 586 continue;
pcercuei 0:03b5121a232e 587 case XML_OP_PARENT:
pcercuei 0:03b5121a232e 588 if ((node->type == XML_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 589 (node->type == XML_HTML_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 590 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 591 (node->type == XML_DOCB_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 592 #endif
pcercuei 0:03b5121a232e 593 (node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 594 goto rollback;
pcercuei 0:03b5121a232e 595 node = node->parent;
pcercuei 0:03b5121a232e 596 if (node == NULL)
pcercuei 0:03b5121a232e 597 goto rollback;
pcercuei 0:03b5121a232e 598 if (step->value == NULL)
pcercuei 0:03b5121a232e 599 continue;
pcercuei 0:03b5121a232e 600 if (step->value[0] != node->name[0])
pcercuei 0:03b5121a232e 601 goto rollback;
pcercuei 0:03b5121a232e 602 if (!xmlStrEqual(step->value, node->name))
pcercuei 0:03b5121a232e 603 goto rollback;
pcercuei 0:03b5121a232e 604 /* Namespace test */
pcercuei 0:03b5121a232e 605 if (node->ns == NULL) {
pcercuei 0:03b5121a232e 606 if (step->value2 != NULL)
pcercuei 0:03b5121a232e 607 goto rollback;
pcercuei 0:03b5121a232e 608 } else if (node->ns->href != NULL) {
pcercuei 0:03b5121a232e 609 if (step->value2 == NULL)
pcercuei 0:03b5121a232e 610 goto rollback;
pcercuei 0:03b5121a232e 611 if (!xmlStrEqual(step->value2, node->ns->href))
pcercuei 0:03b5121a232e 612 goto rollback;
pcercuei 0:03b5121a232e 613 }
pcercuei 0:03b5121a232e 614 continue;
pcercuei 0:03b5121a232e 615 case XML_OP_ANCESTOR:
pcercuei 0:03b5121a232e 616 /* TODO: implement coalescing of ANCESTOR/NODE ops */
pcercuei 0:03b5121a232e 617 if (step->value == NULL) {
pcercuei 0:03b5121a232e 618 i++;
pcercuei 0:03b5121a232e 619 step = &comp->steps[i];
pcercuei 0:03b5121a232e 620 if (step->op == XML_OP_ROOT)
pcercuei 0:03b5121a232e 621 goto found;
pcercuei 0:03b5121a232e 622 if (step->op != XML_OP_ELEM)
pcercuei 0:03b5121a232e 623 goto rollback;
pcercuei 0:03b5121a232e 624 if (step->value == NULL)
pcercuei 0:03b5121a232e 625 return(-1);
pcercuei 0:03b5121a232e 626 }
pcercuei 0:03b5121a232e 627 if (node == NULL)
pcercuei 0:03b5121a232e 628 goto rollback;
pcercuei 0:03b5121a232e 629 if ((node->type == XML_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 630 (node->type == XML_HTML_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 631 #ifdef LIBXML_DOCB_ENABLED
pcercuei 0:03b5121a232e 632 (node->type == XML_DOCB_DOCUMENT_NODE) ||
pcercuei 0:03b5121a232e 633 #endif
pcercuei 0:03b5121a232e 634 (node->type == XML_NAMESPACE_DECL))
pcercuei 0:03b5121a232e 635 goto rollback;
pcercuei 0:03b5121a232e 636 node = node->parent;
pcercuei 0:03b5121a232e 637 while (node != NULL) {
pcercuei 0:03b5121a232e 638 if ((node->type == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 639 (step->value[0] == node->name[0]) &&
pcercuei 0:03b5121a232e 640 (xmlStrEqual(step->value, node->name))) {
pcercuei 0:03b5121a232e 641 /* Namespace test */
pcercuei 0:03b5121a232e 642 if (node->ns == NULL) {
pcercuei 0:03b5121a232e 643 if (step->value2 == NULL)
pcercuei 0:03b5121a232e 644 break;
pcercuei 0:03b5121a232e 645 } else if (node->ns->href != NULL) {
pcercuei 0:03b5121a232e 646 if ((step->value2 != NULL) &&
pcercuei 0:03b5121a232e 647 (xmlStrEqual(step->value2, node->ns->href)))
pcercuei 0:03b5121a232e 648 break;
pcercuei 0:03b5121a232e 649 }
pcercuei 0:03b5121a232e 650 }
pcercuei 0:03b5121a232e 651 node = node->parent;
pcercuei 0:03b5121a232e 652 }
pcercuei 0:03b5121a232e 653 if (node == NULL)
pcercuei 0:03b5121a232e 654 goto rollback;
pcercuei 0:03b5121a232e 655 /*
pcercuei 0:03b5121a232e 656 * prepare a potential rollback from here
pcercuei 0:03b5121a232e 657 * for ancestors of that node.
pcercuei 0:03b5121a232e 658 */
pcercuei 0:03b5121a232e 659 if (step->op == XML_OP_ANCESTOR)
pcercuei 0:03b5121a232e 660 xmlPatPushState(&states, i, node);
pcercuei 0:03b5121a232e 661 else
pcercuei 0:03b5121a232e 662 xmlPatPushState(&states, i - 1, node);
pcercuei 0:03b5121a232e 663 continue;
pcercuei 0:03b5121a232e 664 case XML_OP_NS:
pcercuei 0:03b5121a232e 665 if (node->type != XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 666 goto rollback;
pcercuei 0:03b5121a232e 667 if (node->ns == NULL) {
pcercuei 0:03b5121a232e 668 if (step->value != NULL)
pcercuei 0:03b5121a232e 669 goto rollback;
pcercuei 0:03b5121a232e 670 } else if (node->ns->href != NULL) {
pcercuei 0:03b5121a232e 671 if (step->value == NULL)
pcercuei 0:03b5121a232e 672 goto rollback;
pcercuei 0:03b5121a232e 673 if (!xmlStrEqual(step->value, node->ns->href))
pcercuei 0:03b5121a232e 674 goto rollback;
pcercuei 0:03b5121a232e 675 }
pcercuei 0:03b5121a232e 676 break;
pcercuei 0:03b5121a232e 677 case XML_OP_ALL:
pcercuei 0:03b5121a232e 678 if (node->type != XML_ELEMENT_NODE)
pcercuei 0:03b5121a232e 679 goto rollback;
pcercuei 0:03b5121a232e 680 break;
pcercuei 0:03b5121a232e 681 }
pcercuei 0:03b5121a232e 682 }
pcercuei 0:03b5121a232e 683 found:
pcercuei 0:03b5121a232e 684 if (states.states != NULL) {
pcercuei 0:03b5121a232e 685 /* Free the rollback states */
pcercuei 0:03b5121a232e 686 xmlFree(states.states);
pcercuei 0:03b5121a232e 687 }
pcercuei 0:03b5121a232e 688 return(1);
pcercuei 0:03b5121a232e 689 rollback:
pcercuei 0:03b5121a232e 690 /* got an error try to rollback */
pcercuei 0:03b5121a232e 691 if (states.states == NULL)
pcercuei 0:03b5121a232e 692 return(0);
pcercuei 0:03b5121a232e 693 if (states.nbstates <= 0) {
pcercuei 0:03b5121a232e 694 xmlFree(states.states);
pcercuei 0:03b5121a232e 695 return(0);
pcercuei 0:03b5121a232e 696 }
pcercuei 0:03b5121a232e 697 states.nbstates--;
pcercuei 0:03b5121a232e 698 i = states.states[states.nbstates].step;
pcercuei 0:03b5121a232e 699 node = states.states[states.nbstates].node;
pcercuei 0:03b5121a232e 700 #if 0
pcercuei 0:03b5121a232e 701 fprintf(stderr, "Pop: %d, %s\n", i, node->name);
pcercuei 0:03b5121a232e 702 #endif
pcercuei 0:03b5121a232e 703 goto restart;
pcercuei 0:03b5121a232e 704 }
pcercuei 0:03b5121a232e 705
pcercuei 0:03b5121a232e 706 /************************************************************************
pcercuei 0:03b5121a232e 707 * *
pcercuei 0:03b5121a232e 708 * Dedicated parser for templates *
pcercuei 0:03b5121a232e 709 * *
pcercuei 0:03b5121a232e 710 ************************************************************************/
pcercuei 0:03b5121a232e 711
pcercuei 0:03b5121a232e 712 #define TODO \
pcercuei 0:03b5121a232e 713 xmlGenericError(xmlGenericErrorContext, \
pcercuei 0:03b5121a232e 714 "Unimplemented block at %s:%d\n", \
pcercuei 0:03b5121a232e 715 __FILE__, __LINE__);
pcercuei 0:03b5121a232e 716 #define CUR (*ctxt->cur)
pcercuei 0:03b5121a232e 717 #define SKIP(val) ctxt->cur += (val)
pcercuei 0:03b5121a232e 718 #define NXT(val) ctxt->cur[(val)]
pcercuei 0:03b5121a232e 719 #define PEEKPREV(val) ctxt->cur[-(val)]
pcercuei 0:03b5121a232e 720 #define CUR_PTR ctxt->cur
pcercuei 0:03b5121a232e 721
pcercuei 0:03b5121a232e 722 #define SKIP_BLANKS \
pcercuei 0:03b5121a232e 723 while (IS_BLANK_CH(CUR)) NEXT
pcercuei 0:03b5121a232e 724
pcercuei 0:03b5121a232e 725 #define CURRENT (*ctxt->cur)
pcercuei 0:03b5121a232e 726 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
pcercuei 0:03b5121a232e 727
pcercuei 0:03b5121a232e 728
pcercuei 0:03b5121a232e 729 #define PUSH(op, val, val2) \
pcercuei 0:03b5121a232e 730 if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error;
pcercuei 0:03b5121a232e 731
pcercuei 0:03b5121a232e 732 #define XSLT_ERROR(X) \
pcercuei 0:03b5121a232e 733 { xsltError(ctxt, __FILE__, __LINE__, X); \
pcercuei 0:03b5121a232e 734 ctxt->error = (X); return; }
pcercuei 0:03b5121a232e 735
pcercuei 0:03b5121a232e 736 #define XSLT_ERROR0(X) \
pcercuei 0:03b5121a232e 737 { xsltError(ctxt, __FILE__, __LINE__, X); \
pcercuei 0:03b5121a232e 738 ctxt->error = (X); return(0); }
pcercuei 0:03b5121a232e 739
pcercuei 0:03b5121a232e 740 #if 0
pcercuei 0:03b5121a232e 741 /**
pcercuei 0:03b5121a232e 742 * xmlPatScanLiteral:
pcercuei 0:03b5121a232e 743 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 744 *
pcercuei 0:03b5121a232e 745 * Parse an XPath Litteral:
pcercuei 0:03b5121a232e 746 *
pcercuei 0:03b5121a232e 747 * [29] Literal ::= '"' [^"]* '"'
pcercuei 0:03b5121a232e 748 * | "'" [^']* "'"
pcercuei 0:03b5121a232e 749 *
pcercuei 0:03b5121a232e 750 * Returns the Literal parsed or NULL
pcercuei 0:03b5121a232e 751 */
pcercuei 0:03b5121a232e 752
pcercuei 0:03b5121a232e 753 static xmlChar *
pcercuei 0:03b5121a232e 754 xmlPatScanLiteral(xmlPatParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 755 const xmlChar *q, *cur;
pcercuei 0:03b5121a232e 756 xmlChar *ret = NULL;
pcercuei 0:03b5121a232e 757 int val, len;
pcercuei 0:03b5121a232e 758
pcercuei 0:03b5121a232e 759 SKIP_BLANKS;
pcercuei 0:03b5121a232e 760 if (CUR == '"') {
pcercuei 0:03b5121a232e 761 NEXT;
pcercuei 0:03b5121a232e 762 cur = q = CUR_PTR;
pcercuei 0:03b5121a232e 763 val = xmlStringCurrentChar(NULL, cur, &len);
pcercuei 0:03b5121a232e 764 while ((IS_CHAR(val)) && (val != '"')) {
pcercuei 0:03b5121a232e 765 cur += len;
pcercuei 0:03b5121a232e 766 val = xmlStringCurrentChar(NULL, cur, &len);
pcercuei 0:03b5121a232e 767 }
pcercuei 0:03b5121a232e 768 if (!IS_CHAR(val)) {
pcercuei 0:03b5121a232e 769 ctxt->error = 1;
pcercuei 0:03b5121a232e 770 return(NULL);
pcercuei 0:03b5121a232e 771 } else {
pcercuei 0:03b5121a232e 772 if (ctxt->dict)
pcercuei 0:03b5121a232e 773 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
pcercuei 0:03b5121a232e 774 else
pcercuei 0:03b5121a232e 775 ret = xmlStrndup(q, cur - q);
pcercuei 0:03b5121a232e 776 }
pcercuei 0:03b5121a232e 777 cur += len;
pcercuei 0:03b5121a232e 778 CUR_PTR = cur;
pcercuei 0:03b5121a232e 779 } else if (CUR == '\'') {
pcercuei 0:03b5121a232e 780 NEXT;
pcercuei 0:03b5121a232e 781 cur = q = CUR_PTR;
pcercuei 0:03b5121a232e 782 val = xmlStringCurrentChar(NULL, cur, &len);
pcercuei 0:03b5121a232e 783 while ((IS_CHAR(val)) && (val != '\'')) {
pcercuei 0:03b5121a232e 784 cur += len;
pcercuei 0:03b5121a232e 785 val = xmlStringCurrentChar(NULL, cur, &len);
pcercuei 0:03b5121a232e 786 }
pcercuei 0:03b5121a232e 787 if (!IS_CHAR(val)) {
pcercuei 0:03b5121a232e 788 ctxt->error = 1;
pcercuei 0:03b5121a232e 789 return(NULL);
pcercuei 0:03b5121a232e 790 } else {
pcercuei 0:03b5121a232e 791 if (ctxt->dict)
pcercuei 0:03b5121a232e 792 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
pcercuei 0:03b5121a232e 793 else
pcercuei 0:03b5121a232e 794 ret = xmlStrndup(q, cur - q);
pcercuei 0:03b5121a232e 795 }
pcercuei 0:03b5121a232e 796 cur += len;
pcercuei 0:03b5121a232e 797 CUR_PTR = cur;
pcercuei 0:03b5121a232e 798 } else {
pcercuei 0:03b5121a232e 799 /* XP_ERROR(XPATH_START_LITERAL_ERROR); */
pcercuei 0:03b5121a232e 800 ctxt->error = 1;
pcercuei 0:03b5121a232e 801 return(NULL);
pcercuei 0:03b5121a232e 802 }
pcercuei 0:03b5121a232e 803 return(ret);
pcercuei 0:03b5121a232e 804 }
pcercuei 0:03b5121a232e 805 #endif
pcercuei 0:03b5121a232e 806
pcercuei 0:03b5121a232e 807 /**
pcercuei 0:03b5121a232e 808 * xmlPatScanName:
pcercuei 0:03b5121a232e 809 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 810 *
pcercuei 0:03b5121a232e 811 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' |
pcercuei 0:03b5121a232e 812 * CombiningChar | Extender
pcercuei 0:03b5121a232e 813 *
pcercuei 0:03b5121a232e 814 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
pcercuei 0:03b5121a232e 815 *
pcercuei 0:03b5121a232e 816 * [6] Names ::= Name (S Name)*
pcercuei 0:03b5121a232e 817 *
pcercuei 0:03b5121a232e 818 * Returns the Name parsed or NULL
pcercuei 0:03b5121a232e 819 */
pcercuei 0:03b5121a232e 820
pcercuei 0:03b5121a232e 821 static xmlChar *
pcercuei 0:03b5121a232e 822 xmlPatScanName(xmlPatParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 823 const xmlChar *q, *cur;
pcercuei 0:03b5121a232e 824 xmlChar *ret = NULL;
pcercuei 0:03b5121a232e 825 int val, len;
pcercuei 0:03b5121a232e 826
pcercuei 0:03b5121a232e 827 SKIP_BLANKS;
pcercuei 0:03b5121a232e 828
pcercuei 0:03b5121a232e 829 cur = q = CUR_PTR;
pcercuei 0:03b5121a232e 830 val = xmlStringCurrentChar(NULL, cur, &len);
pcercuei 0:03b5121a232e 831 if (!IS_LETTER(val) && (val != '_') && (val != ':'))
pcercuei 0:03b5121a232e 832 return(NULL);
pcercuei 0:03b5121a232e 833
pcercuei 0:03b5121a232e 834 while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
pcercuei 0:03b5121a232e 835 (val == '.') || (val == '-') ||
pcercuei 0:03b5121a232e 836 (val == '_') ||
pcercuei 0:03b5121a232e 837 (IS_COMBINING(val)) ||
pcercuei 0:03b5121a232e 838 (IS_EXTENDER(val))) {
pcercuei 0:03b5121a232e 839 cur += len;
pcercuei 0:03b5121a232e 840 val = xmlStringCurrentChar(NULL, cur, &len);
pcercuei 0:03b5121a232e 841 }
pcercuei 0:03b5121a232e 842 if (ctxt->dict)
pcercuei 0:03b5121a232e 843 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
pcercuei 0:03b5121a232e 844 else
pcercuei 0:03b5121a232e 845 ret = xmlStrndup(q, cur - q);
pcercuei 0:03b5121a232e 846 CUR_PTR = cur;
pcercuei 0:03b5121a232e 847 return(ret);
pcercuei 0:03b5121a232e 848 }
pcercuei 0:03b5121a232e 849
pcercuei 0:03b5121a232e 850 /**
pcercuei 0:03b5121a232e 851 * xmlPatScanNCName:
pcercuei 0:03b5121a232e 852 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 853 *
pcercuei 0:03b5121a232e 854 * Parses a non qualified name
pcercuei 0:03b5121a232e 855 *
pcercuei 0:03b5121a232e 856 * Returns the Name parsed or NULL
pcercuei 0:03b5121a232e 857 */
pcercuei 0:03b5121a232e 858
pcercuei 0:03b5121a232e 859 static xmlChar *
pcercuei 0:03b5121a232e 860 xmlPatScanNCName(xmlPatParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 861 const xmlChar *q, *cur;
pcercuei 0:03b5121a232e 862 xmlChar *ret = NULL;
pcercuei 0:03b5121a232e 863 int val, len;
pcercuei 0:03b5121a232e 864
pcercuei 0:03b5121a232e 865 SKIP_BLANKS;
pcercuei 0:03b5121a232e 866
pcercuei 0:03b5121a232e 867 cur = q = CUR_PTR;
pcercuei 0:03b5121a232e 868 val = xmlStringCurrentChar(NULL, cur, &len);
pcercuei 0:03b5121a232e 869 if (!IS_LETTER(val) && (val != '_'))
pcercuei 0:03b5121a232e 870 return(NULL);
pcercuei 0:03b5121a232e 871
pcercuei 0:03b5121a232e 872 while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
pcercuei 0:03b5121a232e 873 (val == '.') || (val == '-') ||
pcercuei 0:03b5121a232e 874 (val == '_') ||
pcercuei 0:03b5121a232e 875 (IS_COMBINING(val)) ||
pcercuei 0:03b5121a232e 876 (IS_EXTENDER(val))) {
pcercuei 0:03b5121a232e 877 cur += len;
pcercuei 0:03b5121a232e 878 val = xmlStringCurrentChar(NULL, cur, &len);
pcercuei 0:03b5121a232e 879 }
pcercuei 0:03b5121a232e 880 if (ctxt->dict)
pcercuei 0:03b5121a232e 881 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q);
pcercuei 0:03b5121a232e 882 else
pcercuei 0:03b5121a232e 883 ret = xmlStrndup(q, cur - q);
pcercuei 0:03b5121a232e 884 CUR_PTR = cur;
pcercuei 0:03b5121a232e 885 return(ret);
pcercuei 0:03b5121a232e 886 }
pcercuei 0:03b5121a232e 887
pcercuei 0:03b5121a232e 888 #if 0
pcercuei 0:03b5121a232e 889 /**
pcercuei 0:03b5121a232e 890 * xmlPatScanQName:
pcercuei 0:03b5121a232e 891 * @ctxt: the XPath Parser context
pcercuei 0:03b5121a232e 892 * @prefix: the place to store the prefix
pcercuei 0:03b5121a232e 893 *
pcercuei 0:03b5121a232e 894 * Parse a qualified name
pcercuei 0:03b5121a232e 895 *
pcercuei 0:03b5121a232e 896 * Returns the Name parsed or NULL
pcercuei 0:03b5121a232e 897 */
pcercuei 0:03b5121a232e 898
pcercuei 0:03b5121a232e 899 static xmlChar *
pcercuei 0:03b5121a232e 900 xmlPatScanQName(xmlPatParserContextPtr ctxt, xmlChar **prefix) {
pcercuei 0:03b5121a232e 901 xmlChar *ret = NULL;
pcercuei 0:03b5121a232e 902
pcercuei 0:03b5121a232e 903 *prefix = NULL;
pcercuei 0:03b5121a232e 904 ret = xmlPatScanNCName(ctxt);
pcercuei 0:03b5121a232e 905 if (CUR == ':') {
pcercuei 0:03b5121a232e 906 *prefix = ret;
pcercuei 0:03b5121a232e 907 NEXT;
pcercuei 0:03b5121a232e 908 ret = xmlPatScanNCName(ctxt);
pcercuei 0:03b5121a232e 909 }
pcercuei 0:03b5121a232e 910 return(ret);
pcercuei 0:03b5121a232e 911 }
pcercuei 0:03b5121a232e 912 #endif
pcercuei 0:03b5121a232e 913
pcercuei 0:03b5121a232e 914 /**
pcercuei 0:03b5121a232e 915 * xmlCompileAttributeTest:
pcercuei 0:03b5121a232e 916 * @ctxt: the compilation context
pcercuei 0:03b5121a232e 917 *
pcercuei 0:03b5121a232e 918 * Compile an attribute test.
pcercuei 0:03b5121a232e 919 */
pcercuei 0:03b5121a232e 920 static void
pcercuei 0:03b5121a232e 921 xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 922 xmlChar *token = NULL;
pcercuei 0:03b5121a232e 923 xmlChar *name = NULL;
pcercuei 0:03b5121a232e 924 xmlChar *URL = NULL;
pcercuei 0:03b5121a232e 925
pcercuei 0:03b5121a232e 926 SKIP_BLANKS;
pcercuei 0:03b5121a232e 927 name = xmlPatScanNCName(ctxt);
pcercuei 0:03b5121a232e 928 if (name == NULL) {
pcercuei 0:03b5121a232e 929 if (CUR == '*') {
pcercuei 0:03b5121a232e 930 PUSH(XML_OP_ATTR, NULL, NULL);
pcercuei 0:03b5121a232e 931 NEXT;
pcercuei 0:03b5121a232e 932 } else {
pcercuei 0:03b5121a232e 933 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 934 "xmlCompileAttributeTest : Name expected\n");
pcercuei 0:03b5121a232e 935 ctxt->error = 1;
pcercuei 0:03b5121a232e 936 }
pcercuei 0:03b5121a232e 937 return;
pcercuei 0:03b5121a232e 938 }
pcercuei 0:03b5121a232e 939 if (CUR == ':') {
pcercuei 0:03b5121a232e 940 int i;
pcercuei 0:03b5121a232e 941 xmlChar *prefix = name;
pcercuei 0:03b5121a232e 942
pcercuei 0:03b5121a232e 943 NEXT;
pcercuei 0:03b5121a232e 944
pcercuei 0:03b5121a232e 945 if (IS_BLANK_CH(CUR)) {
pcercuei 0:03b5121a232e 946 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
pcercuei 0:03b5121a232e 947 XML_PAT_FREE_STRING(ctxt, prefix);
pcercuei 0:03b5121a232e 948 ctxt->error = 1;
pcercuei 0:03b5121a232e 949 goto error;
pcercuei 0:03b5121a232e 950 }
pcercuei 0:03b5121a232e 951 /*
pcercuei 0:03b5121a232e 952 * This is a namespace match
pcercuei 0:03b5121a232e 953 */
pcercuei 0:03b5121a232e 954 token = xmlPatScanName(ctxt);
pcercuei 0:03b5121a232e 955 if ((prefix[0] == 'x') &&
pcercuei 0:03b5121a232e 956 (prefix[1] == 'm') &&
pcercuei 0:03b5121a232e 957 (prefix[2] == 'l') &&
pcercuei 0:03b5121a232e 958 (prefix[3] == 0))
pcercuei 0:03b5121a232e 959 {
pcercuei 0:03b5121a232e 960 XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE);
pcercuei 0:03b5121a232e 961 } else {
pcercuei 0:03b5121a232e 962 for (i = 0;i < ctxt->nb_namespaces;i++) {
pcercuei 0:03b5121a232e 963 if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
pcercuei 0:03b5121a232e 964 XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
pcercuei 0:03b5121a232e 965 break;
pcercuei 0:03b5121a232e 966 }
pcercuei 0:03b5121a232e 967 }
pcercuei 0:03b5121a232e 968 if (i >= ctxt->nb_namespaces) {
pcercuei 0:03b5121a232e 969 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 970 "xmlCompileAttributeTest : no namespace bound to prefix %s\n",
pcercuei 0:03b5121a232e 971 prefix);
pcercuei 0:03b5121a232e 972 ctxt->error = 1;
pcercuei 0:03b5121a232e 973 goto error;
pcercuei 0:03b5121a232e 974 }
pcercuei 0:03b5121a232e 975 }
pcercuei 0:03b5121a232e 976 XML_PAT_FREE_STRING(ctxt, prefix);
pcercuei 0:03b5121a232e 977 if (token == NULL) {
pcercuei 0:03b5121a232e 978 if (CUR == '*') {
pcercuei 0:03b5121a232e 979 NEXT;
pcercuei 0:03b5121a232e 980 PUSH(XML_OP_ATTR, NULL, URL);
pcercuei 0:03b5121a232e 981 } else {
pcercuei 0:03b5121a232e 982 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 983 "xmlCompileAttributeTest : Name expected\n");
pcercuei 0:03b5121a232e 984 ctxt->error = 1;
pcercuei 0:03b5121a232e 985 goto error;
pcercuei 0:03b5121a232e 986 }
pcercuei 0:03b5121a232e 987 } else {
pcercuei 0:03b5121a232e 988 PUSH(XML_OP_ATTR, token, URL);
pcercuei 0:03b5121a232e 989 }
pcercuei 0:03b5121a232e 990 } else {
pcercuei 0:03b5121a232e 991 PUSH(XML_OP_ATTR, name, NULL);
pcercuei 0:03b5121a232e 992 }
pcercuei 0:03b5121a232e 993 return;
pcercuei 0:03b5121a232e 994 error:
pcercuei 0:03b5121a232e 995 if (URL != NULL)
pcercuei 0:03b5121a232e 996 XML_PAT_FREE_STRING(ctxt, URL)
pcercuei 0:03b5121a232e 997 if (token != NULL)
pcercuei 0:03b5121a232e 998 XML_PAT_FREE_STRING(ctxt, token);
pcercuei 0:03b5121a232e 999 }
pcercuei 0:03b5121a232e 1000
pcercuei 0:03b5121a232e 1001 /**
pcercuei 0:03b5121a232e 1002 * xmlCompileStepPattern:
pcercuei 0:03b5121a232e 1003 * @ctxt: the compilation context
pcercuei 0:03b5121a232e 1004 *
pcercuei 0:03b5121a232e 1005 * Compile the Step Pattern and generates a precompiled
pcercuei 0:03b5121a232e 1006 * form suitable for fast matching.
pcercuei 0:03b5121a232e 1007 *
pcercuei 0:03b5121a232e 1008 * [3] Step ::= '.' | NameTest
pcercuei 0:03b5121a232e 1009 * [4] NameTest ::= QName | '*' | NCName ':' '*'
pcercuei 0:03b5121a232e 1010 */
pcercuei 0:03b5121a232e 1011
pcercuei 0:03b5121a232e 1012 static void
pcercuei 0:03b5121a232e 1013 xmlCompileStepPattern(xmlPatParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 1014 xmlChar *token = NULL;
pcercuei 0:03b5121a232e 1015 xmlChar *name = NULL;
pcercuei 0:03b5121a232e 1016 xmlChar *URL = NULL;
pcercuei 0:03b5121a232e 1017 int hasBlanks = 0;
pcercuei 0:03b5121a232e 1018
pcercuei 0:03b5121a232e 1019 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1020 if (CUR == '.') {
pcercuei 0:03b5121a232e 1021 /*
pcercuei 0:03b5121a232e 1022 * Context node.
pcercuei 0:03b5121a232e 1023 */
pcercuei 0:03b5121a232e 1024 NEXT;
pcercuei 0:03b5121a232e 1025 PUSH(XML_OP_ELEM, NULL, NULL);
pcercuei 0:03b5121a232e 1026 return;
pcercuei 0:03b5121a232e 1027 }
pcercuei 0:03b5121a232e 1028 if (CUR == '@') {
pcercuei 0:03b5121a232e 1029 /*
pcercuei 0:03b5121a232e 1030 * Attribute test.
pcercuei 0:03b5121a232e 1031 */
pcercuei 0:03b5121a232e 1032 if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
pcercuei 0:03b5121a232e 1033 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1034 "Unexpected attribute axis in '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1035 ctxt->error = 1;
pcercuei 0:03b5121a232e 1036 return;
pcercuei 0:03b5121a232e 1037 }
pcercuei 0:03b5121a232e 1038 NEXT;
pcercuei 0:03b5121a232e 1039 xmlCompileAttributeTest(ctxt);
pcercuei 0:03b5121a232e 1040 if (ctxt->error != 0)
pcercuei 0:03b5121a232e 1041 goto error;
pcercuei 0:03b5121a232e 1042 return;
pcercuei 0:03b5121a232e 1043 }
pcercuei 0:03b5121a232e 1044 name = xmlPatScanNCName(ctxt);
pcercuei 0:03b5121a232e 1045 if (name == NULL) {
pcercuei 0:03b5121a232e 1046 if (CUR == '*') {
pcercuei 0:03b5121a232e 1047 NEXT;
pcercuei 0:03b5121a232e 1048 PUSH(XML_OP_ALL, NULL, NULL);
pcercuei 0:03b5121a232e 1049 return;
pcercuei 0:03b5121a232e 1050 } else {
pcercuei 0:03b5121a232e 1051 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1052 "xmlCompileStepPattern : Name expected\n");
pcercuei 0:03b5121a232e 1053 ctxt->error = 1;
pcercuei 0:03b5121a232e 1054 return;
pcercuei 0:03b5121a232e 1055 }
pcercuei 0:03b5121a232e 1056 }
pcercuei 0:03b5121a232e 1057 if (IS_BLANK_CH(CUR)) {
pcercuei 0:03b5121a232e 1058 hasBlanks = 1;
pcercuei 0:03b5121a232e 1059 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1060 }
pcercuei 0:03b5121a232e 1061 if (CUR == ':') {
pcercuei 0:03b5121a232e 1062 NEXT;
pcercuei 0:03b5121a232e 1063 if (CUR != ':') {
pcercuei 0:03b5121a232e 1064 xmlChar *prefix = name;
pcercuei 0:03b5121a232e 1065 int i;
pcercuei 0:03b5121a232e 1066
pcercuei 0:03b5121a232e 1067 if (hasBlanks || IS_BLANK_CH(CUR)) {
pcercuei 0:03b5121a232e 1068 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
pcercuei 0:03b5121a232e 1069 ctxt->error = 1;
pcercuei 0:03b5121a232e 1070 goto error;
pcercuei 0:03b5121a232e 1071 }
pcercuei 0:03b5121a232e 1072 /*
pcercuei 0:03b5121a232e 1073 * This is a namespace match
pcercuei 0:03b5121a232e 1074 */
pcercuei 0:03b5121a232e 1075 token = xmlPatScanName(ctxt);
pcercuei 0:03b5121a232e 1076 if ((prefix[0] == 'x') &&
pcercuei 0:03b5121a232e 1077 (prefix[1] == 'm') &&
pcercuei 0:03b5121a232e 1078 (prefix[2] == 'l') &&
pcercuei 0:03b5121a232e 1079 (prefix[3] == 0))
pcercuei 0:03b5121a232e 1080 {
pcercuei 0:03b5121a232e 1081 XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
pcercuei 0:03b5121a232e 1082 } else {
pcercuei 0:03b5121a232e 1083 for (i = 0;i < ctxt->nb_namespaces;i++) {
pcercuei 0:03b5121a232e 1084 if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
pcercuei 0:03b5121a232e 1085 XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
pcercuei 0:03b5121a232e 1086 break;
pcercuei 0:03b5121a232e 1087 }
pcercuei 0:03b5121a232e 1088 }
pcercuei 0:03b5121a232e 1089 if (i >= ctxt->nb_namespaces) {
pcercuei 0:03b5121a232e 1090 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1091 "xmlCompileStepPattern : no namespace bound to prefix %s\n",
pcercuei 0:03b5121a232e 1092 prefix);
pcercuei 0:03b5121a232e 1093 ctxt->error = 1;
pcercuei 0:03b5121a232e 1094 goto error;
pcercuei 0:03b5121a232e 1095 }
pcercuei 0:03b5121a232e 1096 }
pcercuei 0:03b5121a232e 1097 XML_PAT_FREE_STRING(ctxt, prefix);
pcercuei 0:03b5121a232e 1098 name = NULL;
pcercuei 0:03b5121a232e 1099 if (token == NULL) {
pcercuei 0:03b5121a232e 1100 if (CUR == '*') {
pcercuei 0:03b5121a232e 1101 NEXT;
pcercuei 0:03b5121a232e 1102 PUSH(XML_OP_NS, URL, NULL);
pcercuei 0:03b5121a232e 1103 } else {
pcercuei 0:03b5121a232e 1104 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1105 "xmlCompileStepPattern : Name expected\n");
pcercuei 0:03b5121a232e 1106 ctxt->error = 1;
pcercuei 0:03b5121a232e 1107 goto error;
pcercuei 0:03b5121a232e 1108 }
pcercuei 0:03b5121a232e 1109 } else {
pcercuei 0:03b5121a232e 1110 PUSH(XML_OP_ELEM, token, URL);
pcercuei 0:03b5121a232e 1111 }
pcercuei 0:03b5121a232e 1112 } else {
pcercuei 0:03b5121a232e 1113 NEXT;
pcercuei 0:03b5121a232e 1114 if (xmlStrEqual(name, (const xmlChar *) "child")) {
pcercuei 0:03b5121a232e 1115 XML_PAT_FREE_STRING(ctxt, name);
pcercuei 0:03b5121a232e 1116 name = xmlPatScanName(ctxt);
pcercuei 0:03b5121a232e 1117 if (name == NULL) {
pcercuei 0:03b5121a232e 1118 if (CUR == '*') {
pcercuei 0:03b5121a232e 1119 NEXT;
pcercuei 0:03b5121a232e 1120 PUSH(XML_OP_ALL, NULL, NULL);
pcercuei 0:03b5121a232e 1121 return;
pcercuei 0:03b5121a232e 1122 } else {
pcercuei 0:03b5121a232e 1123 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1124 "xmlCompileStepPattern : QName expected\n");
pcercuei 0:03b5121a232e 1125 ctxt->error = 1;
pcercuei 0:03b5121a232e 1126 goto error;
pcercuei 0:03b5121a232e 1127 }
pcercuei 0:03b5121a232e 1128 }
pcercuei 0:03b5121a232e 1129 if (CUR == ':') {
pcercuei 0:03b5121a232e 1130 xmlChar *prefix = name;
pcercuei 0:03b5121a232e 1131 int i;
pcercuei 0:03b5121a232e 1132
pcercuei 0:03b5121a232e 1133 NEXT;
pcercuei 0:03b5121a232e 1134 if (IS_BLANK_CH(CUR)) {
pcercuei 0:03b5121a232e 1135 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL);
pcercuei 0:03b5121a232e 1136 ctxt->error = 1;
pcercuei 0:03b5121a232e 1137 goto error;
pcercuei 0:03b5121a232e 1138 }
pcercuei 0:03b5121a232e 1139 /*
pcercuei 0:03b5121a232e 1140 * This is a namespace match
pcercuei 0:03b5121a232e 1141 */
pcercuei 0:03b5121a232e 1142 token = xmlPatScanName(ctxt);
pcercuei 0:03b5121a232e 1143 if ((prefix[0] == 'x') &&
pcercuei 0:03b5121a232e 1144 (prefix[1] == 'm') &&
pcercuei 0:03b5121a232e 1145 (prefix[2] == 'l') &&
pcercuei 0:03b5121a232e 1146 (prefix[3] == 0))
pcercuei 0:03b5121a232e 1147 {
pcercuei 0:03b5121a232e 1148 XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)
pcercuei 0:03b5121a232e 1149 } else {
pcercuei 0:03b5121a232e 1150 for (i = 0;i < ctxt->nb_namespaces;i++) {
pcercuei 0:03b5121a232e 1151 if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) {
pcercuei 0:03b5121a232e 1152 XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])
pcercuei 0:03b5121a232e 1153 break;
pcercuei 0:03b5121a232e 1154 }
pcercuei 0:03b5121a232e 1155 }
pcercuei 0:03b5121a232e 1156 if (i >= ctxt->nb_namespaces) {
pcercuei 0:03b5121a232e 1157 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1158 "xmlCompileStepPattern : no namespace bound "
pcercuei 0:03b5121a232e 1159 "to prefix %s\n", prefix);
pcercuei 0:03b5121a232e 1160 ctxt->error = 1;
pcercuei 0:03b5121a232e 1161 goto error;
pcercuei 0:03b5121a232e 1162 }
pcercuei 0:03b5121a232e 1163 }
pcercuei 0:03b5121a232e 1164 XML_PAT_FREE_STRING(ctxt, prefix);
pcercuei 0:03b5121a232e 1165 name = NULL;
pcercuei 0:03b5121a232e 1166 if (token == NULL) {
pcercuei 0:03b5121a232e 1167 if (CUR == '*') {
pcercuei 0:03b5121a232e 1168 NEXT;
pcercuei 0:03b5121a232e 1169 PUSH(XML_OP_NS, URL, NULL);
pcercuei 0:03b5121a232e 1170 } else {
pcercuei 0:03b5121a232e 1171 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1172 "xmlCompileStepPattern : Name expected\n");
pcercuei 0:03b5121a232e 1173 ctxt->error = 1;
pcercuei 0:03b5121a232e 1174 goto error;
pcercuei 0:03b5121a232e 1175 }
pcercuei 0:03b5121a232e 1176 } else {
pcercuei 0:03b5121a232e 1177 PUSH(XML_OP_CHILD, token, URL);
pcercuei 0:03b5121a232e 1178 }
pcercuei 0:03b5121a232e 1179 } else
pcercuei 0:03b5121a232e 1180 PUSH(XML_OP_CHILD, name, NULL);
pcercuei 0:03b5121a232e 1181 return;
pcercuei 0:03b5121a232e 1182 } else if (xmlStrEqual(name, (const xmlChar *) "attribute")) {
pcercuei 0:03b5121a232e 1183 XML_PAT_FREE_STRING(ctxt, name)
pcercuei 0:03b5121a232e 1184 name = NULL;
pcercuei 0:03b5121a232e 1185 if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) {
pcercuei 0:03b5121a232e 1186 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1187 "Unexpected attribute axis in '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1188 ctxt->error = 1;
pcercuei 0:03b5121a232e 1189 goto error;
pcercuei 0:03b5121a232e 1190 }
pcercuei 0:03b5121a232e 1191 xmlCompileAttributeTest(ctxt);
pcercuei 0:03b5121a232e 1192 if (ctxt->error != 0)
pcercuei 0:03b5121a232e 1193 goto error;
pcercuei 0:03b5121a232e 1194 return;
pcercuei 0:03b5121a232e 1195 } else {
pcercuei 0:03b5121a232e 1196 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1197 "The 'element' or 'attribute' axis is expected.\n", NULL);
pcercuei 0:03b5121a232e 1198 ctxt->error = 1;
pcercuei 0:03b5121a232e 1199 goto error;
pcercuei 0:03b5121a232e 1200 }
pcercuei 0:03b5121a232e 1201 }
pcercuei 0:03b5121a232e 1202 } else if (CUR == '*') {
pcercuei 0:03b5121a232e 1203 if (name != NULL) {
pcercuei 0:03b5121a232e 1204 ctxt->error = 1;
pcercuei 0:03b5121a232e 1205 goto error;
pcercuei 0:03b5121a232e 1206 }
pcercuei 0:03b5121a232e 1207 NEXT;
pcercuei 0:03b5121a232e 1208 PUSH(XML_OP_ALL, token, NULL);
pcercuei 0:03b5121a232e 1209 } else {
pcercuei 0:03b5121a232e 1210 PUSH(XML_OP_ELEM, name, NULL);
pcercuei 0:03b5121a232e 1211 }
pcercuei 0:03b5121a232e 1212 return;
pcercuei 0:03b5121a232e 1213 error:
pcercuei 0:03b5121a232e 1214 if (URL != NULL)
pcercuei 0:03b5121a232e 1215 XML_PAT_FREE_STRING(ctxt, URL)
pcercuei 0:03b5121a232e 1216 if (token != NULL)
pcercuei 0:03b5121a232e 1217 XML_PAT_FREE_STRING(ctxt, token)
pcercuei 0:03b5121a232e 1218 if (name != NULL)
pcercuei 0:03b5121a232e 1219 XML_PAT_FREE_STRING(ctxt, name)
pcercuei 0:03b5121a232e 1220 }
pcercuei 0:03b5121a232e 1221
pcercuei 0:03b5121a232e 1222 /**
pcercuei 0:03b5121a232e 1223 * xmlCompilePathPattern:
pcercuei 0:03b5121a232e 1224 * @ctxt: the compilation context
pcercuei 0:03b5121a232e 1225 *
pcercuei 0:03b5121a232e 1226 * Compile the Path Pattern and generates a precompiled
pcercuei 0:03b5121a232e 1227 * form suitable for fast matching.
pcercuei 0:03b5121a232e 1228 *
pcercuei 0:03b5121a232e 1229 * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
pcercuei 0:03b5121a232e 1230 */
pcercuei 0:03b5121a232e 1231 static void
pcercuei 0:03b5121a232e 1232 xmlCompilePathPattern(xmlPatParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 1233 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1234 if (CUR == '/') {
pcercuei 0:03b5121a232e 1235 ctxt->comp->flags |= PAT_FROM_ROOT;
pcercuei 0:03b5121a232e 1236 } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) {
pcercuei 0:03b5121a232e 1237 ctxt->comp->flags |= PAT_FROM_CUR;
pcercuei 0:03b5121a232e 1238 }
pcercuei 0:03b5121a232e 1239
pcercuei 0:03b5121a232e 1240 if ((CUR == '/') && (NXT(1) == '/')) {
pcercuei 0:03b5121a232e 1241 PUSH(XML_OP_ANCESTOR, NULL, NULL);
pcercuei 0:03b5121a232e 1242 NEXT;
pcercuei 0:03b5121a232e 1243 NEXT;
pcercuei 0:03b5121a232e 1244 } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) {
pcercuei 0:03b5121a232e 1245 PUSH(XML_OP_ANCESTOR, NULL, NULL);
pcercuei 0:03b5121a232e 1246 NEXT;
pcercuei 0:03b5121a232e 1247 NEXT;
pcercuei 0:03b5121a232e 1248 NEXT;
pcercuei 0:03b5121a232e 1249 /* Check for incompleteness. */
pcercuei 0:03b5121a232e 1250 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1251 if (CUR == 0) {
pcercuei 0:03b5121a232e 1252 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1253 "Incomplete expression '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1254 ctxt->error = 1;
pcercuei 0:03b5121a232e 1255 goto error;
pcercuei 0:03b5121a232e 1256 }
pcercuei 0:03b5121a232e 1257 }
pcercuei 0:03b5121a232e 1258 if (CUR == '@') {
pcercuei 0:03b5121a232e 1259 NEXT;
pcercuei 0:03b5121a232e 1260 xmlCompileAttributeTest(ctxt);
pcercuei 0:03b5121a232e 1261 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1262 /* TODO: check for incompleteness */
pcercuei 0:03b5121a232e 1263 if (CUR != 0) {
pcercuei 0:03b5121a232e 1264 xmlCompileStepPattern(ctxt);
pcercuei 0:03b5121a232e 1265 if (ctxt->error != 0)
pcercuei 0:03b5121a232e 1266 goto error;
pcercuei 0:03b5121a232e 1267 }
pcercuei 0:03b5121a232e 1268 } else {
pcercuei 0:03b5121a232e 1269 if (CUR == '/') {
pcercuei 0:03b5121a232e 1270 PUSH(XML_OP_ROOT, NULL, NULL);
pcercuei 0:03b5121a232e 1271 NEXT;
pcercuei 0:03b5121a232e 1272 /* Check for incompleteness. */
pcercuei 0:03b5121a232e 1273 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1274 if (CUR == 0) {
pcercuei 0:03b5121a232e 1275 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1276 "Incomplete expression '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1277 ctxt->error = 1;
pcercuei 0:03b5121a232e 1278 goto error;
pcercuei 0:03b5121a232e 1279 }
pcercuei 0:03b5121a232e 1280 }
pcercuei 0:03b5121a232e 1281 xmlCompileStepPattern(ctxt);
pcercuei 0:03b5121a232e 1282 if (ctxt->error != 0)
pcercuei 0:03b5121a232e 1283 goto error;
pcercuei 0:03b5121a232e 1284 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1285 while (CUR == '/') {
pcercuei 0:03b5121a232e 1286 if (NXT(1) == '/') {
pcercuei 0:03b5121a232e 1287 PUSH(XML_OP_ANCESTOR, NULL, NULL);
pcercuei 0:03b5121a232e 1288 NEXT;
pcercuei 0:03b5121a232e 1289 NEXT;
pcercuei 0:03b5121a232e 1290 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1291 xmlCompileStepPattern(ctxt);
pcercuei 0:03b5121a232e 1292 if (ctxt->error != 0)
pcercuei 0:03b5121a232e 1293 goto error;
pcercuei 0:03b5121a232e 1294 } else {
pcercuei 0:03b5121a232e 1295 PUSH(XML_OP_PARENT, NULL, NULL);
pcercuei 0:03b5121a232e 1296 NEXT;
pcercuei 0:03b5121a232e 1297 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1298 if (CUR == 0) {
pcercuei 0:03b5121a232e 1299 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1300 "Incomplete expression '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1301 ctxt->error = 1;
pcercuei 0:03b5121a232e 1302 goto error;
pcercuei 0:03b5121a232e 1303 }
pcercuei 0:03b5121a232e 1304 xmlCompileStepPattern(ctxt);
pcercuei 0:03b5121a232e 1305 if (ctxt->error != 0)
pcercuei 0:03b5121a232e 1306 goto error;
pcercuei 0:03b5121a232e 1307 }
pcercuei 0:03b5121a232e 1308 }
pcercuei 0:03b5121a232e 1309 }
pcercuei 0:03b5121a232e 1310 if (CUR != 0) {
pcercuei 0:03b5121a232e 1311 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1312 "Failed to compile pattern %s\n", ctxt->base);
pcercuei 0:03b5121a232e 1313 ctxt->error = 1;
pcercuei 0:03b5121a232e 1314 }
pcercuei 0:03b5121a232e 1315 error:
pcercuei 0:03b5121a232e 1316 return;
pcercuei 0:03b5121a232e 1317 }
pcercuei 0:03b5121a232e 1318
pcercuei 0:03b5121a232e 1319 /**
pcercuei 0:03b5121a232e 1320 * xmlCompileIDCXPathPath:
pcercuei 0:03b5121a232e 1321 * @ctxt: the compilation context
pcercuei 0:03b5121a232e 1322 *
pcercuei 0:03b5121a232e 1323 * Compile the Path Pattern and generates a precompiled
pcercuei 0:03b5121a232e 1324 * form suitable for fast matching.
pcercuei 0:03b5121a232e 1325 *
pcercuei 0:03b5121a232e 1326 * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest )
pcercuei 0:03b5121a232e 1327 */
pcercuei 0:03b5121a232e 1328 static void
pcercuei 0:03b5121a232e 1329 xmlCompileIDCXPathPath(xmlPatParserContextPtr ctxt) {
pcercuei 0:03b5121a232e 1330 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1331 if (CUR == '/') {
pcercuei 0:03b5121a232e 1332 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1333 "Unexpected selection of the document root in '%s'.\n",
pcercuei 0:03b5121a232e 1334 ctxt->base);
pcercuei 0:03b5121a232e 1335 goto error;
pcercuei 0:03b5121a232e 1336 }
pcercuei 0:03b5121a232e 1337 ctxt->comp->flags |= PAT_FROM_CUR;
pcercuei 0:03b5121a232e 1338
pcercuei 0:03b5121a232e 1339 if (CUR == '.') {
pcercuei 0:03b5121a232e 1340 /* "." - "self::node()" */
pcercuei 0:03b5121a232e 1341 NEXT;
pcercuei 0:03b5121a232e 1342 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1343 if (CUR == 0) {
pcercuei 0:03b5121a232e 1344 /*
pcercuei 0:03b5121a232e 1345 * Selection of the context node.
pcercuei 0:03b5121a232e 1346 */
pcercuei 0:03b5121a232e 1347 PUSH(XML_OP_ELEM, NULL, NULL);
pcercuei 0:03b5121a232e 1348 return;
pcercuei 0:03b5121a232e 1349 }
pcercuei 0:03b5121a232e 1350 if (CUR != '/') {
pcercuei 0:03b5121a232e 1351 /* TODO: A more meaningful error message. */
pcercuei 0:03b5121a232e 1352 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1353 "Unexpected token after '.' in '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1354 goto error;
pcercuei 0:03b5121a232e 1355 }
pcercuei 0:03b5121a232e 1356 /* "./" - "self::node()/" */
pcercuei 0:03b5121a232e 1357 NEXT;
pcercuei 0:03b5121a232e 1358 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1359 if (CUR == '/') {
pcercuei 0:03b5121a232e 1360 if (IS_BLANK_CH(PEEKPREV(1))) {
pcercuei 0:03b5121a232e 1361 /*
pcercuei 0:03b5121a232e 1362 * Disallow "./ /"
pcercuei 0:03b5121a232e 1363 */
pcercuei 0:03b5121a232e 1364 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1365 "Unexpected '/' token in '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1366 goto error;
pcercuei 0:03b5121a232e 1367 }
pcercuei 0:03b5121a232e 1368 /* ".//" - "self:node()/descendant-or-self::node()/" */
pcercuei 0:03b5121a232e 1369 PUSH(XML_OP_ANCESTOR, NULL, NULL);
pcercuei 0:03b5121a232e 1370 NEXT;
pcercuei 0:03b5121a232e 1371 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1372 }
pcercuei 0:03b5121a232e 1373 if (CUR == 0)
pcercuei 0:03b5121a232e 1374 goto error_unfinished;
pcercuei 0:03b5121a232e 1375 }
pcercuei 0:03b5121a232e 1376 /*
pcercuei 0:03b5121a232e 1377 * Process steps.
pcercuei 0:03b5121a232e 1378 */
pcercuei 0:03b5121a232e 1379 do {
pcercuei 0:03b5121a232e 1380 xmlCompileStepPattern(ctxt);
pcercuei 0:03b5121a232e 1381 if (ctxt->error != 0)
pcercuei 0:03b5121a232e 1382 goto error;
pcercuei 0:03b5121a232e 1383 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1384 if (CUR != '/')
pcercuei 0:03b5121a232e 1385 break;
pcercuei 0:03b5121a232e 1386 PUSH(XML_OP_PARENT, NULL, NULL);
pcercuei 0:03b5121a232e 1387 NEXT;
pcercuei 0:03b5121a232e 1388 SKIP_BLANKS;
pcercuei 0:03b5121a232e 1389 if (CUR == '/') {
pcercuei 0:03b5121a232e 1390 /*
pcercuei 0:03b5121a232e 1391 * Disallow subsequent '//'.
pcercuei 0:03b5121a232e 1392 */
pcercuei 0:03b5121a232e 1393 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1394 "Unexpected subsequent '//' in '%s'.\n",
pcercuei 0:03b5121a232e 1395 ctxt->base);
pcercuei 0:03b5121a232e 1396 goto error;
pcercuei 0:03b5121a232e 1397 }
pcercuei 0:03b5121a232e 1398 if (CUR == 0)
pcercuei 0:03b5121a232e 1399 goto error_unfinished;
pcercuei 0:03b5121a232e 1400
pcercuei 0:03b5121a232e 1401 } while (CUR != 0);
pcercuei 0:03b5121a232e 1402
pcercuei 0:03b5121a232e 1403 if (CUR != 0) {
pcercuei 0:03b5121a232e 1404 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1405 "Failed to compile expression '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1406 ctxt->error = 1;
pcercuei 0:03b5121a232e 1407 }
pcercuei 0:03b5121a232e 1408 return;
pcercuei 0:03b5121a232e 1409 error:
pcercuei 0:03b5121a232e 1410 ctxt->error = 1;
pcercuei 0:03b5121a232e 1411 return;
pcercuei 0:03b5121a232e 1412
pcercuei 0:03b5121a232e 1413 error_unfinished:
pcercuei 0:03b5121a232e 1414 ctxt->error = 1;
pcercuei 0:03b5121a232e 1415 ERROR5(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1416 "Unfinished expression '%s'.\n", ctxt->base);
pcercuei 0:03b5121a232e 1417 return;
pcercuei 0:03b5121a232e 1418 }
pcercuei 0:03b5121a232e 1419
pcercuei 0:03b5121a232e 1420 /************************************************************************
pcercuei 0:03b5121a232e 1421 * *
pcercuei 0:03b5121a232e 1422 * The streaming code *
pcercuei 0:03b5121a232e 1423 * *
pcercuei 0:03b5121a232e 1424 ************************************************************************/
pcercuei 0:03b5121a232e 1425
pcercuei 0:03b5121a232e 1426 #ifdef DEBUG_STREAMING
pcercuei 0:03b5121a232e 1427 static void
pcercuei 0:03b5121a232e 1428 xmlDebugStreamComp(xmlStreamCompPtr stream) {
pcercuei 0:03b5121a232e 1429 int i;
pcercuei 0:03b5121a232e 1430
pcercuei 0:03b5121a232e 1431 if (stream == NULL) {
pcercuei 0:03b5121a232e 1432 printf("Stream: NULL\n");
pcercuei 0:03b5121a232e 1433 return;
pcercuei 0:03b5121a232e 1434 }
pcercuei 0:03b5121a232e 1435 printf("Stream: %d steps\n", stream->nbStep);
pcercuei 0:03b5121a232e 1436 for (i = 0;i < stream->nbStep;i++) {
pcercuei 0:03b5121a232e 1437 if (stream->steps[i].ns != NULL) {
pcercuei 0:03b5121a232e 1438 printf("{%s}", stream->steps[i].ns);
pcercuei 0:03b5121a232e 1439 }
pcercuei 0:03b5121a232e 1440 if (stream->steps[i].name == NULL) {
pcercuei 0:03b5121a232e 1441 printf("* ");
pcercuei 0:03b5121a232e 1442 } else {
pcercuei 0:03b5121a232e 1443 printf("%s ", stream->steps[i].name);
pcercuei 0:03b5121a232e 1444 }
pcercuei 0:03b5121a232e 1445 if (stream->steps[i].flags & XML_STREAM_STEP_ROOT)
pcercuei 0:03b5121a232e 1446 printf("root ");
pcercuei 0:03b5121a232e 1447 if (stream->steps[i].flags & XML_STREAM_STEP_DESC)
pcercuei 0:03b5121a232e 1448 printf("// ");
pcercuei 0:03b5121a232e 1449 if (stream->steps[i].flags & XML_STREAM_STEP_FINAL)
pcercuei 0:03b5121a232e 1450 printf("final ");
pcercuei 0:03b5121a232e 1451 printf("\n");
pcercuei 0:03b5121a232e 1452 }
pcercuei 0:03b5121a232e 1453 }
pcercuei 0:03b5121a232e 1454 static void
pcercuei 0:03b5121a232e 1455 xmlDebugStreamCtxt(xmlStreamCtxtPtr ctxt, int match) {
pcercuei 0:03b5121a232e 1456 int i;
pcercuei 0:03b5121a232e 1457
pcercuei 0:03b5121a232e 1458 if (ctxt == NULL) {
pcercuei 0:03b5121a232e 1459 printf("Stream: NULL\n");
pcercuei 0:03b5121a232e 1460 return;
pcercuei 0:03b5121a232e 1461 }
pcercuei 0:03b5121a232e 1462 printf("Stream: level %d, %d states: ", ctxt->level, ctxt->nbState);
pcercuei 0:03b5121a232e 1463 if (match)
pcercuei 0:03b5121a232e 1464 printf("matches\n");
pcercuei 0:03b5121a232e 1465 else
pcercuei 0:03b5121a232e 1466 printf("\n");
pcercuei 0:03b5121a232e 1467 for (i = 0;i < ctxt->nbState;i++) {
pcercuei 0:03b5121a232e 1468 if (ctxt->states[2 * i] < 0)
pcercuei 0:03b5121a232e 1469 printf(" %d: free\n", i);
pcercuei 0:03b5121a232e 1470 else {
pcercuei 0:03b5121a232e 1471 printf(" %d: step %d, level %d", i, ctxt->states[2 * i],
pcercuei 0:03b5121a232e 1472 ctxt->states[(2 * i) + 1]);
pcercuei 0:03b5121a232e 1473 if (ctxt->comp->steps[ctxt->states[2 * i]].flags &
pcercuei 0:03b5121a232e 1474 XML_STREAM_STEP_DESC)
pcercuei 0:03b5121a232e 1475 printf(" //\n");
pcercuei 0:03b5121a232e 1476 else
pcercuei 0:03b5121a232e 1477 printf("\n");
pcercuei 0:03b5121a232e 1478 }
pcercuei 0:03b5121a232e 1479 }
pcercuei 0:03b5121a232e 1480 }
pcercuei 0:03b5121a232e 1481 #endif
pcercuei 0:03b5121a232e 1482 /**
pcercuei 0:03b5121a232e 1483 * xmlNewStreamComp:
pcercuei 0:03b5121a232e 1484 * @size: the number of expected steps
pcercuei 0:03b5121a232e 1485 *
pcercuei 0:03b5121a232e 1486 * build a new compiled pattern for streaming
pcercuei 0:03b5121a232e 1487 *
pcercuei 0:03b5121a232e 1488 * Returns the new structure or NULL in case of error.
pcercuei 0:03b5121a232e 1489 */
pcercuei 0:03b5121a232e 1490 static xmlStreamCompPtr
pcercuei 0:03b5121a232e 1491 xmlNewStreamComp(int size) {
pcercuei 0:03b5121a232e 1492 xmlStreamCompPtr cur;
pcercuei 0:03b5121a232e 1493
pcercuei 0:03b5121a232e 1494 if (size < 4)
pcercuei 0:03b5121a232e 1495 size = 4;
pcercuei 0:03b5121a232e 1496
pcercuei 0:03b5121a232e 1497 cur = (xmlStreamCompPtr) xmlMalloc(sizeof(xmlStreamComp));
pcercuei 0:03b5121a232e 1498 if (cur == NULL) {
pcercuei 0:03b5121a232e 1499 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1500 "xmlNewStreamComp: malloc failed\n");
pcercuei 0:03b5121a232e 1501 return(NULL);
pcercuei 0:03b5121a232e 1502 }
pcercuei 0:03b5121a232e 1503 memset(cur, 0, sizeof(xmlStreamComp));
pcercuei 0:03b5121a232e 1504 cur->steps = (xmlStreamStepPtr) xmlMalloc(size * sizeof(xmlStreamStep));
pcercuei 0:03b5121a232e 1505 if (cur->steps == NULL) {
pcercuei 0:03b5121a232e 1506 xmlFree(cur);
pcercuei 0:03b5121a232e 1507 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1508 "xmlNewStreamComp: malloc failed\n");
pcercuei 0:03b5121a232e 1509 return(NULL);
pcercuei 0:03b5121a232e 1510 }
pcercuei 0:03b5121a232e 1511 cur->nbStep = 0;
pcercuei 0:03b5121a232e 1512 cur->maxStep = size;
pcercuei 0:03b5121a232e 1513 return(cur);
pcercuei 0:03b5121a232e 1514 }
pcercuei 0:03b5121a232e 1515
pcercuei 0:03b5121a232e 1516 /**
pcercuei 0:03b5121a232e 1517 * xmlFreeStreamComp:
pcercuei 0:03b5121a232e 1518 * @comp: the compiled pattern for streaming
pcercuei 0:03b5121a232e 1519 *
pcercuei 0:03b5121a232e 1520 * Free the compiled pattern for streaming
pcercuei 0:03b5121a232e 1521 */
pcercuei 0:03b5121a232e 1522 static void
pcercuei 0:03b5121a232e 1523 xmlFreeStreamComp(xmlStreamCompPtr comp) {
pcercuei 0:03b5121a232e 1524 if (comp != NULL) {
pcercuei 0:03b5121a232e 1525 if (comp->steps != NULL)
pcercuei 0:03b5121a232e 1526 xmlFree(comp->steps);
pcercuei 0:03b5121a232e 1527 if (comp->dict != NULL)
pcercuei 0:03b5121a232e 1528 xmlDictFree(comp->dict);
pcercuei 0:03b5121a232e 1529 xmlFree(comp);
pcercuei 0:03b5121a232e 1530 }
pcercuei 0:03b5121a232e 1531 }
pcercuei 0:03b5121a232e 1532
pcercuei 0:03b5121a232e 1533 /**
pcercuei 0:03b5121a232e 1534 * xmlStreamCompAddStep:
pcercuei 0:03b5121a232e 1535 * @comp: the compiled pattern for streaming
pcercuei 0:03b5121a232e 1536 * @name: the first string, the name, or NULL for *
pcercuei 0:03b5121a232e 1537 * @ns: the second step, the namespace name
pcercuei 0:03b5121a232e 1538 * @flags: the flags for that step
pcercuei 0:03b5121a232e 1539 *
pcercuei 0:03b5121a232e 1540 * Add a new step to the compiled pattern
pcercuei 0:03b5121a232e 1541 *
pcercuei 0:03b5121a232e 1542 * Returns -1 in case of error or the step index if successful
pcercuei 0:03b5121a232e 1543 */
pcercuei 0:03b5121a232e 1544 static int
pcercuei 0:03b5121a232e 1545 xmlStreamCompAddStep(xmlStreamCompPtr comp, const xmlChar *name,
pcercuei 0:03b5121a232e 1546 const xmlChar *ns, int nodeType, int flags) {
pcercuei 0:03b5121a232e 1547 xmlStreamStepPtr cur;
pcercuei 0:03b5121a232e 1548
pcercuei 0:03b5121a232e 1549 if (comp->nbStep >= comp->maxStep) {
pcercuei 0:03b5121a232e 1550 cur = (xmlStreamStepPtr) xmlRealloc(comp->steps,
pcercuei 0:03b5121a232e 1551 comp->maxStep * 2 * sizeof(xmlStreamStep));
pcercuei 0:03b5121a232e 1552 if (cur == NULL) {
pcercuei 0:03b5121a232e 1553 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1554 "xmlNewStreamComp: malloc failed\n");
pcercuei 0:03b5121a232e 1555 return(-1);
pcercuei 0:03b5121a232e 1556 }
pcercuei 0:03b5121a232e 1557 comp->steps = cur;
pcercuei 0:03b5121a232e 1558 comp->maxStep *= 2;
pcercuei 0:03b5121a232e 1559 }
pcercuei 0:03b5121a232e 1560 cur = &comp->steps[comp->nbStep++];
pcercuei 0:03b5121a232e 1561 cur->flags = flags;
pcercuei 0:03b5121a232e 1562 cur->name = name;
pcercuei 0:03b5121a232e 1563 cur->ns = ns;
pcercuei 0:03b5121a232e 1564 cur->nodeType = nodeType;
pcercuei 0:03b5121a232e 1565 return(comp->nbStep - 1);
pcercuei 0:03b5121a232e 1566 }
pcercuei 0:03b5121a232e 1567
pcercuei 0:03b5121a232e 1568 /**
pcercuei 0:03b5121a232e 1569 * xmlStreamCompile:
pcercuei 0:03b5121a232e 1570 * @comp: the precompiled pattern
pcercuei 0:03b5121a232e 1571 *
pcercuei 0:03b5121a232e 1572 * Tries to stream compile a pattern
pcercuei 0:03b5121a232e 1573 *
pcercuei 0:03b5121a232e 1574 * Returns -1 in case of failure and 0 in case of success.
pcercuei 0:03b5121a232e 1575 */
pcercuei 0:03b5121a232e 1576 static int
pcercuei 0:03b5121a232e 1577 xmlStreamCompile(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 1578 xmlStreamCompPtr stream;
pcercuei 0:03b5121a232e 1579 int i, s = 0, root = 0, flags = 0, prevs = -1;
pcercuei 0:03b5121a232e 1580 xmlStepOp step;
pcercuei 0:03b5121a232e 1581
pcercuei 0:03b5121a232e 1582 if ((comp == NULL) || (comp->steps == NULL))
pcercuei 0:03b5121a232e 1583 return(-1);
pcercuei 0:03b5121a232e 1584 /*
pcercuei 0:03b5121a232e 1585 * special case for .
pcercuei 0:03b5121a232e 1586 */
pcercuei 0:03b5121a232e 1587 if ((comp->nbStep == 1) &&
pcercuei 0:03b5121a232e 1588 (comp->steps[0].op == XML_OP_ELEM) &&
pcercuei 0:03b5121a232e 1589 (comp->steps[0].value == NULL) &&
pcercuei 0:03b5121a232e 1590 (comp->steps[0].value2 == NULL)) {
pcercuei 0:03b5121a232e 1591 stream = xmlNewStreamComp(0);
pcercuei 0:03b5121a232e 1592 if (stream == NULL)
pcercuei 0:03b5121a232e 1593 return(-1);
pcercuei 0:03b5121a232e 1594 /* Note that the stream will have no steps in this case. */
pcercuei 0:03b5121a232e 1595 stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;
pcercuei 0:03b5121a232e 1596 comp->stream = stream;
pcercuei 0:03b5121a232e 1597 return(0);
pcercuei 0:03b5121a232e 1598 }
pcercuei 0:03b5121a232e 1599
pcercuei 0:03b5121a232e 1600 stream = xmlNewStreamComp((comp->nbStep / 2) + 1);
pcercuei 0:03b5121a232e 1601 if (stream == NULL)
pcercuei 0:03b5121a232e 1602 return(-1);
pcercuei 0:03b5121a232e 1603 if (comp->dict != NULL) {
pcercuei 0:03b5121a232e 1604 stream->dict = comp->dict;
pcercuei 0:03b5121a232e 1605 xmlDictReference(stream->dict);
pcercuei 0:03b5121a232e 1606 }
pcercuei 0:03b5121a232e 1607
pcercuei 0:03b5121a232e 1608 i = 0;
pcercuei 0:03b5121a232e 1609 if (comp->flags & PAT_FROM_ROOT)
pcercuei 0:03b5121a232e 1610 stream->flags |= XML_STREAM_FROM_ROOT;
pcercuei 0:03b5121a232e 1611
pcercuei 0:03b5121a232e 1612 for (;i < comp->nbStep;i++) {
pcercuei 0:03b5121a232e 1613 step = comp->steps[i];
pcercuei 0:03b5121a232e 1614 switch (step.op) {
pcercuei 0:03b5121a232e 1615 case XML_OP_END:
pcercuei 0:03b5121a232e 1616 break;
pcercuei 0:03b5121a232e 1617 case XML_OP_ROOT:
pcercuei 0:03b5121a232e 1618 if (i != 0)
pcercuei 0:03b5121a232e 1619 goto error;
pcercuei 0:03b5121a232e 1620 root = 1;
pcercuei 0:03b5121a232e 1621 break;
pcercuei 0:03b5121a232e 1622 case XML_OP_NS:
pcercuei 0:03b5121a232e 1623 s = xmlStreamCompAddStep(stream, NULL, step.value,
pcercuei 0:03b5121a232e 1624 XML_ELEMENT_NODE, flags);
pcercuei 0:03b5121a232e 1625 if (s < 0)
pcercuei 0:03b5121a232e 1626 goto error;
pcercuei 0:03b5121a232e 1627 prevs = s;
pcercuei 0:03b5121a232e 1628 flags = 0;
pcercuei 0:03b5121a232e 1629 break;
pcercuei 0:03b5121a232e 1630 case XML_OP_ATTR:
pcercuei 0:03b5121a232e 1631 flags |= XML_STREAM_STEP_ATTR;
pcercuei 0:03b5121a232e 1632 prevs = -1;
pcercuei 0:03b5121a232e 1633 s = xmlStreamCompAddStep(stream,
pcercuei 0:03b5121a232e 1634 step.value, step.value2, XML_ATTRIBUTE_NODE, flags);
pcercuei 0:03b5121a232e 1635 flags = 0;
pcercuei 0:03b5121a232e 1636 if (s < 0)
pcercuei 0:03b5121a232e 1637 goto error;
pcercuei 0:03b5121a232e 1638 break;
pcercuei 0:03b5121a232e 1639 case XML_OP_ELEM:
pcercuei 0:03b5121a232e 1640 if ((step.value == NULL) && (step.value2 == NULL)) {
pcercuei 0:03b5121a232e 1641 /*
pcercuei 0:03b5121a232e 1642 * We have a "." or "self::node()" here.
pcercuei 0:03b5121a232e 1643 * Eliminate redundant self::node() tests like in "/./."
pcercuei 0:03b5121a232e 1644 * or "//./"
pcercuei 0:03b5121a232e 1645 * The only case we won't eliminate is "//.", i.e. if
pcercuei 0:03b5121a232e 1646 * self::node() is the last node test and we had
pcercuei 0:03b5121a232e 1647 * continuation somewhere beforehand.
pcercuei 0:03b5121a232e 1648 */
pcercuei 0:03b5121a232e 1649 if ((comp->nbStep == i + 1) &&
pcercuei 0:03b5121a232e 1650 (flags & XML_STREAM_STEP_DESC)) {
pcercuei 0:03b5121a232e 1651 /*
pcercuei 0:03b5121a232e 1652 * Mark the special case where the expression resolves
pcercuei 0:03b5121a232e 1653 * to any type of node.
pcercuei 0:03b5121a232e 1654 */
pcercuei 0:03b5121a232e 1655 if (comp->nbStep == i + 1) {
pcercuei 0:03b5121a232e 1656 stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE;
pcercuei 0:03b5121a232e 1657 }
pcercuei 0:03b5121a232e 1658 flags |= XML_STREAM_STEP_NODE;
pcercuei 0:03b5121a232e 1659 s = xmlStreamCompAddStep(stream, NULL, NULL,
pcercuei 0:03b5121a232e 1660 XML_STREAM_ANY_NODE, flags);
pcercuei 0:03b5121a232e 1661 if (s < 0)
pcercuei 0:03b5121a232e 1662 goto error;
pcercuei 0:03b5121a232e 1663 flags = 0;
pcercuei 0:03b5121a232e 1664 /*
pcercuei 0:03b5121a232e 1665 * If there was a previous step, mark it to be added to
pcercuei 0:03b5121a232e 1666 * the result node-set; this is needed since only
pcercuei 0:03b5121a232e 1667 * the last step will be marked as "final" and only
pcercuei 0:03b5121a232e 1668 * "final" nodes are added to the resulting set.
pcercuei 0:03b5121a232e 1669 */
pcercuei 0:03b5121a232e 1670 if (prevs != -1) {
pcercuei 0:03b5121a232e 1671 stream->steps[prevs].flags |= XML_STREAM_STEP_IN_SET;
pcercuei 0:03b5121a232e 1672 prevs = -1;
pcercuei 0:03b5121a232e 1673 }
pcercuei 0:03b5121a232e 1674 break;
pcercuei 0:03b5121a232e 1675
pcercuei 0:03b5121a232e 1676 } else {
pcercuei 0:03b5121a232e 1677 /* Just skip this one. */
pcercuei 0:03b5121a232e 1678 continue;
pcercuei 0:03b5121a232e 1679 }
pcercuei 0:03b5121a232e 1680 }
pcercuei 0:03b5121a232e 1681 /* An element node. */
pcercuei 0:03b5121a232e 1682 s = xmlStreamCompAddStep(stream, step.value, step.value2,
pcercuei 0:03b5121a232e 1683 XML_ELEMENT_NODE, flags);
pcercuei 0:03b5121a232e 1684 if (s < 0)
pcercuei 0:03b5121a232e 1685 goto error;
pcercuei 0:03b5121a232e 1686 prevs = s;
pcercuei 0:03b5121a232e 1687 flags = 0;
pcercuei 0:03b5121a232e 1688 break;
pcercuei 0:03b5121a232e 1689 case XML_OP_CHILD:
pcercuei 0:03b5121a232e 1690 /* An element node child. */
pcercuei 0:03b5121a232e 1691 s = xmlStreamCompAddStep(stream, step.value, step.value2,
pcercuei 0:03b5121a232e 1692 XML_ELEMENT_NODE, flags);
pcercuei 0:03b5121a232e 1693 if (s < 0)
pcercuei 0:03b5121a232e 1694 goto error;
pcercuei 0:03b5121a232e 1695 prevs = s;
pcercuei 0:03b5121a232e 1696 flags = 0;
pcercuei 0:03b5121a232e 1697 break;
pcercuei 0:03b5121a232e 1698 case XML_OP_ALL:
pcercuei 0:03b5121a232e 1699 s = xmlStreamCompAddStep(stream, NULL, NULL,
pcercuei 0:03b5121a232e 1700 XML_ELEMENT_NODE, flags);
pcercuei 0:03b5121a232e 1701 if (s < 0)
pcercuei 0:03b5121a232e 1702 goto error;
pcercuei 0:03b5121a232e 1703 prevs = s;
pcercuei 0:03b5121a232e 1704 flags = 0;
pcercuei 0:03b5121a232e 1705 break;
pcercuei 0:03b5121a232e 1706 case XML_OP_PARENT:
pcercuei 0:03b5121a232e 1707 break;
pcercuei 0:03b5121a232e 1708 case XML_OP_ANCESTOR:
pcercuei 0:03b5121a232e 1709 /* Skip redundant continuations. */
pcercuei 0:03b5121a232e 1710 if (flags & XML_STREAM_STEP_DESC)
pcercuei 0:03b5121a232e 1711 break;
pcercuei 0:03b5121a232e 1712 flags |= XML_STREAM_STEP_DESC;
pcercuei 0:03b5121a232e 1713 /*
pcercuei 0:03b5121a232e 1714 * Mark the expression as having "//".
pcercuei 0:03b5121a232e 1715 */
pcercuei 0:03b5121a232e 1716 if ((stream->flags & XML_STREAM_DESC) == 0)
pcercuei 0:03b5121a232e 1717 stream->flags |= XML_STREAM_DESC;
pcercuei 0:03b5121a232e 1718 break;
pcercuei 0:03b5121a232e 1719 }
pcercuei 0:03b5121a232e 1720 }
pcercuei 0:03b5121a232e 1721 if ((! root) && (comp->flags & XML_PATTERN_NOTPATTERN) == 0) {
pcercuei 0:03b5121a232e 1722 /*
pcercuei 0:03b5121a232e 1723 * If this should behave like a real pattern, we will mark
pcercuei 0:03b5121a232e 1724 * the first step as having "//", to be reentrant on every
pcercuei 0:03b5121a232e 1725 * tree level.
pcercuei 0:03b5121a232e 1726 */
pcercuei 0:03b5121a232e 1727 if ((stream->flags & XML_STREAM_DESC) == 0)
pcercuei 0:03b5121a232e 1728 stream->flags |= XML_STREAM_DESC;
pcercuei 0:03b5121a232e 1729
pcercuei 0:03b5121a232e 1730 if (stream->nbStep > 0) {
pcercuei 0:03b5121a232e 1731 if ((stream->steps[0].flags & XML_STREAM_STEP_DESC) == 0)
pcercuei 0:03b5121a232e 1732 stream->steps[0].flags |= XML_STREAM_STEP_DESC;
pcercuei 0:03b5121a232e 1733 }
pcercuei 0:03b5121a232e 1734 }
pcercuei 0:03b5121a232e 1735 if (stream->nbStep <= s)
pcercuei 0:03b5121a232e 1736 goto error;
pcercuei 0:03b5121a232e 1737 stream->steps[s].flags |= XML_STREAM_STEP_FINAL;
pcercuei 0:03b5121a232e 1738 if (root)
pcercuei 0:03b5121a232e 1739 stream->steps[0].flags |= XML_STREAM_STEP_ROOT;
pcercuei 0:03b5121a232e 1740 #ifdef DEBUG_STREAMING
pcercuei 0:03b5121a232e 1741 xmlDebugStreamComp(stream);
pcercuei 0:03b5121a232e 1742 #endif
pcercuei 0:03b5121a232e 1743 comp->stream = stream;
pcercuei 0:03b5121a232e 1744 return(0);
pcercuei 0:03b5121a232e 1745 error:
pcercuei 0:03b5121a232e 1746 xmlFreeStreamComp(stream);
pcercuei 0:03b5121a232e 1747 return(0);
pcercuei 0:03b5121a232e 1748 }
pcercuei 0:03b5121a232e 1749
pcercuei 0:03b5121a232e 1750 /**
pcercuei 0:03b5121a232e 1751 * xmlNewStreamCtxt:
pcercuei 0:03b5121a232e 1752 * @size: the number of expected states
pcercuei 0:03b5121a232e 1753 *
pcercuei 0:03b5121a232e 1754 * build a new stream context
pcercuei 0:03b5121a232e 1755 *
pcercuei 0:03b5121a232e 1756 * Returns the new structure or NULL in case of error.
pcercuei 0:03b5121a232e 1757 */
pcercuei 0:03b5121a232e 1758 static xmlStreamCtxtPtr
pcercuei 0:03b5121a232e 1759 xmlNewStreamCtxt(xmlStreamCompPtr stream) {
pcercuei 0:03b5121a232e 1760 xmlStreamCtxtPtr cur;
pcercuei 0:03b5121a232e 1761
pcercuei 0:03b5121a232e 1762 cur = (xmlStreamCtxtPtr) xmlMalloc(sizeof(xmlStreamCtxt));
pcercuei 0:03b5121a232e 1763 if (cur == NULL) {
pcercuei 0:03b5121a232e 1764 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1765 "xmlNewStreamCtxt: malloc failed\n");
pcercuei 0:03b5121a232e 1766 return(NULL);
pcercuei 0:03b5121a232e 1767 }
pcercuei 0:03b5121a232e 1768 memset(cur, 0, sizeof(xmlStreamCtxt));
pcercuei 0:03b5121a232e 1769 cur->states = (int *) xmlMalloc(4 * 2 * sizeof(int));
pcercuei 0:03b5121a232e 1770 if (cur->states == NULL) {
pcercuei 0:03b5121a232e 1771 xmlFree(cur);
pcercuei 0:03b5121a232e 1772 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1773 "xmlNewStreamCtxt: malloc failed\n");
pcercuei 0:03b5121a232e 1774 return(NULL);
pcercuei 0:03b5121a232e 1775 }
pcercuei 0:03b5121a232e 1776 cur->nbState = 0;
pcercuei 0:03b5121a232e 1777 cur->maxState = 4;
pcercuei 0:03b5121a232e 1778 cur->level = 0;
pcercuei 0:03b5121a232e 1779 cur->comp = stream;
pcercuei 0:03b5121a232e 1780 cur->blockLevel = -1;
pcercuei 0:03b5121a232e 1781 return(cur);
pcercuei 0:03b5121a232e 1782 }
pcercuei 0:03b5121a232e 1783
pcercuei 0:03b5121a232e 1784 /**
pcercuei 0:03b5121a232e 1785 * xmlFreeStreamCtxt:
pcercuei 0:03b5121a232e 1786 * @stream: the stream context
pcercuei 0:03b5121a232e 1787 *
pcercuei 0:03b5121a232e 1788 * Free the stream context
pcercuei 0:03b5121a232e 1789 */
pcercuei 0:03b5121a232e 1790 void
pcercuei 0:03b5121a232e 1791 xmlFreeStreamCtxt(xmlStreamCtxtPtr stream) {
pcercuei 0:03b5121a232e 1792 xmlStreamCtxtPtr next;
pcercuei 0:03b5121a232e 1793
pcercuei 0:03b5121a232e 1794 while (stream != NULL) {
pcercuei 0:03b5121a232e 1795 next = stream->next;
pcercuei 0:03b5121a232e 1796 if (stream->states != NULL)
pcercuei 0:03b5121a232e 1797 xmlFree(stream->states);
pcercuei 0:03b5121a232e 1798 xmlFree(stream);
pcercuei 0:03b5121a232e 1799 stream = next;
pcercuei 0:03b5121a232e 1800 }
pcercuei 0:03b5121a232e 1801 }
pcercuei 0:03b5121a232e 1802
pcercuei 0:03b5121a232e 1803 /**
pcercuei 0:03b5121a232e 1804 * xmlStreamCtxtAddState:
pcercuei 0:03b5121a232e 1805 * @comp: the stream context
pcercuei 0:03b5121a232e 1806 * @idx: the step index for that streaming state
pcercuei 0:03b5121a232e 1807 *
pcercuei 0:03b5121a232e 1808 * Add a new state to the stream context
pcercuei 0:03b5121a232e 1809 *
pcercuei 0:03b5121a232e 1810 * Returns -1 in case of error or the state index if successful
pcercuei 0:03b5121a232e 1811 */
pcercuei 0:03b5121a232e 1812 static int
pcercuei 0:03b5121a232e 1813 xmlStreamCtxtAddState(xmlStreamCtxtPtr comp, int idx, int level) {
pcercuei 0:03b5121a232e 1814 int i;
pcercuei 0:03b5121a232e 1815 for (i = 0;i < comp->nbState;i++) {
pcercuei 0:03b5121a232e 1816 if (comp->states[2 * i] < 0) {
pcercuei 0:03b5121a232e 1817 comp->states[2 * i] = idx;
pcercuei 0:03b5121a232e 1818 comp->states[2 * i + 1] = level;
pcercuei 0:03b5121a232e 1819 return(i);
pcercuei 0:03b5121a232e 1820 }
pcercuei 0:03b5121a232e 1821 }
pcercuei 0:03b5121a232e 1822 if (comp->nbState >= comp->maxState) {
pcercuei 0:03b5121a232e 1823 int *cur;
pcercuei 0:03b5121a232e 1824
pcercuei 0:03b5121a232e 1825 cur = (int *) xmlRealloc(comp->states,
pcercuei 0:03b5121a232e 1826 comp->maxState * 4 * sizeof(int));
pcercuei 0:03b5121a232e 1827 if (cur == NULL) {
pcercuei 0:03b5121a232e 1828 ERROR(NULL, NULL, NULL,
pcercuei 0:03b5121a232e 1829 "xmlNewStreamCtxt: malloc failed\n");
pcercuei 0:03b5121a232e 1830 return(-1);
pcercuei 0:03b5121a232e 1831 }
pcercuei 0:03b5121a232e 1832 comp->states = cur;
pcercuei 0:03b5121a232e 1833 comp->maxState *= 2;
pcercuei 0:03b5121a232e 1834 }
pcercuei 0:03b5121a232e 1835 comp->states[2 * comp->nbState] = idx;
pcercuei 0:03b5121a232e 1836 comp->states[2 * comp->nbState++ + 1] = level;
pcercuei 0:03b5121a232e 1837 return(comp->nbState - 1);
pcercuei 0:03b5121a232e 1838 }
pcercuei 0:03b5121a232e 1839
pcercuei 0:03b5121a232e 1840 /**
pcercuei 0:03b5121a232e 1841 * xmlStreamPushInternal:
pcercuei 0:03b5121a232e 1842 * @stream: the stream context
pcercuei 0:03b5121a232e 1843 * @name: the current name
pcercuei 0:03b5121a232e 1844 * @ns: the namespace name
pcercuei 0:03b5121a232e 1845 * @nodeType: the type of the node
pcercuei 0:03b5121a232e 1846 *
pcercuei 0:03b5121a232e 1847 * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
pcercuei 0:03b5121a232e 1848 * indicated a dictionary, then strings for name and ns will be expected
pcercuei 0:03b5121a232e 1849 * to come from the dictionary.
pcercuei 0:03b5121a232e 1850 * Both @name and @ns being NULL means the / i.e. the root of the document.
pcercuei 0:03b5121a232e 1851 * This can also act as a reset.
pcercuei 0:03b5121a232e 1852 *
pcercuei 0:03b5121a232e 1853 * Returns: -1 in case of error, 1 if the current state in the stream is a
pcercuei 0:03b5121a232e 1854 * match and 0 otherwise.
pcercuei 0:03b5121a232e 1855 */
pcercuei 0:03b5121a232e 1856 static int
pcercuei 0:03b5121a232e 1857 xmlStreamPushInternal(xmlStreamCtxtPtr stream,
pcercuei 0:03b5121a232e 1858 const xmlChar *name, const xmlChar *ns,
pcercuei 0:03b5121a232e 1859 int nodeType) {
pcercuei 0:03b5121a232e 1860 int ret = 0, err = 0, final = 0, tmp, i, m, match, stepNr, desc;
pcercuei 0:03b5121a232e 1861 xmlStreamCompPtr comp;
pcercuei 0:03b5121a232e 1862 xmlStreamStep step;
pcercuei 0:03b5121a232e 1863 #ifdef DEBUG_STREAMING
pcercuei 0:03b5121a232e 1864 xmlStreamCtxtPtr orig = stream;
pcercuei 0:03b5121a232e 1865 #endif
pcercuei 0:03b5121a232e 1866
pcercuei 0:03b5121a232e 1867 if ((stream == NULL) || (stream->nbState < 0))
pcercuei 0:03b5121a232e 1868 return(-1);
pcercuei 0:03b5121a232e 1869
pcercuei 0:03b5121a232e 1870 while (stream != NULL) {
pcercuei 0:03b5121a232e 1871 comp = stream->comp;
pcercuei 0:03b5121a232e 1872
pcercuei 0:03b5121a232e 1873 if ((nodeType == XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 1874 (name == NULL) && (ns == NULL)) {
pcercuei 0:03b5121a232e 1875 /* We have a document node here (or a reset). */
pcercuei 0:03b5121a232e 1876 stream->nbState = 0;
pcercuei 0:03b5121a232e 1877 stream->level = 0;
pcercuei 0:03b5121a232e 1878 stream->blockLevel = -1;
pcercuei 0:03b5121a232e 1879 if (comp->flags & XML_STREAM_FROM_ROOT) {
pcercuei 0:03b5121a232e 1880 if (comp->nbStep == 0) {
pcercuei 0:03b5121a232e 1881 /* TODO: We have a "/." here? */
pcercuei 0:03b5121a232e 1882 ret = 1;
pcercuei 0:03b5121a232e 1883 } else {
pcercuei 0:03b5121a232e 1884 if ((comp->nbStep == 1) &&
pcercuei 0:03b5121a232e 1885 (comp->steps[0].nodeType == XML_STREAM_ANY_NODE) &&
pcercuei 0:03b5121a232e 1886 (comp->steps[0].flags & XML_STREAM_STEP_DESC))
pcercuei 0:03b5121a232e 1887 {
pcercuei 0:03b5121a232e 1888 /*
pcercuei 0:03b5121a232e 1889 * In the case of "//." the document node will match
pcercuei 0:03b5121a232e 1890 * as well.
pcercuei 0:03b5121a232e 1891 */
pcercuei 0:03b5121a232e 1892 ret = 1;
pcercuei 0:03b5121a232e 1893 } else if (comp->steps[0].flags & XML_STREAM_STEP_ROOT) {
pcercuei 0:03b5121a232e 1894 /* TODO: Do we need this ? */
pcercuei 0:03b5121a232e 1895 tmp = xmlStreamCtxtAddState(stream, 0, 0);
pcercuei 0:03b5121a232e 1896 if (tmp < 0)
pcercuei 0:03b5121a232e 1897 err++;
pcercuei 0:03b5121a232e 1898 }
pcercuei 0:03b5121a232e 1899 }
pcercuei 0:03b5121a232e 1900 }
pcercuei 0:03b5121a232e 1901 stream = stream->next;
pcercuei 0:03b5121a232e 1902 continue; /* while */
pcercuei 0:03b5121a232e 1903 }
pcercuei 0:03b5121a232e 1904
pcercuei 0:03b5121a232e 1905 /*
pcercuei 0:03b5121a232e 1906 * Fast check for ".".
pcercuei 0:03b5121a232e 1907 */
pcercuei 0:03b5121a232e 1908 if (comp->nbStep == 0) {
pcercuei 0:03b5121a232e 1909 /*
pcercuei 0:03b5121a232e 1910 * / and . are handled at the XPath node set creation
pcercuei 0:03b5121a232e 1911 * level by checking min depth
pcercuei 0:03b5121a232e 1912 */
pcercuei 0:03b5121a232e 1913 if (stream->flags & XML_PATTERN_XPATH) {
pcercuei 0:03b5121a232e 1914 stream = stream->next;
pcercuei 0:03b5121a232e 1915 continue; /* while */
pcercuei 0:03b5121a232e 1916 }
pcercuei 0:03b5121a232e 1917 /*
pcercuei 0:03b5121a232e 1918 * For non-pattern like evaluation like XML Schema IDCs
pcercuei 0:03b5121a232e 1919 * or traditional XPath expressions, this will match if
pcercuei 0:03b5121a232e 1920 * we are at the first level only, otherwise on every level.
pcercuei 0:03b5121a232e 1921 */
pcercuei 0:03b5121a232e 1922 if ((nodeType != XML_ATTRIBUTE_NODE) &&
pcercuei 0:03b5121a232e 1923 (((stream->flags & XML_PATTERN_NOTPATTERN) == 0) ||
pcercuei 0:03b5121a232e 1924 (stream->level == 0))) {
pcercuei 0:03b5121a232e 1925 ret = 1;
pcercuei 0:03b5121a232e 1926 }
pcercuei 0:03b5121a232e 1927 stream->level++;
pcercuei 0:03b5121a232e 1928 goto stream_next;
pcercuei 0:03b5121a232e 1929 }
pcercuei 0:03b5121a232e 1930 if (stream->blockLevel != -1) {
pcercuei 0:03b5121a232e 1931 /*
pcercuei 0:03b5121a232e 1932 * Skip blocked expressions.
pcercuei 0:03b5121a232e 1933 */
pcercuei 0:03b5121a232e 1934 stream->level++;
pcercuei 0:03b5121a232e 1935 goto stream_next;
pcercuei 0:03b5121a232e 1936 }
pcercuei 0:03b5121a232e 1937
pcercuei 0:03b5121a232e 1938 if ((nodeType != XML_ELEMENT_NODE) &&
pcercuei 0:03b5121a232e 1939 (nodeType != XML_ATTRIBUTE_NODE) &&
pcercuei 0:03b5121a232e 1940 ((comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) == 0)) {
pcercuei 0:03b5121a232e 1941 /*
pcercuei 0:03b5121a232e 1942 * No need to process nodes of other types if we don't
pcercuei 0:03b5121a232e 1943 * resolve to those types.
pcercuei 0:03b5121a232e 1944 * TODO: Do we need to block the context here?
pcercuei 0:03b5121a232e 1945 */
pcercuei 0:03b5121a232e 1946 stream->level++;
pcercuei 0:03b5121a232e 1947 goto stream_next;
pcercuei 0:03b5121a232e 1948 }
pcercuei 0:03b5121a232e 1949
pcercuei 0:03b5121a232e 1950 /*
pcercuei 0:03b5121a232e 1951 * Check evolution of existing states
pcercuei 0:03b5121a232e 1952 */
pcercuei 0:03b5121a232e 1953 i = 0;
pcercuei 0:03b5121a232e 1954 m = stream->nbState;
pcercuei 0:03b5121a232e 1955 while (i < m) {
pcercuei 0:03b5121a232e 1956 if ((comp->flags & XML_STREAM_DESC) == 0) {
pcercuei 0:03b5121a232e 1957 /*
pcercuei 0:03b5121a232e 1958 * If there is no "//", then only the last
pcercuei 0:03b5121a232e 1959 * added state is of interest.
pcercuei 0:03b5121a232e 1960 */
pcercuei 0:03b5121a232e 1961 stepNr = stream->states[2 * (stream->nbState -1)];
pcercuei 0:03b5121a232e 1962 /*
pcercuei 0:03b5121a232e 1963 * TODO: Security check, should not happen, remove it.
pcercuei 0:03b5121a232e 1964 */
pcercuei 0:03b5121a232e 1965 if (stream->states[(2 * (stream->nbState -1)) + 1] <
pcercuei 0:03b5121a232e 1966 stream->level) {
pcercuei 0:03b5121a232e 1967 return (-1);
pcercuei 0:03b5121a232e 1968 }
pcercuei 0:03b5121a232e 1969 desc = 0;
pcercuei 0:03b5121a232e 1970 /* loop-stopper */
pcercuei 0:03b5121a232e 1971 i = m;
pcercuei 0:03b5121a232e 1972 } else {
pcercuei 0:03b5121a232e 1973 /*
pcercuei 0:03b5121a232e 1974 * If there are "//", then we need to process every "//"
pcercuei 0:03b5121a232e 1975 * occuring in the states, plus any other state for this
pcercuei 0:03b5121a232e 1976 * level.
pcercuei 0:03b5121a232e 1977 */
pcercuei 0:03b5121a232e 1978 stepNr = stream->states[2 * i];
pcercuei 0:03b5121a232e 1979
pcercuei 0:03b5121a232e 1980 /* TODO: should not happen anymore: dead states */
pcercuei 0:03b5121a232e 1981 if (stepNr < 0)
pcercuei 0:03b5121a232e 1982 goto next_state;
pcercuei 0:03b5121a232e 1983
pcercuei 0:03b5121a232e 1984 tmp = stream->states[(2 * i) + 1];
pcercuei 0:03b5121a232e 1985
pcercuei 0:03b5121a232e 1986 /* skip new states just added */
pcercuei 0:03b5121a232e 1987 if (tmp > stream->level)
pcercuei 0:03b5121a232e 1988 goto next_state;
pcercuei 0:03b5121a232e 1989
pcercuei 0:03b5121a232e 1990 /* skip states at ancestor levels, except if "//" */
pcercuei 0:03b5121a232e 1991 desc = comp->steps[stepNr].flags & XML_STREAM_STEP_DESC;
pcercuei 0:03b5121a232e 1992 if ((tmp < stream->level) && (!desc))
pcercuei 0:03b5121a232e 1993 goto next_state;
pcercuei 0:03b5121a232e 1994 }
pcercuei 0:03b5121a232e 1995 /*
pcercuei 0:03b5121a232e 1996 * Check for correct node-type.
pcercuei 0:03b5121a232e 1997 */
pcercuei 0:03b5121a232e 1998 step = comp->steps[stepNr];
pcercuei 0:03b5121a232e 1999 if (step.nodeType != nodeType) {
pcercuei 0:03b5121a232e 2000 if (step.nodeType == XML_ATTRIBUTE_NODE) {
pcercuei 0:03b5121a232e 2001 /*
pcercuei 0:03b5121a232e 2002 * Block this expression for deeper evaluation.
pcercuei 0:03b5121a232e 2003 */
pcercuei 0:03b5121a232e 2004 if ((comp->flags & XML_STREAM_DESC) == 0)
pcercuei 0:03b5121a232e 2005 stream->blockLevel = stream->level +1;
pcercuei 0:03b5121a232e 2006 goto next_state;
pcercuei 0:03b5121a232e 2007 } else if (step.nodeType != XML_STREAM_ANY_NODE)
pcercuei 0:03b5121a232e 2008 goto next_state;
pcercuei 0:03b5121a232e 2009 }
pcercuei 0:03b5121a232e 2010 /*
pcercuei 0:03b5121a232e 2011 * Compare local/namespace-name.
pcercuei 0:03b5121a232e 2012 */
pcercuei 0:03b5121a232e 2013 match = 0;
pcercuei 0:03b5121a232e 2014 if (step.nodeType == XML_STREAM_ANY_NODE) {
pcercuei 0:03b5121a232e 2015 match = 1;
pcercuei 0:03b5121a232e 2016 } else if (step.name == NULL) {
pcercuei 0:03b5121a232e 2017 if (step.ns == NULL) {
pcercuei 0:03b5121a232e 2018 /*
pcercuei 0:03b5121a232e 2019 * This lets through all elements/attributes.
pcercuei 0:03b5121a232e 2020 */
pcercuei 0:03b5121a232e 2021 match = 1;
pcercuei 0:03b5121a232e 2022 } else if (ns != NULL)
pcercuei 0:03b5121a232e 2023 match = xmlStrEqual(step.ns, ns);
pcercuei 0:03b5121a232e 2024 } else if (((step.ns != NULL) == (ns != NULL)) &&
pcercuei 0:03b5121a232e 2025 (name != NULL) &&
pcercuei 0:03b5121a232e 2026 (step.name[0] == name[0]) &&
pcercuei 0:03b5121a232e 2027 xmlStrEqual(step.name, name) &&
pcercuei 0:03b5121a232e 2028 ((step.ns == ns) || xmlStrEqual(step.ns, ns)))
pcercuei 0:03b5121a232e 2029 {
pcercuei 0:03b5121a232e 2030 match = 1;
pcercuei 0:03b5121a232e 2031 }
pcercuei 0:03b5121a232e 2032 #if 0
pcercuei 0:03b5121a232e 2033 /*
pcercuei 0:03b5121a232e 2034 * TODO: Pointer comparison won't work, since not guaranteed that the given
pcercuei 0:03b5121a232e 2035 * values are in the same dict; especially if it's the namespace name,
pcercuei 0:03b5121a232e 2036 * normally coming from ns->href. We need a namespace dict mechanism !
pcercuei 0:03b5121a232e 2037 */
pcercuei 0:03b5121a232e 2038 } else if (comp->dict) {
pcercuei 0:03b5121a232e 2039 if (step.name == NULL) {
pcercuei 0:03b5121a232e 2040 if (step.ns == NULL)
pcercuei 0:03b5121a232e 2041 match = 1;
pcercuei 0:03b5121a232e 2042 else
pcercuei 0:03b5121a232e 2043 match = (step.ns == ns);
pcercuei 0:03b5121a232e 2044 } else {
pcercuei 0:03b5121a232e 2045 match = ((step.name == name) && (step.ns == ns));
pcercuei 0:03b5121a232e 2046 }
pcercuei 0:03b5121a232e 2047 #endif /* if 0 ------------------------------------------------------- */
pcercuei 0:03b5121a232e 2048 if (match) {
pcercuei 0:03b5121a232e 2049 final = step.flags & XML_STREAM_STEP_FINAL;
pcercuei 0:03b5121a232e 2050 if (desc) {
pcercuei 0:03b5121a232e 2051 if (final) {
pcercuei 0:03b5121a232e 2052 ret = 1;
pcercuei 0:03b5121a232e 2053 } else {
pcercuei 0:03b5121a232e 2054 /* descending match create a new state */
pcercuei 0:03b5121a232e 2055 xmlStreamCtxtAddState(stream, stepNr + 1,
pcercuei 0:03b5121a232e 2056 stream->level + 1);
pcercuei 0:03b5121a232e 2057 }
pcercuei 0:03b5121a232e 2058 } else {
pcercuei 0:03b5121a232e 2059 if (final) {
pcercuei 0:03b5121a232e 2060 ret = 1;
pcercuei 0:03b5121a232e 2061 } else {
pcercuei 0:03b5121a232e 2062 xmlStreamCtxtAddState(stream, stepNr + 1,
pcercuei 0:03b5121a232e 2063 stream->level + 1);
pcercuei 0:03b5121a232e 2064 }
pcercuei 0:03b5121a232e 2065 }
pcercuei 0:03b5121a232e 2066 if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
pcercuei 0:03b5121a232e 2067 /*
pcercuei 0:03b5121a232e 2068 * Check if we have a special case like "foo/bar//.", where
pcercuei 0:03b5121a232e 2069 * "foo" is selected as well.
pcercuei 0:03b5121a232e 2070 */
pcercuei 0:03b5121a232e 2071 ret = 1;
pcercuei 0:03b5121a232e 2072 }
pcercuei 0:03b5121a232e 2073 }
pcercuei 0:03b5121a232e 2074 if (((comp->flags & XML_STREAM_DESC) == 0) &&
pcercuei 0:03b5121a232e 2075 ((! match) || final)) {
pcercuei 0:03b5121a232e 2076 /*
pcercuei 0:03b5121a232e 2077 * Mark this expression as blocked for any evaluation at
pcercuei 0:03b5121a232e 2078 * deeper levels. Note that this includes "/foo"
pcercuei 0:03b5121a232e 2079 * expressions if the *pattern* behaviour is used.
pcercuei 0:03b5121a232e 2080 */
pcercuei 0:03b5121a232e 2081 stream->blockLevel = stream->level +1;
pcercuei 0:03b5121a232e 2082 }
pcercuei 0:03b5121a232e 2083 next_state:
pcercuei 0:03b5121a232e 2084 i++;
pcercuei 0:03b5121a232e 2085 }
pcercuei 0:03b5121a232e 2086
pcercuei 0:03b5121a232e 2087 stream->level++;
pcercuei 0:03b5121a232e 2088
pcercuei 0:03b5121a232e 2089 /*
pcercuei 0:03b5121a232e 2090 * Re/enter the expression.
pcercuei 0:03b5121a232e 2091 * Don't reenter if it's an absolute expression like "/foo",
pcercuei 0:03b5121a232e 2092 * except "//foo".
pcercuei 0:03b5121a232e 2093 */
pcercuei 0:03b5121a232e 2094 step = comp->steps[0];
pcercuei 0:03b5121a232e 2095 if (step.flags & XML_STREAM_STEP_ROOT)
pcercuei 0:03b5121a232e 2096 goto stream_next;
pcercuei 0:03b5121a232e 2097
pcercuei 0:03b5121a232e 2098 desc = step.flags & XML_STREAM_STEP_DESC;
pcercuei 0:03b5121a232e 2099 if (stream->flags & XML_PATTERN_NOTPATTERN) {
pcercuei 0:03b5121a232e 2100 /*
pcercuei 0:03b5121a232e 2101 * Re/enter the expression if it is a "descendant" one,
pcercuei 0:03b5121a232e 2102 * or if we are at the 1st level of evaluation.
pcercuei 0:03b5121a232e 2103 */
pcercuei 0:03b5121a232e 2104
pcercuei 0:03b5121a232e 2105 if (stream->level == 1) {
pcercuei 0:03b5121a232e 2106 if (XML_STREAM_XS_IDC(stream)) {
pcercuei 0:03b5121a232e 2107 /*
pcercuei 0:03b5121a232e 2108 * XS-IDC: The missing "self::node()" will always
pcercuei 0:03b5121a232e 2109 * match the first given node.
pcercuei 0:03b5121a232e 2110 */
pcercuei 0:03b5121a232e 2111 goto stream_next;
pcercuei 0:03b5121a232e 2112 } else
pcercuei 0:03b5121a232e 2113 goto compare;
pcercuei 0:03b5121a232e 2114 }
pcercuei 0:03b5121a232e 2115 /*
pcercuei 0:03b5121a232e 2116 * A "//" is always reentrant.
pcercuei 0:03b5121a232e 2117 */
pcercuei 0:03b5121a232e 2118 if (desc)
pcercuei 0:03b5121a232e 2119 goto compare;
pcercuei 0:03b5121a232e 2120
pcercuei 0:03b5121a232e 2121 /*
pcercuei 0:03b5121a232e 2122 * XS-IDC: Process the 2nd level, since the missing
pcercuei 0:03b5121a232e 2123 * "self::node()" is responsible for the 2nd level being
pcercuei 0:03b5121a232e 2124 * the real start level.
pcercuei 0:03b5121a232e 2125 */
pcercuei 0:03b5121a232e 2126 if ((stream->level == 2) && XML_STREAM_XS_IDC(stream))
pcercuei 0:03b5121a232e 2127 goto compare;
pcercuei 0:03b5121a232e 2128
pcercuei 0:03b5121a232e 2129 goto stream_next;
pcercuei 0:03b5121a232e 2130 }
pcercuei 0:03b5121a232e 2131
pcercuei 0:03b5121a232e 2132 compare:
pcercuei 0:03b5121a232e 2133 /*
pcercuei 0:03b5121a232e 2134 * Check expected node-type.
pcercuei 0:03b5121a232e 2135 */
pcercuei 0:03b5121a232e 2136 if (step.nodeType != nodeType) {
pcercuei 0:03b5121a232e 2137 if (nodeType == XML_ATTRIBUTE_NODE)
pcercuei 0:03b5121a232e 2138 goto stream_next;
pcercuei 0:03b5121a232e 2139 else if (step.nodeType != XML_STREAM_ANY_NODE)
pcercuei 0:03b5121a232e 2140 goto stream_next;
pcercuei 0:03b5121a232e 2141 }
pcercuei 0:03b5121a232e 2142 /*
pcercuei 0:03b5121a232e 2143 * Compare local/namespace-name.
pcercuei 0:03b5121a232e 2144 */
pcercuei 0:03b5121a232e 2145 match = 0;
pcercuei 0:03b5121a232e 2146 if (step.nodeType == XML_STREAM_ANY_NODE) {
pcercuei 0:03b5121a232e 2147 match = 1;
pcercuei 0:03b5121a232e 2148 } else if (step.name == NULL) {
pcercuei 0:03b5121a232e 2149 if (step.ns == NULL) {
pcercuei 0:03b5121a232e 2150 /*
pcercuei 0:03b5121a232e 2151 * This lets through all elements/attributes.
pcercuei 0:03b5121a232e 2152 */
pcercuei 0:03b5121a232e 2153 match = 1;
pcercuei 0:03b5121a232e 2154 } else if (ns != NULL)
pcercuei 0:03b5121a232e 2155 match = xmlStrEqual(step.ns, ns);
pcercuei 0:03b5121a232e 2156 } else if (((step.ns != NULL) == (ns != NULL)) &&
pcercuei 0:03b5121a232e 2157 (name != NULL) &&
pcercuei 0:03b5121a232e 2158 (step.name[0] == name[0]) &&
pcercuei 0:03b5121a232e 2159 xmlStrEqual(step.name, name) &&
pcercuei 0:03b5121a232e 2160 ((step.ns == ns) || xmlStrEqual(step.ns, ns)))
pcercuei 0:03b5121a232e 2161 {
pcercuei 0:03b5121a232e 2162 match = 1;
pcercuei 0:03b5121a232e 2163 }
pcercuei 0:03b5121a232e 2164 final = step.flags & XML_STREAM_STEP_FINAL;
pcercuei 0:03b5121a232e 2165 if (match) {
pcercuei 0:03b5121a232e 2166 if (final)
pcercuei 0:03b5121a232e 2167 ret = 1;
pcercuei 0:03b5121a232e 2168 else
pcercuei 0:03b5121a232e 2169 xmlStreamCtxtAddState(stream, 1, stream->level);
pcercuei 0:03b5121a232e 2170 if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) {
pcercuei 0:03b5121a232e 2171 /*
pcercuei 0:03b5121a232e 2172 * Check if we have a special case like "foo//.", where
pcercuei 0:03b5121a232e 2173 * "foo" is selected as well.
pcercuei 0:03b5121a232e 2174 */
pcercuei 0:03b5121a232e 2175 ret = 1;
pcercuei 0:03b5121a232e 2176 }
pcercuei 0:03b5121a232e 2177 }
pcercuei 0:03b5121a232e 2178 if (((comp->flags & XML_STREAM_DESC) == 0) &&
pcercuei 0:03b5121a232e 2179 ((! match) || final)) {
pcercuei 0:03b5121a232e 2180 /*
pcercuei 0:03b5121a232e 2181 * Mark this expression as blocked for any evaluation at
pcercuei 0:03b5121a232e 2182 * deeper levels.
pcercuei 0:03b5121a232e 2183 */
pcercuei 0:03b5121a232e 2184 stream->blockLevel = stream->level;
pcercuei 0:03b5121a232e 2185 }
pcercuei 0:03b5121a232e 2186
pcercuei 0:03b5121a232e 2187 stream_next:
pcercuei 0:03b5121a232e 2188 stream = stream->next;
pcercuei 0:03b5121a232e 2189 } /* while stream != NULL */
pcercuei 0:03b5121a232e 2190
pcercuei 0:03b5121a232e 2191 if (err > 0)
pcercuei 0:03b5121a232e 2192 ret = -1;
pcercuei 0:03b5121a232e 2193 #ifdef DEBUG_STREAMING
pcercuei 0:03b5121a232e 2194 xmlDebugStreamCtxt(orig, ret);
pcercuei 0:03b5121a232e 2195 #endif
pcercuei 0:03b5121a232e 2196 return(ret);
pcercuei 0:03b5121a232e 2197 }
pcercuei 0:03b5121a232e 2198
pcercuei 0:03b5121a232e 2199 /**
pcercuei 0:03b5121a232e 2200 * xmlStreamPush:
pcercuei 0:03b5121a232e 2201 * @stream: the stream context
pcercuei 0:03b5121a232e 2202 * @name: the current name
pcercuei 0:03b5121a232e 2203 * @ns: the namespace name
pcercuei 0:03b5121a232e 2204 *
pcercuei 0:03b5121a232e 2205 * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
pcercuei 0:03b5121a232e 2206 * indicated a dictionary, then strings for name and ns will be expected
pcercuei 0:03b5121a232e 2207 * to come from the dictionary.
pcercuei 0:03b5121a232e 2208 * Both @name and @ns being NULL means the / i.e. the root of the document.
pcercuei 0:03b5121a232e 2209 * This can also act as a reset.
pcercuei 0:03b5121a232e 2210 * Otherwise the function will act as if it has been given an element-node.
pcercuei 0:03b5121a232e 2211 *
pcercuei 0:03b5121a232e 2212 * Returns: -1 in case of error, 1 if the current state in the stream is a
pcercuei 0:03b5121a232e 2213 * match and 0 otherwise.
pcercuei 0:03b5121a232e 2214 */
pcercuei 0:03b5121a232e 2215 int
pcercuei 0:03b5121a232e 2216 xmlStreamPush(xmlStreamCtxtPtr stream,
pcercuei 0:03b5121a232e 2217 const xmlChar *name, const xmlChar *ns) {
pcercuei 0:03b5121a232e 2218 return (xmlStreamPushInternal(stream, name, ns, (int) XML_ELEMENT_NODE));
pcercuei 0:03b5121a232e 2219 }
pcercuei 0:03b5121a232e 2220
pcercuei 0:03b5121a232e 2221 /**
pcercuei 0:03b5121a232e 2222 * xmlStreamPushNode:
pcercuei 0:03b5121a232e 2223 * @stream: the stream context
pcercuei 0:03b5121a232e 2224 * @name: the current name
pcercuei 0:03b5121a232e 2225 * @ns: the namespace name
pcercuei 0:03b5121a232e 2226 * @nodeType: the type of the node being pushed
pcercuei 0:03b5121a232e 2227 *
pcercuei 0:03b5121a232e 2228 * Push new data onto the stream. NOTE: if the call xmlPatterncompile()
pcercuei 0:03b5121a232e 2229 * indicated a dictionary, then strings for name and ns will be expected
pcercuei 0:03b5121a232e 2230 * to come from the dictionary.
pcercuei 0:03b5121a232e 2231 * Both @name and @ns being NULL means the / i.e. the root of the document.
pcercuei 0:03b5121a232e 2232 * This can also act as a reset.
pcercuei 0:03b5121a232e 2233 * Different from xmlStreamPush() this function can be fed with nodes of type:
pcercuei 0:03b5121a232e 2234 * element-, attribute-, text-, cdata-section-, comment- and
pcercuei 0:03b5121a232e 2235 * processing-instruction-node.
pcercuei 0:03b5121a232e 2236 *
pcercuei 0:03b5121a232e 2237 * Returns: -1 in case of error, 1 if the current state in the stream is a
pcercuei 0:03b5121a232e 2238 * match and 0 otherwise.
pcercuei 0:03b5121a232e 2239 */
pcercuei 0:03b5121a232e 2240 int
pcercuei 0:03b5121a232e 2241 xmlStreamPushNode(xmlStreamCtxtPtr stream,
pcercuei 0:03b5121a232e 2242 const xmlChar *name, const xmlChar *ns,
pcercuei 0:03b5121a232e 2243 int nodeType)
pcercuei 0:03b5121a232e 2244 {
pcercuei 0:03b5121a232e 2245 return (xmlStreamPushInternal(stream, name, ns,
pcercuei 0:03b5121a232e 2246 nodeType));
pcercuei 0:03b5121a232e 2247 }
pcercuei 0:03b5121a232e 2248
pcercuei 0:03b5121a232e 2249 /**
pcercuei 0:03b5121a232e 2250 * xmlStreamPushAttr:
pcercuei 0:03b5121a232e 2251 * @stream: the stream context
pcercuei 0:03b5121a232e 2252 * @name: the current name
pcercuei 0:03b5121a232e 2253 * @ns: the namespace name
pcercuei 0:03b5121a232e 2254 *
pcercuei 0:03b5121a232e 2255 * Push new attribute data onto the stream. NOTE: if the call xmlPatterncompile()
pcercuei 0:03b5121a232e 2256 * indicated a dictionary, then strings for name and ns will be expected
pcercuei 0:03b5121a232e 2257 * to come from the dictionary.
pcercuei 0:03b5121a232e 2258 * Both @name and @ns being NULL means the / i.e. the root of the document.
pcercuei 0:03b5121a232e 2259 * This can also act as a reset.
pcercuei 0:03b5121a232e 2260 * Otherwise the function will act as if it has been given an attribute-node.
pcercuei 0:03b5121a232e 2261 *
pcercuei 0:03b5121a232e 2262 * Returns: -1 in case of error, 1 if the current state in the stream is a
pcercuei 0:03b5121a232e 2263 * match and 0 otherwise.
pcercuei 0:03b5121a232e 2264 */
pcercuei 0:03b5121a232e 2265 int
pcercuei 0:03b5121a232e 2266 xmlStreamPushAttr(xmlStreamCtxtPtr stream,
pcercuei 0:03b5121a232e 2267 const xmlChar *name, const xmlChar *ns) {
pcercuei 0:03b5121a232e 2268 return (xmlStreamPushInternal(stream, name, ns, (int) XML_ATTRIBUTE_NODE));
pcercuei 0:03b5121a232e 2269 }
pcercuei 0:03b5121a232e 2270
pcercuei 0:03b5121a232e 2271 /**
pcercuei 0:03b5121a232e 2272 * xmlStreamPop:
pcercuei 0:03b5121a232e 2273 * @stream: the stream context
pcercuei 0:03b5121a232e 2274 *
pcercuei 0:03b5121a232e 2275 * push one level from the stream.
pcercuei 0:03b5121a232e 2276 *
pcercuei 0:03b5121a232e 2277 * Returns: -1 in case of error, 0 otherwise.
pcercuei 0:03b5121a232e 2278 */
pcercuei 0:03b5121a232e 2279 int
pcercuei 0:03b5121a232e 2280 xmlStreamPop(xmlStreamCtxtPtr stream) {
pcercuei 0:03b5121a232e 2281 int i, lev;
pcercuei 0:03b5121a232e 2282
pcercuei 0:03b5121a232e 2283 if (stream == NULL)
pcercuei 0:03b5121a232e 2284 return(-1);
pcercuei 0:03b5121a232e 2285 while (stream != NULL) {
pcercuei 0:03b5121a232e 2286 /*
pcercuei 0:03b5121a232e 2287 * Reset block-level.
pcercuei 0:03b5121a232e 2288 */
pcercuei 0:03b5121a232e 2289 if (stream->blockLevel == stream->level)
pcercuei 0:03b5121a232e 2290 stream->blockLevel = -1;
pcercuei 0:03b5121a232e 2291
pcercuei 0:03b5121a232e 2292 /*
pcercuei 0:03b5121a232e 2293 * stream->level can be zero when XML_FINAL_IS_ANY_NODE is set
pcercuei 0:03b5121a232e 2294 * (see the thread at
pcercuei 0:03b5121a232e 2295 * http://mail.gnome.org/archives/xslt/2008-July/msg00027.html)
pcercuei 0:03b5121a232e 2296 */
pcercuei 0:03b5121a232e 2297 if (stream->level)
pcercuei 0:03b5121a232e 2298 stream->level--;
pcercuei 0:03b5121a232e 2299 /*
pcercuei 0:03b5121a232e 2300 * Check evolution of existing states
pcercuei 0:03b5121a232e 2301 */
pcercuei 0:03b5121a232e 2302 for (i = stream->nbState -1; i >= 0; i--) {
pcercuei 0:03b5121a232e 2303 /* discard obsoleted states */
pcercuei 0:03b5121a232e 2304 lev = stream->states[(2 * i) + 1];
pcercuei 0:03b5121a232e 2305 if (lev > stream->level)
pcercuei 0:03b5121a232e 2306 stream->nbState--;
pcercuei 0:03b5121a232e 2307 if (lev <= stream->level)
pcercuei 0:03b5121a232e 2308 break;
pcercuei 0:03b5121a232e 2309 }
pcercuei 0:03b5121a232e 2310 stream = stream->next;
pcercuei 0:03b5121a232e 2311 }
pcercuei 0:03b5121a232e 2312 return(0);
pcercuei 0:03b5121a232e 2313 }
pcercuei 0:03b5121a232e 2314
pcercuei 0:03b5121a232e 2315 /**
pcercuei 0:03b5121a232e 2316 * xmlStreamWantsAnyNode:
pcercuei 0:03b5121a232e 2317 * @streamCtxt: the stream context
pcercuei 0:03b5121a232e 2318 *
pcercuei 0:03b5121a232e 2319 * Query if the streaming pattern additionally needs to be fed with
pcercuei 0:03b5121a232e 2320 * text-, cdata-section-, comment- and processing-instruction-nodes.
pcercuei 0:03b5121a232e 2321 * If the result is 0 then only element-nodes and attribute-nodes
pcercuei 0:03b5121a232e 2322 * need to be pushed.
pcercuei 0:03b5121a232e 2323 *
pcercuei 0:03b5121a232e 2324 * Returns: 1 in case of need of nodes of the above described types,
pcercuei 0:03b5121a232e 2325 * 0 otherwise. -1 on API errors.
pcercuei 0:03b5121a232e 2326 */
pcercuei 0:03b5121a232e 2327 int
pcercuei 0:03b5121a232e 2328 xmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt)
pcercuei 0:03b5121a232e 2329 {
pcercuei 0:03b5121a232e 2330 if (streamCtxt == NULL)
pcercuei 0:03b5121a232e 2331 return(-1);
pcercuei 0:03b5121a232e 2332 while (streamCtxt != NULL) {
pcercuei 0:03b5121a232e 2333 if (streamCtxt->comp->flags & XML_STREAM_FINAL_IS_ANY_NODE)
pcercuei 0:03b5121a232e 2334 return(1);
pcercuei 0:03b5121a232e 2335 streamCtxt = streamCtxt->next;
pcercuei 0:03b5121a232e 2336 }
pcercuei 0:03b5121a232e 2337 return(0);
pcercuei 0:03b5121a232e 2338 }
pcercuei 0:03b5121a232e 2339
pcercuei 0:03b5121a232e 2340 /************************************************************************
pcercuei 0:03b5121a232e 2341 * *
pcercuei 0:03b5121a232e 2342 * The public interfaces *
pcercuei 0:03b5121a232e 2343 * *
pcercuei 0:03b5121a232e 2344 ************************************************************************/
pcercuei 0:03b5121a232e 2345
pcercuei 0:03b5121a232e 2346 /**
pcercuei 0:03b5121a232e 2347 * xmlPatterncompile:
pcercuei 0:03b5121a232e 2348 * @pattern: the pattern to compile
pcercuei 0:03b5121a232e 2349 * @dict: an optional dictionary for interned strings
pcercuei 0:03b5121a232e 2350 * @flags: compilation flags, see xmlPatternFlags
pcercuei 0:03b5121a232e 2351 * @namespaces: the prefix definitions, array of [URI, prefix] or NULL
pcercuei 0:03b5121a232e 2352 *
pcercuei 0:03b5121a232e 2353 * Compile a pattern.
pcercuei 0:03b5121a232e 2354 *
pcercuei 0:03b5121a232e 2355 * Returns the compiled form of the pattern or NULL in case of error
pcercuei 0:03b5121a232e 2356 */
pcercuei 0:03b5121a232e 2357 xmlPatternPtr
pcercuei 0:03b5121a232e 2358 xmlPatterncompile(const xmlChar *pattern, xmlDict *dict, int flags,
pcercuei 0:03b5121a232e 2359 const xmlChar **namespaces) {
pcercuei 0:03b5121a232e 2360 xmlPatternPtr ret = NULL, cur;
pcercuei 0:03b5121a232e 2361 xmlPatParserContextPtr ctxt = NULL;
pcercuei 0:03b5121a232e 2362 const xmlChar *or, *start;
pcercuei 0:03b5121a232e 2363 xmlChar *tmp = NULL;
pcercuei 0:03b5121a232e 2364 int type = 0;
pcercuei 0:03b5121a232e 2365 int streamable = 1;
pcercuei 0:03b5121a232e 2366
pcercuei 0:03b5121a232e 2367 if (pattern == NULL)
pcercuei 0:03b5121a232e 2368 return(NULL);
pcercuei 0:03b5121a232e 2369
pcercuei 0:03b5121a232e 2370 start = pattern;
pcercuei 0:03b5121a232e 2371 or = start;
pcercuei 0:03b5121a232e 2372 while (*or != 0) {
pcercuei 0:03b5121a232e 2373 tmp = NULL;
pcercuei 0:03b5121a232e 2374 while ((*or != 0) && (*or != '|')) or++;
pcercuei 0:03b5121a232e 2375 if (*or == 0)
pcercuei 0:03b5121a232e 2376 ctxt = xmlNewPatParserContext(start, dict, namespaces);
pcercuei 0:03b5121a232e 2377 else {
pcercuei 0:03b5121a232e 2378 tmp = xmlStrndup(start, or - start);
pcercuei 0:03b5121a232e 2379 if (tmp != NULL) {
pcercuei 0:03b5121a232e 2380 ctxt = xmlNewPatParserContext(tmp, dict, namespaces);
pcercuei 0:03b5121a232e 2381 }
pcercuei 0:03b5121a232e 2382 or++;
pcercuei 0:03b5121a232e 2383 }
pcercuei 0:03b5121a232e 2384 if (ctxt == NULL) goto error;
pcercuei 0:03b5121a232e 2385 cur = xmlNewPattern();
pcercuei 0:03b5121a232e 2386 if (cur == NULL) goto error;
pcercuei 0:03b5121a232e 2387 /*
pcercuei 0:03b5121a232e 2388 * Assign string dict.
pcercuei 0:03b5121a232e 2389 */
pcercuei 0:03b5121a232e 2390 if (dict) {
pcercuei 0:03b5121a232e 2391 cur->dict = dict;
pcercuei 0:03b5121a232e 2392 xmlDictReference(dict);
pcercuei 0:03b5121a232e 2393 }
pcercuei 0:03b5121a232e 2394 if (ret == NULL)
pcercuei 0:03b5121a232e 2395 ret = cur;
pcercuei 0:03b5121a232e 2396 else {
pcercuei 0:03b5121a232e 2397 cur->next = ret->next;
pcercuei 0:03b5121a232e 2398 ret->next = cur;
pcercuei 0:03b5121a232e 2399 }
pcercuei 0:03b5121a232e 2400 cur->flags = flags;
pcercuei 0:03b5121a232e 2401 ctxt->comp = cur;
pcercuei 0:03b5121a232e 2402
pcercuei 0:03b5121a232e 2403 if (XML_STREAM_XS_IDC(cur))
pcercuei 0:03b5121a232e 2404 xmlCompileIDCXPathPath(ctxt);
pcercuei 0:03b5121a232e 2405 else
pcercuei 0:03b5121a232e 2406 xmlCompilePathPattern(ctxt);
pcercuei 0:03b5121a232e 2407 if (ctxt->error != 0)
pcercuei 0:03b5121a232e 2408 goto error;
pcercuei 0:03b5121a232e 2409 xmlFreePatParserContext(ctxt);
pcercuei 0:03b5121a232e 2410 ctxt = NULL;
pcercuei 0:03b5121a232e 2411
pcercuei 0:03b5121a232e 2412
pcercuei 0:03b5121a232e 2413 if (streamable) {
pcercuei 0:03b5121a232e 2414 if (type == 0) {
pcercuei 0:03b5121a232e 2415 type = cur->flags & (PAT_FROM_ROOT | PAT_FROM_CUR);
pcercuei 0:03b5121a232e 2416 } else if (type == PAT_FROM_ROOT) {
pcercuei 0:03b5121a232e 2417 if (cur->flags & PAT_FROM_CUR)
pcercuei 0:03b5121a232e 2418 streamable = 0;
pcercuei 0:03b5121a232e 2419 } else if (type == PAT_FROM_CUR) {
pcercuei 0:03b5121a232e 2420 if (cur->flags & PAT_FROM_ROOT)
pcercuei 0:03b5121a232e 2421 streamable = 0;
pcercuei 0:03b5121a232e 2422 }
pcercuei 0:03b5121a232e 2423 }
pcercuei 0:03b5121a232e 2424 if (streamable)
pcercuei 0:03b5121a232e 2425 xmlStreamCompile(cur);
pcercuei 0:03b5121a232e 2426 if (xmlReversePattern(cur) < 0)
pcercuei 0:03b5121a232e 2427 goto error;
pcercuei 0:03b5121a232e 2428 if (tmp != NULL) {
pcercuei 0:03b5121a232e 2429 xmlFree(tmp);
pcercuei 0:03b5121a232e 2430 tmp = NULL;
pcercuei 0:03b5121a232e 2431 }
pcercuei 0:03b5121a232e 2432 start = or;
pcercuei 0:03b5121a232e 2433 }
pcercuei 0:03b5121a232e 2434 if (streamable == 0) {
pcercuei 0:03b5121a232e 2435 cur = ret;
pcercuei 0:03b5121a232e 2436 while (cur != NULL) {
pcercuei 0:03b5121a232e 2437 if (cur->stream != NULL) {
pcercuei 0:03b5121a232e 2438 xmlFreeStreamComp(cur->stream);
pcercuei 0:03b5121a232e 2439 cur->stream = NULL;
pcercuei 0:03b5121a232e 2440 }
pcercuei 0:03b5121a232e 2441 cur = cur->next;
pcercuei 0:03b5121a232e 2442 }
pcercuei 0:03b5121a232e 2443 }
pcercuei 0:03b5121a232e 2444
pcercuei 0:03b5121a232e 2445 return(ret);
pcercuei 0:03b5121a232e 2446 error:
pcercuei 0:03b5121a232e 2447 if (ctxt != NULL) xmlFreePatParserContext(ctxt);
pcercuei 0:03b5121a232e 2448 if (ret != NULL) xmlFreePattern(ret);
pcercuei 0:03b5121a232e 2449 if (tmp != NULL) xmlFree(tmp);
pcercuei 0:03b5121a232e 2450 return(NULL);
pcercuei 0:03b5121a232e 2451 }
pcercuei 0:03b5121a232e 2452
pcercuei 0:03b5121a232e 2453 /**
pcercuei 0:03b5121a232e 2454 * xmlPatternMatch:
pcercuei 0:03b5121a232e 2455 * @comp: the precompiled pattern
pcercuei 0:03b5121a232e 2456 * @node: a node
pcercuei 0:03b5121a232e 2457 *
pcercuei 0:03b5121a232e 2458 * Test whether the node matches the pattern
pcercuei 0:03b5121a232e 2459 *
pcercuei 0:03b5121a232e 2460 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
pcercuei 0:03b5121a232e 2461 */
pcercuei 0:03b5121a232e 2462 int
pcercuei 0:03b5121a232e 2463 xmlPatternMatch(xmlPatternPtr comp, xmlNodePtr node)
pcercuei 0:03b5121a232e 2464 {
pcercuei 0:03b5121a232e 2465 int ret = 0;
pcercuei 0:03b5121a232e 2466
pcercuei 0:03b5121a232e 2467 if ((comp == NULL) || (node == NULL))
pcercuei 0:03b5121a232e 2468 return(-1);
pcercuei 0:03b5121a232e 2469
pcercuei 0:03b5121a232e 2470 while (comp != NULL) {
pcercuei 0:03b5121a232e 2471 ret = xmlPatMatch(comp, node);
pcercuei 0:03b5121a232e 2472 if (ret != 0)
pcercuei 0:03b5121a232e 2473 return(ret);
pcercuei 0:03b5121a232e 2474 comp = comp->next;
pcercuei 0:03b5121a232e 2475 }
pcercuei 0:03b5121a232e 2476 return(ret);
pcercuei 0:03b5121a232e 2477 }
pcercuei 0:03b5121a232e 2478
pcercuei 0:03b5121a232e 2479 /**
pcercuei 0:03b5121a232e 2480 * xmlPatternGetStreamCtxt:
pcercuei 0:03b5121a232e 2481 * @comp: the precompiled pattern
pcercuei 0:03b5121a232e 2482 *
pcercuei 0:03b5121a232e 2483 * Get a streaming context for that pattern
pcercuei 0:03b5121a232e 2484 * Use xmlFreeStreamCtxt to free the context.
pcercuei 0:03b5121a232e 2485 *
pcercuei 0:03b5121a232e 2486 * Returns a pointer to the context or NULL in case of failure
pcercuei 0:03b5121a232e 2487 */
pcercuei 0:03b5121a232e 2488 xmlStreamCtxtPtr
pcercuei 0:03b5121a232e 2489 xmlPatternGetStreamCtxt(xmlPatternPtr comp)
pcercuei 0:03b5121a232e 2490 {
pcercuei 0:03b5121a232e 2491 xmlStreamCtxtPtr ret = NULL, cur;
pcercuei 0:03b5121a232e 2492
pcercuei 0:03b5121a232e 2493 if ((comp == NULL) || (comp->stream == NULL))
pcercuei 0:03b5121a232e 2494 return(NULL);
pcercuei 0:03b5121a232e 2495
pcercuei 0:03b5121a232e 2496 while (comp != NULL) {
pcercuei 0:03b5121a232e 2497 if (comp->stream == NULL)
pcercuei 0:03b5121a232e 2498 goto failed;
pcercuei 0:03b5121a232e 2499 cur = xmlNewStreamCtxt(comp->stream);
pcercuei 0:03b5121a232e 2500 if (cur == NULL)
pcercuei 0:03b5121a232e 2501 goto failed;
pcercuei 0:03b5121a232e 2502 if (ret == NULL)
pcercuei 0:03b5121a232e 2503 ret = cur;
pcercuei 0:03b5121a232e 2504 else {
pcercuei 0:03b5121a232e 2505 cur->next = ret->next;
pcercuei 0:03b5121a232e 2506 ret->next = cur;
pcercuei 0:03b5121a232e 2507 }
pcercuei 0:03b5121a232e 2508 cur->flags = comp->flags;
pcercuei 0:03b5121a232e 2509 comp = comp->next;
pcercuei 0:03b5121a232e 2510 }
pcercuei 0:03b5121a232e 2511 return(ret);
pcercuei 0:03b5121a232e 2512 failed:
pcercuei 0:03b5121a232e 2513 xmlFreeStreamCtxt(ret);
pcercuei 0:03b5121a232e 2514 return(NULL);
pcercuei 0:03b5121a232e 2515 }
pcercuei 0:03b5121a232e 2516
pcercuei 0:03b5121a232e 2517 /**
pcercuei 0:03b5121a232e 2518 * xmlPatternStreamable:
pcercuei 0:03b5121a232e 2519 * @comp: the precompiled pattern
pcercuei 0:03b5121a232e 2520 *
pcercuei 0:03b5121a232e 2521 * Check if the pattern is streamable i.e. xmlPatternGetStreamCtxt()
pcercuei 0:03b5121a232e 2522 * should work.
pcercuei 0:03b5121a232e 2523 *
pcercuei 0:03b5121a232e 2524 * Returns 1 if streamable, 0 if not and -1 in case of error.
pcercuei 0:03b5121a232e 2525 */
pcercuei 0:03b5121a232e 2526 int
pcercuei 0:03b5121a232e 2527 xmlPatternStreamable(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 2528 if (comp == NULL)
pcercuei 0:03b5121a232e 2529 return(-1);
pcercuei 0:03b5121a232e 2530 while (comp != NULL) {
pcercuei 0:03b5121a232e 2531 if (comp->stream == NULL)
pcercuei 0:03b5121a232e 2532 return(0);
pcercuei 0:03b5121a232e 2533 comp = comp->next;
pcercuei 0:03b5121a232e 2534 }
pcercuei 0:03b5121a232e 2535 return(1);
pcercuei 0:03b5121a232e 2536 }
pcercuei 0:03b5121a232e 2537
pcercuei 0:03b5121a232e 2538 /**
pcercuei 0:03b5121a232e 2539 * xmlPatternMaxDepth:
pcercuei 0:03b5121a232e 2540 * @comp: the precompiled pattern
pcercuei 0:03b5121a232e 2541 *
pcercuei 0:03b5121a232e 2542 * Check the maximum depth reachable by a pattern
pcercuei 0:03b5121a232e 2543 *
pcercuei 0:03b5121a232e 2544 * Returns -2 if no limit (using //), otherwise the depth,
pcercuei 0:03b5121a232e 2545 * and -1 in case of error
pcercuei 0:03b5121a232e 2546 */
pcercuei 0:03b5121a232e 2547 int
pcercuei 0:03b5121a232e 2548 xmlPatternMaxDepth(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 2549 int ret = 0, i;
pcercuei 0:03b5121a232e 2550 if (comp == NULL)
pcercuei 0:03b5121a232e 2551 return(-1);
pcercuei 0:03b5121a232e 2552 while (comp != NULL) {
pcercuei 0:03b5121a232e 2553 if (comp->stream == NULL)
pcercuei 0:03b5121a232e 2554 return(-1);
pcercuei 0:03b5121a232e 2555 for (i = 0;i < comp->stream->nbStep;i++)
pcercuei 0:03b5121a232e 2556 if (comp->stream->steps[i].flags & XML_STREAM_STEP_DESC)
pcercuei 0:03b5121a232e 2557 return(-2);
pcercuei 0:03b5121a232e 2558 if (comp->stream->nbStep > ret)
pcercuei 0:03b5121a232e 2559 ret = comp->stream->nbStep;
pcercuei 0:03b5121a232e 2560 comp = comp->next;
pcercuei 0:03b5121a232e 2561 }
pcercuei 0:03b5121a232e 2562 return(ret);
pcercuei 0:03b5121a232e 2563 }
pcercuei 0:03b5121a232e 2564
pcercuei 0:03b5121a232e 2565 /**
pcercuei 0:03b5121a232e 2566 * xmlPatternMinDepth:
pcercuei 0:03b5121a232e 2567 * @comp: the precompiled pattern
pcercuei 0:03b5121a232e 2568 *
pcercuei 0:03b5121a232e 2569 * Check the minimum depth reachable by a pattern, 0 mean the / or . are
pcercuei 0:03b5121a232e 2570 * part of the set.
pcercuei 0:03b5121a232e 2571 *
pcercuei 0:03b5121a232e 2572 * Returns -1 in case of error otherwise the depth,
pcercuei 0:03b5121a232e 2573 *
pcercuei 0:03b5121a232e 2574 */
pcercuei 0:03b5121a232e 2575 int
pcercuei 0:03b5121a232e 2576 xmlPatternMinDepth(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 2577 int ret = 12345678;
pcercuei 0:03b5121a232e 2578 if (comp == NULL)
pcercuei 0:03b5121a232e 2579 return(-1);
pcercuei 0:03b5121a232e 2580 while (comp != NULL) {
pcercuei 0:03b5121a232e 2581 if (comp->stream == NULL)
pcercuei 0:03b5121a232e 2582 return(-1);
pcercuei 0:03b5121a232e 2583 if (comp->stream->nbStep < ret)
pcercuei 0:03b5121a232e 2584 ret = comp->stream->nbStep;
pcercuei 0:03b5121a232e 2585 if (ret == 0)
pcercuei 0:03b5121a232e 2586 return(0);
pcercuei 0:03b5121a232e 2587 comp = comp->next;
pcercuei 0:03b5121a232e 2588 }
pcercuei 0:03b5121a232e 2589 return(ret);
pcercuei 0:03b5121a232e 2590 }
pcercuei 0:03b5121a232e 2591
pcercuei 0:03b5121a232e 2592 /**
pcercuei 0:03b5121a232e 2593 * xmlPatternFromRoot:
pcercuei 0:03b5121a232e 2594 * @comp: the precompiled pattern
pcercuei 0:03b5121a232e 2595 *
pcercuei 0:03b5121a232e 2596 * Check if the pattern must be looked at from the root.
pcercuei 0:03b5121a232e 2597 *
pcercuei 0:03b5121a232e 2598 * Returns 1 if true, 0 if false and -1 in case of error
pcercuei 0:03b5121a232e 2599 */
pcercuei 0:03b5121a232e 2600 int
pcercuei 0:03b5121a232e 2601 xmlPatternFromRoot(xmlPatternPtr comp) {
pcercuei 0:03b5121a232e 2602 if (comp == NULL)
pcercuei 0:03b5121a232e 2603 return(-1);
pcercuei 0:03b5121a232e 2604 while (comp != NULL) {
pcercuei 0:03b5121a232e 2605 if (comp->stream == NULL)
pcercuei 0:03b5121a232e 2606 return(-1);
pcercuei 0:03b5121a232e 2607 if (comp->flags & PAT_FROM_ROOT)
pcercuei 0:03b5121a232e 2608 return(1);
pcercuei 0:03b5121a232e 2609 comp = comp->next;
pcercuei 0:03b5121a232e 2610 }
pcercuei 0:03b5121a232e 2611 return(0);
pcercuei 0:03b5121a232e 2612
pcercuei 0:03b5121a232e 2613 }
pcercuei 0:03b5121a232e 2614
pcercuei 0:03b5121a232e 2615 #define bottom_pattern
pcercuei 0:03b5121a232e 2616 #include "elfgcchack.h"
pcercuei 0:03b5121a232e 2617 #endif /* LIBXML_PATTERN_ENABLED */
pcercuei 0:03b5121a232e 2618