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