OLD | NEW |
1 /* | 1 /* |
2 * pattern.c: Implemetation of selectors for nodes | 2 * pattern.c: Implemetation of selectors for nodes |
3 * | 3 * |
4 * Reference: | 4 * Reference: |
5 * http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/ | 5 * http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/ |
6 * to some extent | 6 * to some extent |
7 * http://www.w3.org/TR/1999/REC-xml-19991116 | 7 * http://www.w3.org/TR/1999/REC-xml-19991116 |
8 * | 8 * |
9 * See Copyright for the status of this software. | 9 * See Copyright for the status of this software. |
10 * | 10 * |
11 * daniel@veillard.com | 11 * daniel@veillard.com |
12 */ | 12 */ |
13 | 13 |
14 /* | 14 /* |
15 * TODO: | 15 * TODO: |
16 * - compilation flags to check for specific syntaxes | 16 * - compilation flags to check for specific syntaxes |
(...skipping 15 matching lines...) Expand all Loading... |
32 #include <libxml/hash.h> | 32 #include <libxml/hash.h> |
33 #include <libxml/dict.h> | 33 #include <libxml/dict.h> |
34 #include <libxml/xmlerror.h> | 34 #include <libxml/xmlerror.h> |
35 #include <libxml/parserInternals.h> | 35 #include <libxml/parserInternals.h> |
36 #include <libxml/pattern.h> | 36 #include <libxml/pattern.h> |
37 | 37 |
38 #ifdef LIBXML_PATTERN_ENABLED | 38 #ifdef LIBXML_PATTERN_ENABLED |
39 | 39 |
40 /* #define DEBUG_STREAMING */ | 40 /* #define DEBUG_STREAMING */ |
41 | 41 |
| 42 #ifdef ERROR |
| 43 #undef ERROR |
| 44 #endif |
42 #define ERROR(a, b, c, d) | 45 #define ERROR(a, b, c, d) |
43 #define ERROR5(a, b, c, d, e) | 46 #define ERROR5(a, b, c, d, e) |
44 | 47 |
45 #define XML_STREAM_STEP_DESC 1 | 48 #define XML_STREAM_STEP_DESC 1 |
46 #define XML_STREAM_STEP_FINAL 2 | 49 #define XML_STREAM_STEP_FINAL 2 |
47 #define XML_STREAM_STEP_ROOT 4 | 50 #define XML_STREAM_STEP_ROOT 4 |
48 #define XML_STREAM_STEP_ATTR 8 | 51 #define XML_STREAM_STEP_ATTR 8 |
49 #define XML_STREAM_STEP_NODE 16 | 52 #define XML_STREAM_STEP_NODE 16 |
50 #define XML_STREAM_STEP_IN_SET 32 | 53 #define XML_STREAM_STEP_IN_SET 32 |
51 | 54 |
52 /* | 55 /* |
53 * NOTE: Those private flags (XML_STREAM_xxx) are used | 56 * NOTE: Those private flags (XML_STREAM_xxx) are used |
54 * in _xmlStreamCtxt->flag. They extend the public | 57 * in _xmlStreamCtxt->flag. They extend the public |
55 * xmlPatternFlags, so be carefull not to interfere with the | 58 * xmlPatternFlags, so be carefull not to interfere with the |
56 * reserved values for xmlPatternFlags. | 59 * reserved values for xmlPatternFlags. |
57 */ | 60 */ |
58 #define XML_STREAM_FINAL_IS_ANY_NODE 1<<14 | 61 #define XML_STREAM_FINAL_IS_ANY_NODE 1<<14 |
59 #define XML_STREAM_FROM_ROOT 1<<15 | 62 #define XML_STREAM_FROM_ROOT 1<<15 |
60 #define XML_STREAM_DESC 1<<16 | 63 #define XML_STREAM_DESC 1<<16 |
61 | 64 |
62 /* | 65 /* |
63 * XML_STREAM_ANY_NODE is used for comparison against | 66 * XML_STREAM_ANY_NODE is used for comparison against |
64 * xmlElementType enums, to indicate a node of any type. | 67 * xmlElementType enums, to indicate a node of any type. |
65 */ | 68 */ |
66 #define XML_STREAM_ANY_NODE 100 | 69 #define XML_STREAM_ANY_NODE 100 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 struct _xmlStepOp { | 155 struct _xmlStepOp { |
153 xmlPatOp op; | 156 xmlPatOp op; |
154 const xmlChar *value; | 157 const xmlChar *value; |
155 const xmlChar *value2; /* The namespace name */ | 158 const xmlChar *value2; /* The namespace name */ |
156 }; | 159 }; |
157 | 160 |
158 #define PAT_FROM_ROOT (1<<8) | 161 #define PAT_FROM_ROOT (1<<8) |
159 #define PAT_FROM_CUR (1<<9) | 162 #define PAT_FROM_CUR (1<<9) |
160 | 163 |
161 struct _xmlPattern { | 164 struct _xmlPattern { |
162 void *data; » » /* the associated template */ | 165 void *data;»» /* the associated template */ |
163 xmlDictPtr dict; /* the optional dictionary */ | 166 xmlDictPtr dict; /* the optional dictionary */ |
164 struct _xmlPattern *next; /* next pattern if | is used */ | 167 struct _xmlPattern *next; /* next pattern if | is used */ |
165 const xmlChar *pattern; /* the pattern */ | 168 const xmlChar *pattern; /* the pattern */ |
166 int flags; /* flags */ | 169 int flags; /* flags */ |
167 int nbStep; | 170 int nbStep; |
168 int maxStep; | 171 int maxStep; |
169 xmlStepOpPtr steps; /* ops for computation */ | 172 xmlStepOpPtr steps; /* ops for computation */ |
170 xmlStreamCompPtr stream; /* the streaming data if any */ | 173 xmlStreamCompPtr stream; /* the streaming data if any */ |
171 }; | 174 }; |
172 | 175 |
173 typedef struct _xmlPatParserContext xmlPatParserContext; | 176 typedef struct _xmlPatParserContext xmlPatParserContext; |
174 typedef xmlPatParserContext *xmlPatParserContextPtr; | 177 typedef xmlPatParserContext *xmlPatParserContextPtr; |
175 struct _xmlPatParserContext { | 178 struct _xmlPatParserContext { |
176 const xmlChar *cur; /* the current char being parsed */ | 179 const xmlChar *cur; /* the current char being parsed */ |
177 const xmlChar *base; /* the full expression */ | 180 const xmlChar *base; /* the full expression */ |
178 int error; /* error code */ | 181 int error; /* error code */ |
179 xmlDictPtr dict; /* the dictionary if any */ | 182 xmlDictPtr dict; /* the dictionary if any */ |
180 xmlPatternPtr comp; /* the result */ | 183 xmlPatternPtr comp; /* the result */ |
181 xmlNodePtr elem;» » /* the current node if any */ | 184 xmlNodePtr elem;» » /* the current node if any */ |
182 const xmlChar **namespaces; /* the namespaces definitions */ | 185 const xmlChar **namespaces; /* the namespaces definitions */ |
183 int nb_namespaces; /* the number of namespaces */ | 186 int nb_namespaces; /* the number of namespaces */ |
184 }; | 187 }; |
185 | 188 |
186 /************************************************************************ | 189 /************************************************************************ |
187 * » » » » » » » » » * | 190 *» » » » » » » » » * |
188 * » » » Type functions »» » » » * | 191 *» » » Type functions» » » » » * |
189 * » » » » » » » » » * | 192 *» » » » » » » » » * |
190 ************************************************************************/ | 193 ************************************************************************/ |
191 | 194 |
192 /** | 195 /** |
193 * xmlNewPattern: | 196 * xmlNewPattern: |
194 * | 197 * |
195 * Create a new XSLT Pattern | 198 * Create a new XSLT Pattern |
196 * | 199 * |
197 * Returns the newly allocated xmlPatternPtr or NULL in case of error | 200 * Returns the newly allocated xmlPatternPtr or NULL in case of error |
198 */ | 201 */ |
199 static xmlPatternPtr | 202 static xmlPatternPtr |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 ERROR(NULL, NULL, NULL, | 301 ERROR(NULL, NULL, NULL, |
299 "xmlNewPatParserContext : malloc failed\n"); | 302 "xmlNewPatParserContext : malloc failed\n"); |
300 return(NULL); | 303 return(NULL); |
301 } | 304 } |
302 memset(cur, 0, sizeof(xmlPatParserContext)); | 305 memset(cur, 0, sizeof(xmlPatParserContext)); |
303 cur->dict = dict; | 306 cur->dict = dict; |
304 cur->cur = pattern; | 307 cur->cur = pattern; |
305 cur->base = pattern; | 308 cur->base = pattern; |
306 if (namespaces != NULL) { | 309 if (namespaces != NULL) { |
307 int i; | 310 int i; |
308 » for (i = 0;namespaces[2 * i] != NULL;i++); | 311 for (i = 0;namespaces[2 * i] != NULL;i++) |
| 312 ; |
309 cur->nb_namespaces = i; | 313 cur->nb_namespaces = i; |
310 } else { | 314 } else { |
311 cur->nb_namespaces = 0; | 315 cur->nb_namespaces = 0; |
312 } | 316 } |
313 cur->namespaces = namespaces; | 317 cur->namespaces = namespaces; |
314 return(cur); | 318 return(cur); |
315 } | 319 } |
316 | 320 |
317 /** | 321 /** |
318 * xmlFreePatParserContext: | 322 * xmlFreePatParserContext: |
319 * @ctxt: an XSLT parser context | 323 * @ctxt: an XSLT parser context |
320 * | 324 * |
321 * Free up the memory allocated by @ctxt | 325 * Free up the memory allocated by @ctxt |
322 */ | 326 */ |
323 static void | 327 static void |
324 xmlFreePatParserContext(xmlPatParserContextPtr ctxt) { | 328 xmlFreePatParserContext(xmlPatParserContextPtr ctxt) { |
325 if (ctxt == NULL) | 329 if (ctxt == NULL) |
326 » return; | 330 » return; |
327 memset(ctxt, -1, sizeof(xmlPatParserContext)); | 331 memset(ctxt, -1, sizeof(xmlPatParserContext)); |
328 xmlFree(ctxt); | 332 xmlFree(ctxt); |
329 } | 333 } |
330 | 334 |
331 /** | 335 /** |
332 * xmlPatternAdd: | 336 * xmlPatternAdd: |
333 * @comp: the compiled match expression | 337 * @comp: the compiled match expression |
334 * @op: an op | 338 * @op: an op |
335 * @value: the first value | 339 * @value: the first value |
336 * @value2: the second value | 340 * @value2: the second value |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 j--; | 448 j--; |
445 i++; | 449 i++; |
446 } | 450 } |
447 comp->steps[comp->nbStep].value = NULL; | 451 comp->steps[comp->nbStep].value = NULL; |
448 comp->steps[comp->nbStep].value2 = NULL; | 452 comp->steps[comp->nbStep].value2 = NULL; |
449 comp->steps[comp->nbStep++].op = XML_OP_END; | 453 comp->steps[comp->nbStep++].op = XML_OP_END; |
450 return(0); | 454 return(0); |
451 } | 455 } |
452 | 456 |
453 /************************************************************************ | 457 /************************************************************************ |
454 * » » » » » » » » » * | 458 *» » » » » » » » » * |
455 * » » The interpreter for the precompiled patterns» » * | 459 *» » The interpreter for the precompiled patterns» » * |
456 * » » » » » » » » » * | 460 *» » » » » » » » » * |
457 ************************************************************************/ | 461 ************************************************************************/ |
458 | 462 |
459 static int | 463 static int |
460 xmlPatPushState(xmlStepStates *states, int step, xmlNodePtr node) { | 464 xmlPatPushState(xmlStepStates *states, int step, xmlNodePtr node) { |
461 if ((states->states == NULL) || (states->maxstates <= 0)) { | 465 if ((states->states == NULL) || (states->maxstates <= 0)) { |
462 states->maxstates = 4; | 466 states->maxstates = 4; |
463 states->nbstates = 0; | 467 states->nbstates = 0; |
464 states->states = xmlMalloc(4 * sizeof(xmlStepState)); | 468 states->states = xmlMalloc(4 * sizeof(xmlStepState)); |
465 } | 469 } |
466 else if (states->maxstates <= states->nbstates) { | 470 else if (states->maxstates <= states->nbstates) { |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 #endif | 702 #endif |
699 goto restart; | 703 goto restart; |
700 } | 704 } |
701 | 705 |
702 /************************************************************************ | 706 /************************************************************************ |
703 * * | 707 * * |
704 * Dedicated parser for templates * | 708 * Dedicated parser for templates * |
705 * * | 709 * * |
706 ************************************************************************/ | 710 ************************************************************************/ |
707 | 711 |
708 #define TODO » » » » » » » » \ | 712 #define TODO» » » » » » » » \ |
709 xmlGenericError(xmlGenericErrorContext, \ | 713 xmlGenericError(xmlGenericErrorContext, \ |
710 "Unimplemented block at %s:%d\n", \ | 714 "Unimplemented block at %s:%d\n", \ |
711 __FILE__, __LINE__); | 715 __FILE__, __LINE__); |
712 #define CUR (*ctxt->cur) | 716 #define CUR (*ctxt->cur) |
713 #define SKIP(val) ctxt->cur += (val) | 717 #define SKIP(val) ctxt->cur += (val) |
714 #define NXT(val) ctxt->cur[(val)] | 718 #define NXT(val) ctxt->cur[(val)] |
715 #define PEEKPREV(val) ctxt->cur[-(val)] | 719 #define PEEKPREV(val) ctxt->cur[-(val)] |
716 #define CUR_PTR ctxt->cur | 720 #define CUR_PTR ctxt->cur |
717 | 721 |
718 #define SKIP_BLANKS » » » » » » » \ | 722 #define SKIP_BLANKS» » » » » » » \ |
719 while (IS_BLANK_CH(CUR)) NEXT | 723 while (IS_BLANK_CH(CUR)) NEXT |
720 | 724 |
721 #define CURRENT (*ctxt->cur) | 725 #define CURRENT (*ctxt->cur) |
722 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) | 726 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) |
723 | 727 |
724 | 728 |
725 #define PUSH(op, val, val2) » » » » » » \ | 729 #define PUSH(op, val, val2)» » » » » » \ |
726 if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error; | 730 if (xmlPatternAdd(ctxt, ctxt->comp, (op), (val), (val2))) goto error; |
727 | 731 |
728 #define XSLT_ERROR(X) \ | 732 #define XSLT_ERROR(X) \ |
729 { xsltError(ctxt, __FILE__, __LINE__, X); \ | 733 { xsltError(ctxt, __FILE__, __LINE__, X); \ |
730 ctxt->error = (X); return; } | 734 ctxt->error = (X); return; } |
731 | 735 |
732 #define XSLT_ERROR0(X) \ | 736 #define XSLT_ERROR0(X) \ |
733 { xsltError(ctxt, __FILE__, __LINE__, X); \ | 737 { xsltError(ctxt, __FILE__, __LINE__, X); \ |
734 ctxt->error = (X); return(0); } | 738 ctxt->error = (X); return(0); } |
735 | 739 |
(...skipping 25 matching lines...) Expand all Loading... |
761 cur += len; | 765 cur += len; |
762 val = xmlStringCurrentChar(NULL, cur, &len); | 766 val = xmlStringCurrentChar(NULL, cur, &len); |
763 } | 767 } |
764 if (!IS_CHAR(val)) { | 768 if (!IS_CHAR(val)) { |
765 ctxt->error = 1; | 769 ctxt->error = 1; |
766 return(NULL); | 770 return(NULL); |
767 } else { | 771 } else { |
768 if (ctxt->dict) | 772 if (ctxt->dict) |
769 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q); | 773 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q); |
770 else | 774 else |
771 » » ret = xmlStrndup(q, cur - q);» | 775 » » ret = xmlStrndup(q, cur - q); |
772 } | 776 } |
773 cur += len; | 777 cur += len; |
774 CUR_PTR = cur; | 778 CUR_PTR = cur; |
775 } else if (CUR == '\'') { | 779 } else if (CUR == '\'') { |
776 NEXT; | 780 NEXT; |
777 cur = q = CUR_PTR; | 781 cur = q = CUR_PTR; |
778 val = xmlStringCurrentChar(NULL, cur, &len); | 782 val = xmlStringCurrentChar(NULL, cur, &len); |
779 while ((IS_CHAR(val)) && (val != '\'')) { | 783 while ((IS_CHAR(val)) && (val != '\'')) { |
780 cur += len; | 784 cur += len; |
781 val = xmlStringCurrentChar(NULL, cur, &len); | 785 val = xmlStringCurrentChar(NULL, cur, &len); |
782 } | 786 } |
783 if (!IS_CHAR(val)) { | 787 if (!IS_CHAR(val)) { |
784 ctxt->error = 1; | 788 ctxt->error = 1; |
785 return(NULL); | 789 return(NULL); |
786 } else { | 790 } else { |
787 if (ctxt->dict) | 791 if (ctxt->dict) |
788 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q); | 792 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q); |
789 else | 793 else |
790 » » ret = xmlStrndup(q, cur - q);» | 794 » » ret = xmlStrndup(q, cur - q); |
791 } | 795 } |
792 cur += len; | 796 cur += len; |
793 CUR_PTR = cur; | 797 CUR_PTR = cur; |
794 } else { | 798 } else { |
795 /* XP_ERROR(XPATH_START_LITERAL_ERROR); */ | 799 /* XP_ERROR(XPATH_START_LITERAL_ERROR); */ |
796 ctxt->error = 1; | 800 ctxt->error = 1; |
797 return(NULL); | 801 return(NULL); |
798 } | 802 } |
799 return(ret); | 803 return(ret); |
800 } | 804 } |
801 #endif | 805 #endif |
802 | 806 |
803 /** | 807 /** |
804 * xmlPatScanName: | 808 * xmlPatScanName: |
805 * @ctxt: the XPath Parser context | 809 * @ctxt: the XPath Parser context |
806 * | 810 * |
807 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | | 811 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | |
808 * CombiningChar | Extender | 812 * CombiningChar | Extender |
809 * | 813 * |
810 * [5] Name ::= (Letter | '_' | ':') (NameChar)* | 814 * [5] Name ::= (Letter | '_' | ':') (NameChar)* |
811 * | 815 * |
812 * [6] Names ::= Name (S Name)* | 816 * [6] Names ::= Name (S Name)* |
813 * | 817 * |
814 * Returns the Name parsed or NULL | 818 * Returns the Name parsed or NULL |
815 */ | 819 */ |
816 | 820 |
817 static xmlChar * | 821 static xmlChar * |
818 xmlPatScanName(xmlPatParserContextPtr ctxt) { | 822 xmlPatScanName(xmlPatParserContextPtr ctxt) { |
819 const xmlChar *q, *cur; | 823 const xmlChar *q, *cur; |
820 xmlChar *ret = NULL; | 824 xmlChar *ret = NULL; |
821 int val, len; | 825 int val, len; |
822 | 826 |
823 SKIP_BLANKS; | 827 SKIP_BLANKS; |
824 | 828 |
825 cur = q = CUR_PTR; | 829 cur = q = CUR_PTR; |
826 val = xmlStringCurrentChar(NULL, cur, &len); | 830 val = xmlStringCurrentChar(NULL, cur, &len); |
827 if (!IS_LETTER(val) && (val != '_') && (val != ':')) | 831 if (!IS_LETTER(val) && (val != '_') && (val != ':')) |
828 return(NULL); | 832 return(NULL); |
829 | 833 |
830 while ((IS_LETTER(val)) || (IS_DIGIT(val)) || | 834 while ((IS_LETTER(val)) || (IS_DIGIT(val)) || |
831 (val == '.') || (val == '-') || | 835 (val == '.') || (val == '-') || |
832 » (val == '_') || | 836 » (val == '_') || |
833 (IS_COMBINING(val)) || | 837 (IS_COMBINING(val)) || |
834 (IS_EXTENDER(val))) { | 838 (IS_EXTENDER(val))) { |
835 cur += len; | 839 cur += len; |
836 val = xmlStringCurrentChar(NULL, cur, &len); | 840 val = xmlStringCurrentChar(NULL, cur, &len); |
837 } | 841 } |
838 if (ctxt->dict) | 842 if (ctxt->dict) |
839 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q); | 843 ret = (xmlChar *) xmlDictLookup(ctxt->dict, q, cur - q); |
840 else | 844 else |
841 » ret = xmlStrndup(q, cur - q); | 845 » ret = xmlStrndup(q, cur - q); |
842 CUR_PTR = cur; | 846 CUR_PTR = cur; |
843 return(ret); | 847 return(ret); |
844 } | 848 } |
845 | 849 |
846 /** | 850 /** |
847 * xmlPatScanNCName: | 851 * xmlPatScanNCName: |
848 * @ctxt: the XPath Parser context | 852 * @ctxt: the XPath Parser context |
849 * | 853 * |
850 * Parses a non qualified name | 854 * Parses a non qualified name |
851 * | 855 * |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 * xmlCompileAttributeTest: | 915 * xmlCompileAttributeTest: |
912 * @ctxt: the compilation context | 916 * @ctxt: the compilation context |
913 * | 917 * |
914 * Compile an attribute test. | 918 * Compile an attribute test. |
915 */ | 919 */ |
916 static void | 920 static void |
917 xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { | 921 xmlCompileAttributeTest(xmlPatParserContextPtr ctxt) { |
918 xmlChar *token = NULL; | 922 xmlChar *token = NULL; |
919 xmlChar *name = NULL; | 923 xmlChar *name = NULL; |
920 xmlChar *URL = NULL; | 924 xmlChar *URL = NULL; |
921 | 925 |
922 SKIP_BLANKS; | 926 SKIP_BLANKS; |
923 name = xmlPatScanNCName(ctxt); | 927 name = xmlPatScanNCName(ctxt); |
924 if (name == NULL) { | 928 if (name == NULL) { |
925 if (CUR == '*') { | 929 if (CUR == '*') { |
926 PUSH(XML_OP_ATTR, NULL, NULL); | 930 PUSH(XML_OP_ATTR, NULL, NULL); |
927 NEXT; | 931 NEXT; |
928 } else { | 932 } else { |
929 ERROR(NULL, NULL, NULL, | 933 ERROR(NULL, NULL, NULL, |
930 "xmlCompileAttributeTest : Name expected\n"); | 934 "xmlCompileAttributeTest : Name expected\n"); |
931 ctxt->error = 1; | 935 ctxt->error = 1; |
932 } | 936 } |
933 return; | 937 return; |
934 } | 938 } |
935 if (CUR == ':') { | 939 if (CUR == ':') { |
936 int i; | 940 int i; |
937 xmlChar *prefix = name; | 941 xmlChar *prefix = name; |
938 » | 942 |
939 NEXT; | 943 NEXT; |
940 | 944 |
941 » if (IS_BLANK_CH(CUR)) {» | 945 » if (IS_BLANK_CH(CUR)) { |
942 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); | 946 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); |
943 XML_PAT_FREE_STRING(ctxt, prefix); | 947 XML_PAT_FREE_STRING(ctxt, prefix); |
944 ctxt->error = 1; | 948 ctxt->error = 1; |
945 goto error; | 949 goto error; |
946 } | 950 } |
947 /* | 951 /* |
948 * This is a namespace match | 952 * This is a namespace match |
949 */ | 953 */ |
950 token = xmlPatScanName(ctxt); | 954 token = xmlPatScanName(ctxt); |
951 if ((prefix[0] == 'x') && | 955 if ((prefix[0] == 'x') && |
952 (prefix[1] == 'm') && | 956 (prefix[1] == 'm') && |
953 (prefix[2] == 'l') && | 957 (prefix[2] == 'l') && |
954 (prefix[3] == 0)) | 958 (prefix[3] == 0)) |
955 { | 959 { |
956 » XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE);» | 960 » XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE); |
957 } else { | 961 } else { |
958 for (i = 0;i < ctxt->nb_namespaces;i++) { | 962 for (i = 0;i < ctxt->nb_namespaces;i++) { |
959 if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) { | 963 if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)) { |
960 » » XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i])»
» | 964 » » XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[2 * i]) |
961 break; | 965 break; |
962 } | 966 } |
963 } | 967 } |
964 if (i >= ctxt->nb_namespaces) { | 968 if (i >= ctxt->nb_namespaces) { |
965 ERROR5(NULL, NULL, NULL, | 969 ERROR5(NULL, NULL, NULL, |
966 "xmlCompileAttributeTest : no namespace bound to prefix %s\n
", | 970 "xmlCompileAttributeTest : no namespace bound to prefix %s\n
", |
967 prefix); | 971 prefix); |
968 » » ctxt->error = 1;» | 972 » » ctxt->error = 1; |
969 goto error; | 973 goto error; |
970 } | 974 } |
971 } | 975 } |
972 XML_PAT_FREE_STRING(ctxt, prefix); | 976 XML_PAT_FREE_STRING(ctxt, prefix); |
973 if (token == NULL) { | 977 if (token == NULL) { |
974 if (CUR == '*') { | 978 if (CUR == '*') { |
975 NEXT; | 979 NEXT; |
976 PUSH(XML_OP_ATTR, NULL, URL); | 980 PUSH(XML_OP_ATTR, NULL, URL); |
977 } else { | 981 } else { |
978 ERROR(NULL, NULL, NULL, | 982 ERROR(NULL, NULL, NULL, |
979 "xmlCompileAttributeTest : Name expected\n"); | 983 "xmlCompileAttributeTest : Name expected\n"); |
980 ctxt->error = 1; | 984 ctxt->error = 1; |
981 goto error; | 985 goto error; |
982 » }» | 986 » } |
983 } else { | 987 } else { |
984 PUSH(XML_OP_ATTR, token, URL); | 988 PUSH(XML_OP_ATTR, token, URL); |
985 } | 989 } |
986 } else { | 990 } else { |
987 PUSH(XML_OP_ATTR, name, NULL); | 991 PUSH(XML_OP_ATTR, name, NULL); |
988 } | 992 } |
989 return; | 993 return; |
990 error: | 994 error: |
991 if (URL != NULL) | 995 if (URL != NULL) |
992 » XML_PAT_FREE_STRING(ctxt, URL)» | 996 » XML_PAT_FREE_STRING(ctxt, URL) |
993 if (token != NULL) | 997 if (token != NULL) |
994 XML_PAT_FREE_STRING(ctxt, token); | 998 XML_PAT_FREE_STRING(ctxt, token); |
995 } | 999 } |
996 | 1000 |
997 /** | 1001 /** |
998 * xmlCompileStepPattern: | 1002 * xmlCompileStepPattern: |
999 * @ctxt: the compilation context | 1003 * @ctxt: the compilation context |
1000 * | 1004 * |
1001 * Compile the Step Pattern and generates a precompiled | 1005 * Compile the Step Pattern and generates a precompiled |
1002 * form suitable for fast matching. | 1006 * form suitable for fast matching. |
1003 * | 1007 * |
1004 * [3] Step ::= '.' | NameTest | 1008 * [3] Step ::= '.' | NameTest |
1005 * [4] NameTest ::= QName | '*' | NCName ':' '*' | 1009 * [4] NameTest ::= QName | '*' | NCName ':' '*' |
1006 */ | 1010 */ |
1007 | 1011 |
1008 static void | 1012 static void |
1009 xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { | 1013 xmlCompileStepPattern(xmlPatParserContextPtr ctxt) { |
1010 xmlChar *token = NULL; | 1014 xmlChar *token = NULL; |
1011 xmlChar *name = NULL; | 1015 xmlChar *name = NULL; |
1012 xmlChar *URL = NULL; | 1016 xmlChar *URL = NULL; |
1013 int hasBlanks = 0; | 1017 int hasBlanks = 0; |
1014 | 1018 |
1015 SKIP_BLANKS; | 1019 SKIP_BLANKS; |
(...skipping 10 matching lines...) Expand all Loading... |
1026 * Attribute test. | 1030 * Attribute test. |
1027 */ | 1031 */ |
1028 if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) { | 1032 if (XML_STREAM_XS_IDC_SEL(ctxt->comp)) { |
1029 ERROR5(NULL, NULL, NULL, | 1033 ERROR5(NULL, NULL, NULL, |
1030 "Unexpected attribute axis in '%s'.\n", ctxt->base); | 1034 "Unexpected attribute axis in '%s'.\n", ctxt->base); |
1031 ctxt->error = 1; | 1035 ctxt->error = 1; |
1032 return; | 1036 return; |
1033 } | 1037 } |
1034 NEXT; | 1038 NEXT; |
1035 xmlCompileAttributeTest(ctxt); | 1039 xmlCompileAttributeTest(ctxt); |
1036 » if (ctxt->error != 0) | 1040 » if (ctxt->error != 0) |
1037 goto error; | 1041 goto error; |
1038 return; | 1042 return; |
1039 } | 1043 } |
1040 name = xmlPatScanNCName(ctxt); | 1044 name = xmlPatScanNCName(ctxt); |
1041 if (name == NULL) { | 1045 if (name == NULL) { |
1042 if (CUR == '*') { | 1046 if (CUR == '*') { |
1043 NEXT; | 1047 NEXT; |
1044 PUSH(XML_OP_ALL, NULL, NULL); | 1048 PUSH(XML_OP_ALL, NULL, NULL); |
1045 return; | 1049 return; |
1046 } else { | 1050 } else { |
1047 ERROR(NULL, NULL, NULL, | 1051 ERROR(NULL, NULL, NULL, |
1048 "xmlCompileStepPattern : Name expected\n"); | 1052 "xmlCompileStepPattern : Name expected\n"); |
1049 ctxt->error = 1; | 1053 ctxt->error = 1; |
1050 return; | 1054 return; |
1051 } | 1055 } |
1052 } | 1056 } |
1053 if (IS_BLANK_CH(CUR)) { | 1057 if (IS_BLANK_CH(CUR)) { |
1054 hasBlanks = 1; | 1058 hasBlanks = 1; |
1055 SKIP_BLANKS; | 1059 SKIP_BLANKS; |
1056 } | 1060 } |
1057 if (CUR == ':') { | 1061 if (CUR == ':') { |
1058 NEXT; | 1062 NEXT; |
1059 if (CUR != ':') { | 1063 if (CUR != ':') { |
1060 xmlChar *prefix = name; | 1064 xmlChar *prefix = name; |
1061 » int i;» | 1065 » int i; |
1062 | 1066 |
1063 if (hasBlanks || IS_BLANK_CH(CUR)) { | 1067 if (hasBlanks || IS_BLANK_CH(CUR)) { |
1064 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); | 1068 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); |
1065 ctxt->error = 1; | 1069 ctxt->error = 1; |
1066 goto error; | 1070 goto error; |
1067 } | 1071 } |
1068 /* | 1072 /* |
1069 * This is a namespace match | 1073 * This is a namespace match |
1070 */ | 1074 */ |
1071 token = xmlPatScanName(ctxt); | 1075 token = xmlPatScanName(ctxt); |
(...skipping 28 matching lines...) Expand all Loading... |
1100 ERROR(NULL, NULL, NULL, | 1104 ERROR(NULL, NULL, NULL, |
1101 "xmlCompileStepPattern : Name expected\n"); | 1105 "xmlCompileStepPattern : Name expected\n"); |
1102 ctxt->error = 1; | 1106 ctxt->error = 1; |
1103 goto error; | 1107 goto error; |
1104 } | 1108 } |
1105 } else { | 1109 } else { |
1106 PUSH(XML_OP_ELEM, token, URL); | 1110 PUSH(XML_OP_ELEM, token, URL); |
1107 } | 1111 } |
1108 } else { | 1112 } else { |
1109 NEXT; | 1113 NEXT; |
1110 » if (xmlStrEqual(name, (const xmlChar *) "child")) {»» | 1114 » if (xmlStrEqual(name, (const xmlChar *) "child")) { |
1111 XML_PAT_FREE_STRING(ctxt, name); | 1115 XML_PAT_FREE_STRING(ctxt, name); |
1112 name = xmlPatScanName(ctxt); | 1116 name = xmlPatScanName(ctxt); |
1113 if (name == NULL) { | 1117 if (name == NULL) { |
1114 if (CUR == '*') { | 1118 if (CUR == '*') { |
1115 NEXT; | 1119 NEXT; |
1116 PUSH(XML_OP_ALL, NULL, NULL); | 1120 PUSH(XML_OP_ALL, NULL, NULL); |
1117 return; | 1121 return; |
1118 } else { | 1122 } else { |
1119 ERROR(NULL, NULL, NULL, | 1123 ERROR(NULL, NULL, NULL, |
1120 "xmlCompileStepPattern : QName expected\n"); | 1124 "xmlCompileStepPattern : QName expected\n"); |
1121 ctxt->error = 1; | 1125 ctxt->error = 1; |
1122 goto error; | 1126 goto error; |
1123 } | 1127 } |
1124 } | 1128 } |
1125 if (CUR == ':') { | 1129 if (CUR == ':') { |
1126 xmlChar *prefix = name; | 1130 xmlChar *prefix = name; |
1127 int i; | 1131 int i; |
1128 » » | 1132 |
1129 NEXT; | 1133 NEXT; |
1130 if (IS_BLANK_CH(CUR)) { | 1134 if (IS_BLANK_CH(CUR)) { |
1131 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); | 1135 ERROR5(NULL, NULL, NULL, "Invalid QName.\n", NULL); |
1132 ctxt->error = 1; | 1136 ctxt->error = 1; |
1133 goto error; | 1137 goto error; |
1134 } | 1138 } |
1135 /* | 1139 /* |
1136 * This is a namespace match | 1140 * This is a namespace match |
1137 */ | 1141 */ |
1138 token = xmlPatScanName(ctxt); | 1142 token = xmlPatScanName(ctxt); |
1139 if ((prefix[0] == 'x') && | 1143 if ((prefix[0] == 'x') && |
1140 (prefix[1] == 'm') && | 1144 (prefix[1] == 'm') && |
1141 (prefix[2] == 'l') && | 1145 (prefix[2] == 'l') && |
1142 (prefix[3] == 0)) | 1146 (prefix[3] == 0)) |
1143 { | 1147 { |
1144 » » » XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE)»
» » | 1148 » » » XML_PAT_COPY_NSNAME(ctxt, URL, XML_XML_NAMESPACE) |
1145 } else { | 1149 } else { |
1146 for (i = 0;i < ctxt->nb_namespaces;i++) { | 1150 for (i = 0;i < ctxt->nb_namespaces;i++) { |
1147 if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)
) { | 1151 if (xmlStrEqual(ctxt->namespaces[2 * i + 1], prefix)
) { |
1148 » » » » XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[
2 * i])»» » » | 1152 » » » » XML_PAT_COPY_NSNAME(ctxt, URL, ctxt->namespaces[
2 * i]) |
1149 break; | 1153 break; |
1150 } | 1154 } |
1151 } | 1155 } |
1152 if (i >= ctxt->nb_namespaces) { | 1156 if (i >= ctxt->nb_namespaces) { |
1153 ERROR5(NULL, NULL, NULL, | 1157 ERROR5(NULL, NULL, NULL, |
1154 "xmlCompileStepPattern : no namespace bound " | 1158 "xmlCompileStepPattern : no namespace bound " |
1155 "to prefix %s\n", prefix); | 1159 "to prefix %s\n", prefix); |
1156 ctxt->error = 1; | 1160 ctxt->error = 1; |
1157 goto error; | 1161 goto error; |
1158 } | 1162 } |
(...skipping 27 matching lines...) Expand all Loading... |
1186 } | 1190 } |
1187 xmlCompileAttributeTest(ctxt); | 1191 xmlCompileAttributeTest(ctxt); |
1188 if (ctxt->error != 0) | 1192 if (ctxt->error != 0) |
1189 goto error; | 1193 goto error; |
1190 return; | 1194 return; |
1191 } else { | 1195 } else { |
1192 ERROR5(NULL, NULL, NULL, | 1196 ERROR5(NULL, NULL, NULL, |
1193 "The 'element' or 'attribute' axis is expected.\n", NULL); | 1197 "The 'element' or 'attribute' axis is expected.\n", NULL); |
1194 ctxt->error = 1; | 1198 ctxt->error = 1; |
1195 goto error; | 1199 goto error; |
1196 » }» | 1200 » } |
1197 } | 1201 } |
1198 } else if (CUR == '*') { | 1202 } else if (CUR == '*') { |
1199 if (name != NULL) { | 1203 if (name != NULL) { |
1200 ctxt->error = 1; | 1204 ctxt->error = 1; |
1201 goto error; | 1205 goto error; |
1202 } | 1206 } |
1203 NEXT; | 1207 NEXT; |
1204 PUSH(XML_OP_ALL, token, NULL); | 1208 PUSH(XML_OP_ALL, token, NULL); |
1205 } else { | 1209 } else { |
1206 PUSH(XML_OP_ELEM, name, NULL); | 1210 PUSH(XML_OP_ELEM, name, NULL); |
1207 } | 1211 } |
1208 return; | 1212 return; |
1209 error: | 1213 error: |
1210 if (URL != NULL) | 1214 if (URL != NULL) |
1211 » XML_PAT_FREE_STRING(ctxt, URL)» | 1215 » XML_PAT_FREE_STRING(ctxt, URL) |
1212 if (token != NULL) | 1216 if (token != NULL) |
1213 XML_PAT_FREE_STRING(ctxt, token) | 1217 XML_PAT_FREE_STRING(ctxt, token) |
1214 if (name != NULL) | 1218 if (name != NULL) |
1215 XML_PAT_FREE_STRING(ctxt, name) | 1219 XML_PAT_FREE_STRING(ctxt, name) |
1216 } | 1220 } |
1217 | 1221 |
1218 /** | 1222 /** |
1219 * xmlCompilePathPattern: | 1223 * xmlCompilePathPattern: |
1220 * @ctxt: the compilation context | 1224 * @ctxt: the compilation context |
1221 * | 1225 * |
1222 * Compile the Path Pattern and generates a precompiled | 1226 * Compile the Path Pattern and generates a precompiled |
1223 * form suitable for fast matching. | 1227 * form suitable for fast matching. |
1224 * | 1228 * |
1225 * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) | 1229 * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) |
1226 */ | 1230 */ |
1227 static void | 1231 static void |
1228 xmlCompilePathPattern(xmlPatParserContextPtr ctxt) { | 1232 xmlCompilePathPattern(xmlPatParserContextPtr ctxt) { |
1229 SKIP_BLANKS; | 1233 SKIP_BLANKS; |
1230 if (CUR == '/') { | 1234 if (CUR == '/') { |
1231 ctxt->comp->flags |= PAT_FROM_ROOT; | 1235 ctxt->comp->flags |= PAT_FROM_ROOT; |
1232 } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) { | 1236 } else if ((CUR == '.') || (ctxt->comp->flags & XML_PATTERN_NOTPATTERN)) { |
1233 ctxt->comp->flags |= PAT_FROM_CUR; | 1237 ctxt->comp->flags |= PAT_FROM_CUR; |
1234 } | 1238 } |
1235 » | 1239 |
1236 if ((CUR == '/') && (NXT(1) == '/')) { | 1240 if ((CUR == '/') && (NXT(1) == '/')) { |
1237 PUSH(XML_OP_ANCESTOR, NULL, NULL); | 1241 PUSH(XML_OP_ANCESTOR, NULL, NULL); |
1238 NEXT; | 1242 NEXT; |
1239 NEXT; | 1243 NEXT; |
1240 } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) { | 1244 } else if ((CUR == '.') && (NXT(1) == '/') && (NXT(2) == '/')) { |
1241 PUSH(XML_OP_ANCESTOR, NULL, NULL); | 1245 PUSH(XML_OP_ANCESTOR, NULL, NULL); |
1242 NEXT; | 1246 NEXT; |
1243 NEXT; | 1247 NEXT; |
1244 NEXT; | 1248 NEXT; |
1245 /* Check for incompleteness. */ | 1249 /* Check for incompleteness. */ |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1288 if (ctxt->error != 0) | 1292 if (ctxt->error != 0) |
1289 goto error; | 1293 goto error; |
1290 } else { | 1294 } else { |
1291 PUSH(XML_OP_PARENT, NULL, NULL); | 1295 PUSH(XML_OP_PARENT, NULL, NULL); |
1292 NEXT; | 1296 NEXT; |
1293 SKIP_BLANKS; | 1297 SKIP_BLANKS; |
1294 if (CUR == 0) { | 1298 if (CUR == 0) { |
1295 ERROR5(NULL, NULL, NULL, | 1299 ERROR5(NULL, NULL, NULL, |
1296 "Incomplete expression '%s'.\n", ctxt->base); | 1300 "Incomplete expression '%s'.\n", ctxt->base); |
1297 ctxt->error = 1; | 1301 ctxt->error = 1; |
1298 » » goto error;»» | 1302 » » goto error; |
1299 } | 1303 } |
1300 xmlCompileStepPattern(ctxt); | 1304 xmlCompileStepPattern(ctxt); |
1301 if (ctxt->error != 0) | 1305 if (ctxt->error != 0) |
1302 goto error; | 1306 goto error; |
1303 } | 1307 } |
1304 } | 1308 } |
1305 } | 1309 } |
1306 if (CUR != 0) { | 1310 if (CUR != 0) { |
1307 ERROR5(NULL, NULL, NULL, | 1311 ERROR5(NULL, NULL, NULL, |
1308 "Failed to compile pattern %s\n", ctxt->base); | 1312 "Failed to compile pattern %s\n", ctxt->base); |
1309 ctxt->error = 1; | 1313 ctxt->error = 1; |
1310 } | 1314 } |
1311 error: | 1315 error: |
1312 return; | 1316 return; |
1313 } | 1317 } |
1314 | 1318 |
1315 /** | 1319 /** |
1316 * xmlCompileIDCXPathPath: | 1320 * xmlCompileIDCXPathPath: |
1317 * @ctxt: the compilation context | 1321 * @ctxt: the compilation context |
1318 * | 1322 * |
1319 * Compile the Path Pattern and generates a precompiled | 1323 * Compile the Path Pattern and generates a precompiled |
1320 * form suitable for fast matching. | 1324 * form suitable for fast matching. |
1321 * | 1325 * |
1322 * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) | 1326 * [5] Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) |
1323 */ | 1327 */ |
1324 static void | 1328 static void |
1325 xmlCompileIDCXPathPath(xmlPatParserContextPtr ctxt) { | 1329 xmlCompileIDCXPathPath(xmlPatParserContextPtr ctxt) { |
1326 SKIP_BLANKS; | 1330 SKIP_BLANKS; |
1327 if (CUR == '/') { | 1331 if (CUR == '/') { |
1328 ERROR5(NULL, NULL, NULL, | 1332 ERROR5(NULL, NULL, NULL, |
1329 "Unexpected selection of the document root in '%s'.\n", | 1333 "Unexpected selection of the document root in '%s'.\n", |
1330 ctxt->base); | 1334 ctxt->base); |
1331 goto error; | 1335 goto error; |
1332 } | 1336 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1367 SKIP_BLANKS; | 1371 SKIP_BLANKS; |
1368 } | 1372 } |
1369 if (CUR == 0) | 1373 if (CUR == 0) |
1370 goto error_unfinished; | 1374 goto error_unfinished; |
1371 } | 1375 } |
1372 /* | 1376 /* |
1373 * Process steps. | 1377 * Process steps. |
1374 */ | 1378 */ |
1375 do { | 1379 do { |
1376 xmlCompileStepPattern(ctxt); | 1380 xmlCompileStepPattern(ctxt); |
1377 » if (ctxt->error != 0) | 1381 » if (ctxt->error != 0) |
1378 goto error; | 1382 goto error; |
1379 SKIP_BLANKS; | 1383 SKIP_BLANKS; |
1380 if (CUR != '/') | 1384 if (CUR != '/') |
1381 break; | 1385 break; |
1382 PUSH(XML_OP_PARENT, NULL, NULL); | 1386 PUSH(XML_OP_PARENT, NULL, NULL); |
1383 NEXT; | 1387 NEXT; |
1384 SKIP_BLANKS; | 1388 SKIP_BLANKS; |
1385 if (CUR == '/') { | 1389 if (CUR == '/') { |
1386 /* | 1390 /* |
1387 * Disallow subsequent '//'. | 1391 * Disallow subsequent '//'. |
1388 */ | 1392 */ |
1389 ERROR5(NULL, NULL, NULL, | 1393 ERROR5(NULL, NULL, NULL, |
1390 "Unexpected subsequent '//' in '%s'.\n", | 1394 "Unexpected subsequent '//' in '%s'.\n", |
1391 ctxt->base); | 1395 ctxt->base); |
1392 goto error; | 1396 goto error; |
1393 } | 1397 } |
1394 if (CUR == 0) | 1398 if (CUR == 0) |
1395 goto error_unfinished; | 1399 goto error_unfinished; |
1396 » | 1400 |
1397 } while (CUR != 0); | 1401 } while (CUR != 0); |
1398 | 1402 |
1399 if (CUR != 0) { | 1403 if (CUR != 0) { |
1400 ERROR5(NULL, NULL, NULL, | 1404 ERROR5(NULL, NULL, NULL, |
1401 "Failed to compile expression '%s'.\n", ctxt->base); | 1405 "Failed to compile expression '%s'.\n", ctxt->base); |
1402 ctxt->error = 1; | 1406 ctxt->error = 1; |
1403 } | 1407 } |
1404 return; | 1408 return; |
1405 error: | 1409 error: |
1406 ctxt->error = 1; | 1410 ctxt->error = 1; |
1407 return; | 1411 return; |
1408 | 1412 |
1409 error_unfinished: | 1413 error_unfinished: |
1410 ctxt->error = 1; | 1414 ctxt->error = 1; |
1411 ERROR5(NULL, NULL, NULL, | 1415 ERROR5(NULL, NULL, NULL, |
1412 » "Unfinished expression '%s'.\n", ctxt->base); | 1416 » "Unfinished expression '%s'.\n", ctxt->base); |
1413 return; | 1417 return; |
1414 } | 1418 } |
1415 | 1419 |
1416 /************************************************************************ | 1420 /************************************************************************ |
1417 * * | 1421 * * |
1418 * The streaming code * | 1422 * The streaming code * |
1419 * * | 1423 * * |
1420 ************************************************************************/ | 1424 ************************************************************************/ |
1421 | 1425 |
1422 #ifdef DEBUG_STREAMING | 1426 #ifdef DEBUG_STREAMING |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 cur->flags = flags; | 1561 cur->flags = flags; |
1558 cur->name = name; | 1562 cur->name = name; |
1559 cur->ns = ns; | 1563 cur->ns = ns; |
1560 cur->nodeType = nodeType; | 1564 cur->nodeType = nodeType; |
1561 return(comp->nbStep - 1); | 1565 return(comp->nbStep - 1); |
1562 } | 1566 } |
1563 | 1567 |
1564 /** | 1568 /** |
1565 * xmlStreamCompile: | 1569 * xmlStreamCompile: |
1566 * @comp: the precompiled pattern | 1570 * @comp: the precompiled pattern |
1567 * | 1571 * |
1568 * Tries to stream compile a pattern | 1572 * Tries to stream compile a pattern |
1569 * | 1573 * |
1570 * Returns -1 in case of failure and 0 in case of success. | 1574 * Returns -1 in case of failure and 0 in case of success. |
1571 */ | 1575 */ |
1572 static int | 1576 static int |
1573 xmlStreamCompile(xmlPatternPtr comp) { | 1577 xmlStreamCompile(xmlPatternPtr comp) { |
1574 xmlStreamCompPtr stream; | 1578 xmlStreamCompPtr stream; |
1575 int i, s = 0, root = 0, flags = 0, prevs = -1; | 1579 int i, s = 0, root = 0, flags = 0, prevs = -1; |
1576 xmlStepOp step; | 1580 xmlStepOp step; |
1577 | 1581 |
(...skipping 16 matching lines...) Expand all Loading... |
1594 } | 1598 } |
1595 | 1599 |
1596 stream = xmlNewStreamComp((comp->nbStep / 2) + 1); | 1600 stream = xmlNewStreamComp((comp->nbStep / 2) + 1); |
1597 if (stream == NULL) | 1601 if (stream == NULL) |
1598 return(-1); | 1602 return(-1); |
1599 if (comp->dict != NULL) { | 1603 if (comp->dict != NULL) { |
1600 stream->dict = comp->dict; | 1604 stream->dict = comp->dict; |
1601 xmlDictReference(stream->dict); | 1605 xmlDictReference(stream->dict); |
1602 } | 1606 } |
1603 | 1607 |
1604 i = 0; | 1608 i = 0; |
1605 if (comp->flags & PAT_FROM_ROOT) | 1609 if (comp->flags & PAT_FROM_ROOT) |
1606 stream->flags |= XML_STREAM_FROM_ROOT; | 1610 stream->flags |= XML_STREAM_FROM_ROOT; |
1607 | 1611 |
1608 for (;i < comp->nbStep;i++) { | 1612 for (;i < comp->nbStep;i++) { |
1609 step = comp->steps[i]; | 1613 step = comp->steps[i]; |
1610 switch (step.op) { | 1614 switch (step.op) { |
1611 case XML_OP_END: | 1615 case XML_OP_END: |
1612 break; | 1616 break; |
1613 case XML_OP_ROOT: | 1617 case XML_OP_ROOT: |
1614 if (i != 0) | 1618 if (i != 0) |
1615 goto error; | 1619 goto error; |
1616 root = 1; | 1620 root = 1; |
1617 break; | 1621 break; |
1618 case XML_OP_NS: | 1622 case XML_OP_NS: |
1619 s = xmlStreamCompAddStep(stream, NULL, step.value, | 1623 s = xmlStreamCompAddStep(stream, NULL, step.value, |
1620 » » XML_ELEMENT_NODE, flags);» » | 1624 » » XML_ELEMENT_NODE, flags); |
1621 if (s < 0) | 1625 if (s < 0) |
1622 goto error; | 1626 goto error; |
1623 prevs = s; | 1627 prevs = s; |
1624 » » flags = 0;» » | 1628 » » flags = 0; |
1625 » » break;» | 1629 » » break; |
1626 case XML_OP_ATTR: | 1630 case XML_OP_ATTR: |
1627 flags |= XML_STREAM_STEP_ATTR; | 1631 flags |= XML_STREAM_STEP_ATTR; |
1628 prevs = -1; | 1632 prevs = -1; |
1629 s = xmlStreamCompAddStep(stream, | 1633 s = xmlStreamCompAddStep(stream, |
1630 step.value, step.value2, XML_ATTRIBUTE_NODE, flags); | 1634 step.value, step.value2, XML_ATTRIBUTE_NODE, flags); |
1631 flags = 0; | 1635 flags = 0; |
1632 if (s < 0) | 1636 if (s < 0) |
1633 goto error; | 1637 goto error; |
1634 break; | 1638 break; |
1635 » case XML_OP_ELEM:» » | 1639 » case XML_OP_ELEM: |
1636 if ((step.value == NULL) && (step.value2 == NULL)) { | 1640 if ((step.value == NULL) && (step.value2 == NULL)) { |
1637 /* | 1641 /* |
1638 * We have a "." or "self::node()" here. | 1642 * We have a "." or "self::node()" here. |
1639 * Eliminate redundant self::node() tests like in "/./." | 1643 * Eliminate redundant self::node() tests like in "/./." |
1640 * or "//./" | 1644 * or "//./" |
1641 * The only case we won't eliminate is "//.", i.e. if | 1645 * The only case we won't eliminate is "//.", i.e. if |
1642 * self::node() is the last node test and we had | 1646 * self::node() is the last node test and we had |
1643 * continuation somewhere beforehand. | 1647 * continuation somewhere beforehand. |
1644 */ | 1648 */ |
1645 if ((comp->nbStep == i + 1) && | 1649 if ((comp->nbStep == i + 1) && |
1646 (flags & XML_STREAM_STEP_DESC)) { | 1650 (flags & XML_STREAM_STEP_DESC)) { |
1647 /* | 1651 /* |
1648 * Mark the special case where the expression resolves | 1652 * Mark the special case where the expression resolves |
1649 * to any type of node. | 1653 * to any type of node. |
1650 */ | 1654 */ |
1651 if (comp->nbStep == i + 1) { | 1655 if (comp->nbStep == i + 1) { |
1652 stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE; | 1656 stream->flags |= XML_STREAM_FINAL_IS_ANY_NODE; |
1653 } | 1657 } |
1654 » » » flags |= XML_STREAM_STEP_NODE;» » » | 1658 » » » flags |= XML_STREAM_STEP_NODE; |
1655 s = xmlStreamCompAddStep(stream, NULL, NULL, | 1659 s = xmlStreamCompAddStep(stream, NULL, NULL, |
1656 XML_STREAM_ANY_NODE, flags); | 1660 XML_STREAM_ANY_NODE, flags); |
1657 if (s < 0) | 1661 if (s < 0) |
1658 goto error; | 1662 goto error; |
1659 flags = 0; | 1663 flags = 0; |
1660 /* | 1664 /* |
1661 * If there was a previous step, mark it to be added to | 1665 * If there was a previous step, mark it to be added to |
1662 * the result node-set; this is needed since only | 1666 * the result node-set; this is needed since only |
1663 * the last step will be marked as "final" and only | 1667 * the last step will be marked as "final" and only |
1664 * "final" nodes are added to the resulting set. | 1668 * "final" nodes are added to the resulting set. |
1665 */ | 1669 */ |
1666 if (prevs != -1) { | 1670 if (prevs != -1) { |
1667 stream->steps[prevs].flags |= XML_STREAM_STEP_IN_SET
; | 1671 stream->steps[prevs].flags |= XML_STREAM_STEP_IN_SET
; |
1668 prevs = -1; | 1672 prevs = -1; |
1669 } | 1673 } |
1670 » » » break;» | 1674 » » » break; |
1671 | 1675 |
1672 } else { | 1676 } else { |
1673 /* Just skip this one. */ | 1677 /* Just skip this one. */ |
1674 continue; | 1678 continue; |
1675 } | 1679 } |
1676 } | 1680 } |
1677 » » /* An element node. */» » | 1681 » » /* An element node. */ |
1678 s = xmlStreamCompAddStep(stream, step.value, step.value2, | 1682 s = xmlStreamCompAddStep(stream, step.value, step.value2, |
1679 » » XML_ELEMENT_NODE, flags);» » | 1683 » » XML_ELEMENT_NODE, flags); |
1680 » » if (s < 0) | |
1681 » » goto error; | |
1682 » » prevs = s; | |
1683 » » flags = 0;» » | |
1684 » » break;» » | |
1685 » case XML_OP_CHILD: | |
1686 » » /* An element node child. */ | |
1687 » s = xmlStreamCompAddStep(stream, step.value, step.value2, | |
1688 » » XML_ELEMENT_NODE, flags);» » | |
1689 » » if (s < 0) | |
1690 » » goto error; | |
1691 » » prevs = s; | |
1692 » » flags = 0; | |
1693 » » break;» | |
1694 » case XML_OP_ALL: | |
1695 » s = xmlStreamCompAddStep(stream, NULL, NULL, | |
1696 » » XML_ELEMENT_NODE, flags);» » | |
1697 if (s < 0) | 1684 if (s < 0) |
1698 goto error; | 1685 goto error; |
1699 prevs = s; | 1686 prevs = s; |
1700 flags = 0; | 1687 flags = 0; |
1701 break; | 1688 break; |
1702 » case XML_OP_PARENT:» | 1689 » case XML_OP_CHILD: |
| 1690 » » /* An element node child. */ |
| 1691 » s = xmlStreamCompAddStep(stream, step.value, step.value2, |
| 1692 » » XML_ELEMENT_NODE, flags); |
| 1693 » » if (s < 0) |
| 1694 » » goto error; |
| 1695 » » prevs = s; |
| 1696 » » flags = 0; |
| 1697 » » break; |
| 1698 » case XML_OP_ALL: |
| 1699 » s = xmlStreamCompAddStep(stream, NULL, NULL, |
| 1700 » » XML_ELEMENT_NODE, flags); |
| 1701 » » if (s < 0) |
| 1702 » » goto error; |
| 1703 » » prevs = s; |
| 1704 » » flags = 0; |
| 1705 » » break; |
| 1706 » case XML_OP_PARENT: |
1703 break; | 1707 break; |
1704 case XML_OP_ANCESTOR: | 1708 case XML_OP_ANCESTOR: |
1705 /* Skip redundant continuations. */ | 1709 /* Skip redundant continuations. */ |
1706 if (flags & XML_STREAM_STEP_DESC) | 1710 if (flags & XML_STREAM_STEP_DESC) |
1707 break; | 1711 break; |
1708 flags |= XML_STREAM_STEP_DESC; | 1712 flags |= XML_STREAM_STEP_DESC; |
1709 /* | 1713 /* |
1710 * Mark the expression as having "//". | 1714 * Mark the expression as having "//". |
1711 */ | 1715 */ |
1712 if ((stream->flags & XML_STREAM_DESC) == 0) | 1716 if ((stream->flags & XML_STREAM_DESC) == 0) |
1713 stream->flags |= XML_STREAM_DESC; | 1717 stream->flags |= XML_STREAM_DESC; |
1714 break; | 1718 break; |
1715 } | 1719 } |
1716 } | 1720 } |
1717 if ((! root) && (comp->flags & XML_PATTERN_NOTPATTERN) == 0) { | 1721 if ((! root) && (comp->flags & XML_PATTERN_NOTPATTERN) == 0) { |
1718 /* | 1722 /* |
1719 * If this should behave like a real pattern, we will mark | 1723 * If this should behave like a real pattern, we will mark |
1720 * the first step as having "//", to be reentrant on every | 1724 * the first step as having "//", to be reentrant on every |
1721 * tree level. | 1725 * tree level. |
1722 */ | 1726 */ |
1723 if ((stream->flags & XML_STREAM_DESC) == 0) | 1727 if ((stream->flags & XML_STREAM_DESC) == 0) |
1724 stream->flags |= XML_STREAM_DESC; | 1728 stream->flags |= XML_STREAM_DESC; |
1725 | 1729 |
1726 if (stream->nbStep > 0) { | 1730 if (stream->nbStep > 0) { |
1727 if ((stream->steps[0].flags & XML_STREAM_STEP_DESC) == 0) | 1731 if ((stream->steps[0].flags & XML_STREAM_STEP_DESC) == 0) |
1728 » » stream->steps[0].flags |= XML_STREAM_STEP_DESC;» | 1732 » » stream->steps[0].flags |= XML_STREAM_STEP_DESC; |
1729 } | 1733 } |
1730 } | 1734 } |
1731 if (stream->nbStep <= s) | 1735 if (stream->nbStep <= s) |
1732 goto error; | 1736 goto error; |
1733 stream->steps[s].flags |= XML_STREAM_STEP_FINAL; | 1737 stream->steps[s].flags |= XML_STREAM_STEP_FINAL; |
1734 if (root) | 1738 if (root) |
1735 stream->steps[0].flags |= XML_STREAM_STEP_ROOT; | 1739 stream->steps[0].flags |= XML_STREAM_STEP_ROOT; |
1736 #ifdef DEBUG_STREAMING | 1740 #ifdef DEBUG_STREAMING |
1737 xmlDebugStreamComp(stream); | 1741 xmlDebugStreamComp(stream); |
1738 #endif | 1742 #endif |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1911 continue; /* while */ | 1915 continue; /* while */ |
1912 } | 1916 } |
1913 /* | 1917 /* |
1914 * For non-pattern like evaluation like XML Schema IDCs | 1918 * For non-pattern like evaluation like XML Schema IDCs |
1915 * or traditional XPath expressions, this will match if | 1919 * or traditional XPath expressions, this will match if |
1916 * we are at the first level only, otherwise on every level. | 1920 * we are at the first level only, otherwise on every level. |
1917 */ | 1921 */ |
1918 if ((nodeType != XML_ATTRIBUTE_NODE) && | 1922 if ((nodeType != XML_ATTRIBUTE_NODE) && |
1919 (((stream->flags & XML_PATTERN_NOTPATTERN) == 0) || | 1923 (((stream->flags & XML_PATTERN_NOTPATTERN) == 0) || |
1920 (stream->level == 0))) { | 1924 (stream->level == 0))) { |
1921 » » ret = 1;» » | 1925 » » ret = 1; |
1922 } | 1926 } |
1923 stream->level++; | 1927 stream->level++; |
1924 goto stream_next; | 1928 goto stream_next; |
1925 } | 1929 } |
1926 if (stream->blockLevel != -1) { | 1930 if (stream->blockLevel != -1) { |
1927 /* | 1931 /* |
1928 * Skip blocked expressions. | 1932 * Skip blocked expressions. |
1929 */ | 1933 */ |
1930 » stream->level++; | 1934 » stream->level++; |
1931 goto stream_next; | 1935 goto stream_next; |
1932 } | 1936 } |
1933 | 1937 |
1934 if ((nodeType != XML_ELEMENT_NODE) && | 1938 if ((nodeType != XML_ELEMENT_NODE) && |
1935 (nodeType != XML_ATTRIBUTE_NODE) && | 1939 (nodeType != XML_ATTRIBUTE_NODE) && |
1936 ((comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) == 0)) { | 1940 ((comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) == 0)) { |
1937 /* | 1941 /* |
1938 * No need to process nodes of other types if we don't | 1942 * No need to process nodes of other types if we don't |
1939 * resolve to those types. | 1943 * resolve to those types. |
1940 * TODO: Do we need to block the context here? | 1944 * TODO: Do we need to block the context here? |
(...skipping 22 matching lines...) Expand all Loading... |
1963 return (-1); | 1967 return (-1); |
1964 } | 1968 } |
1965 desc = 0; | 1969 desc = 0; |
1966 /* loop-stopper */ | 1970 /* loop-stopper */ |
1967 i = m; | 1971 i = m; |
1968 } else { | 1972 } else { |
1969 /* | 1973 /* |
1970 * If there are "//", then we need to process every "//" | 1974 * If there are "//", then we need to process every "//" |
1971 * occuring in the states, plus any other state for this | 1975 * occuring in the states, plus any other state for this |
1972 * level. | 1976 * level. |
1973 » » */» » | 1977 » » */ |
1974 stepNr = stream->states[2 * i]; | 1978 stepNr = stream->states[2 * i]; |
1975 | 1979 |
1976 /* TODO: should not happen anymore: dead states */ | 1980 /* TODO: should not happen anymore: dead states */ |
1977 if (stepNr < 0) | 1981 if (stepNr < 0) |
1978 goto next_state; | 1982 goto next_state; |
1979 | 1983 |
1980 tmp = stream->states[(2 * i) + 1]; | 1984 tmp = stream->states[(2 * i) + 1]; |
1981 | 1985 |
1982 /* skip new states just added */ | 1986 /* skip new states just added */ |
1983 if (tmp > stream->level) | 1987 if (tmp > stream->level) |
1984 goto next_state; | 1988 goto next_state; |
1985 | 1989 |
1986 /* skip states at ancestor levels, except if "//" */ | 1990 /* skip states at ancestor levels, except if "//" */ |
1987 desc = comp->steps[stepNr].flags & XML_STREAM_STEP_DESC; | 1991 desc = comp->steps[stepNr].flags & XML_STREAM_STEP_DESC; |
1988 if ((tmp < stream->level) && (!desc)) | 1992 if ((tmp < stream->level) && (!desc)) |
1989 goto next_state; | 1993 goto next_state; |
1990 } | 1994 } |
1991 » /* | 1995 » /* |
1992 * Check for correct node-type. | 1996 * Check for correct node-type. |
1993 */ | 1997 */ |
1994 step = comp->steps[stepNr]; | 1998 step = comp->steps[stepNr]; |
1995 if (step.nodeType != nodeType) { | 1999 if (step.nodeType != nodeType) { |
1996 if (step.nodeType == XML_ATTRIBUTE_NODE) { | 2000 if (step.nodeType == XML_ATTRIBUTE_NODE) { |
1997 /* | 2001 /* |
1998 * Block this expression for deeper evaluation. | 2002 * Block this expression for deeper evaluation. |
1999 */ | 2003 */ |
2000 if ((comp->flags & XML_STREAM_DESC) == 0) | 2004 if ((comp->flags & XML_STREAM_DESC) == 0) |
2001 stream->blockLevel = stream->level +1; | 2005 stream->blockLevel = stream->level +1; |
2002 goto next_state; | 2006 goto next_state; |
2003 } else if (step.nodeType != XML_STREAM_ANY_NODE) | 2007 } else if (step.nodeType != XML_STREAM_ANY_NODE) |
2004 goto next_state; | 2008 goto next_state; |
2005 » }» | 2009 » } |
2006 /* | 2010 /* |
2007 * Compare local/namespace-name. | 2011 * Compare local/namespace-name. |
2008 */ | 2012 */ |
2009 match = 0; | 2013 match = 0; |
2010 if (step.nodeType == XML_STREAM_ANY_NODE) { | 2014 if (step.nodeType == XML_STREAM_ANY_NODE) { |
2011 match = 1; | 2015 match = 1; |
2012 } else if (step.name == NULL) { | 2016 } else if (step.name == NULL) { |
2013 if (step.ns == NULL) { | 2017 if (step.ns == NULL) { |
2014 /* | 2018 /* |
2015 * This lets through all elements/attributes. | 2019 * This lets through all elements/attributes. |
2016 */ | 2020 */ |
2017 match = 1; | 2021 match = 1; |
2018 } else if (ns != NULL) | 2022 } else if (ns != NULL) |
2019 match = xmlStrEqual(step.ns, ns); | 2023 match = xmlStrEqual(step.ns, ns); |
2020 } else if (((step.ns != NULL) == (ns != NULL)) && | 2024 } else if (((step.ns != NULL) == (ns != NULL)) && |
2021 (name != NULL) && | 2025 (name != NULL) && |
2022 (step.name[0] == name[0]) && | 2026 (step.name[0] == name[0]) && |
2023 xmlStrEqual(step.name, name) && | 2027 xmlStrEqual(step.name, name) && |
2024 ((step.ns == ns) || xmlStrEqual(step.ns, ns))) | 2028 ((step.ns == ns) || xmlStrEqual(step.ns, ns))) |
2025 { | 2029 { |
2026 » » match = 1;» | 2030 » » match = 1; |
2027 » }» | 2031 » } |
2028 #if 0 | 2032 #if 0 |
2029 /* | 2033 /* |
2030 * TODO: Pointer comparison won't work, since not guaranteed that the given | 2034 * TODO: Pointer comparison won't work, since not guaranteed that the given |
2031 * values are in the same dict; especially if it's the namespace name, | 2035 * values are in the same dict; especially if it's the namespace name, |
2032 * normally coming from ns->href. We need a namespace dict mechanism ! | 2036 * normally coming from ns->href. We need a namespace dict mechanism ! |
2033 */ | 2037 */ |
2034 } else if (comp->dict) { | 2038 } else if (comp->dict) { |
2035 if (step.name == NULL) { | 2039 if (step.name == NULL) { |
2036 if (step.ns == NULL) | 2040 if (step.ns == NULL) |
2037 match = 1; | 2041 match = 1; |
2038 else | 2042 else |
2039 match = (step.ns == ns); | 2043 match = (step.ns == ns); |
2040 } else { | 2044 } else { |
2041 match = ((step.name == name) && (step.ns == ns)); | 2045 match = ((step.name == name) && (step.ns == ns)); |
2042 } | 2046 } |
2043 #endif /* if 0 ------------------------------------------------------- */»
| 2047 #endif /* if 0 ------------------------------------------------------- */ |
2044 » if (match) {» » | 2048 » if (match) { |
2045 final = step.flags & XML_STREAM_STEP_FINAL; | 2049 final = step.flags & XML_STREAM_STEP_FINAL; |
2046 if (desc) { | 2050 if (desc) { |
2047 if (final) { | 2051 if (final) { |
2048 ret = 1; | 2052 ret = 1; |
2049 } else { | 2053 } else { |
2050 /* descending match create a new state */ | 2054 /* descending match create a new state */ |
2051 xmlStreamCtxtAddState(stream, stepNr + 1, | 2055 xmlStreamCtxtAddState(stream, stepNr + 1, |
2052 stream->level + 1); | 2056 stream->level + 1); |
2053 } | 2057 } |
2054 } else { | 2058 } else { |
2055 if (final) { | 2059 if (final) { |
2056 ret = 1; | 2060 ret = 1; |
2057 } else { | 2061 } else { |
2058 xmlStreamCtxtAddState(stream, stepNr + 1, | 2062 xmlStreamCtxtAddState(stream, stepNr + 1, |
2059 stream->level + 1); | 2063 stream->level + 1); |
2060 } | 2064 } |
2061 } | 2065 } |
2062 if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) { | 2066 if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) { |
2063 /* | 2067 /* |
2064 * Check if we have a special case like "foo/bar//.", where | 2068 * Check if we have a special case like "foo/bar//.", where |
2065 * "foo" is selected as well. | 2069 * "foo" is selected as well. |
2066 */ | 2070 */ |
2067 ret = 1; | 2071 ret = 1; |
2068 } | 2072 } |
2069 » }» | 2073 » } |
2070 if (((comp->flags & XML_STREAM_DESC) == 0) && | 2074 if (((comp->flags & XML_STREAM_DESC) == 0) && |
2071 ((! match) || final)) { | 2075 ((! match) || final)) { |
2072 /* | 2076 /* |
2073 * Mark this expression as blocked for any evaluation at | 2077 * Mark this expression as blocked for any evaluation at |
2074 * deeper levels. Note that this includes "/foo" | 2078 * deeper levels. Note that this includes "/foo" |
2075 * expressions if the *pattern* behaviour is used. | 2079 * expressions if the *pattern* behaviour is used. |
2076 */ | 2080 */ |
2077 stream->blockLevel = stream->level +1; | 2081 stream->blockLevel = stream->level +1; |
2078 } | 2082 } |
2079 next_state: | 2083 next_state: |
(...skipping 10 matching lines...) Expand all Loading... |
2090 step = comp->steps[0]; | 2094 step = comp->steps[0]; |
2091 if (step.flags & XML_STREAM_STEP_ROOT) | 2095 if (step.flags & XML_STREAM_STEP_ROOT) |
2092 goto stream_next; | 2096 goto stream_next; |
2093 | 2097 |
2094 desc = step.flags & XML_STREAM_STEP_DESC; | 2098 desc = step.flags & XML_STREAM_STEP_DESC; |
2095 if (stream->flags & XML_PATTERN_NOTPATTERN) { | 2099 if (stream->flags & XML_PATTERN_NOTPATTERN) { |
2096 /* | 2100 /* |
2097 * Re/enter the expression if it is a "descendant" one, | 2101 * Re/enter the expression if it is a "descendant" one, |
2098 * or if we are at the 1st level of evaluation. | 2102 * or if we are at the 1st level of evaluation. |
2099 */ | 2103 */ |
2100 » | 2104 |
2101 if (stream->level == 1) { | 2105 if (stream->level == 1) { |
2102 if (XML_STREAM_XS_IDC(stream)) { | 2106 if (XML_STREAM_XS_IDC(stream)) { |
2103 /* | 2107 /* |
2104 * XS-IDC: The missing "self::node()" will always | 2108 * XS-IDC: The missing "self::node()" will always |
2105 * match the first given node. | 2109 * match the first given node. |
2106 */ | 2110 */ |
2107 goto stream_next; | 2111 goto stream_next; |
2108 } else | 2112 } else |
2109 goto compare; | 2113 goto compare; |
2110 » }» | 2114 » } |
2111 /* | 2115 /* |
2112 * A "//" is always reentrant. | 2116 * A "//" is always reentrant. |
2113 */ | 2117 */ |
2114 if (desc) | 2118 if (desc) |
2115 goto compare; | 2119 goto compare; |
2116 | 2120 |
2117 /* | 2121 /* |
2118 * XS-IDC: Process the 2nd level, since the missing | 2122 * XS-IDC: Process the 2nd level, since the missing |
2119 * "self::node()" is responsible for the 2nd level being | 2123 * "self::node()" is responsible for the 2nd level being |
2120 » * the real start level.» | 2124 » * the real start level. |
2121 » */» | 2125 » */ |
2122 if ((stream->level == 2) && XML_STREAM_XS_IDC(stream)) | 2126 if ((stream->level == 2) && XML_STREAM_XS_IDC(stream)) |
2123 goto compare; | 2127 goto compare; |
2124 | 2128 |
2125 goto stream_next; | 2129 goto stream_next; |
2126 } | 2130 } |
2127 » | 2131 |
2128 compare: | 2132 compare: |
2129 /* | 2133 /* |
2130 * Check expected node-type. | 2134 * Check expected node-type. |
2131 */ | 2135 */ |
2132 if (step.nodeType != nodeType) { | 2136 if (step.nodeType != nodeType) { |
2133 if (nodeType == XML_ATTRIBUTE_NODE) | 2137 if (nodeType == XML_ATTRIBUTE_NODE) |
2134 goto stream_next; | 2138 goto stream_next; |
2135 else if (step.nodeType != XML_STREAM_ANY_NODE) | 2139 else if (step.nodeType != XML_STREAM_ANY_NODE) |
2136 » » goto stream_next;» | 2140 » » goto stream_next; |
2137 } | 2141 } |
2138 /* | 2142 /* |
2139 * Compare local/namespace-name. | 2143 * Compare local/namespace-name. |
2140 */ | 2144 */ |
2141 match = 0; | 2145 match = 0; |
2142 if (step.nodeType == XML_STREAM_ANY_NODE) { | 2146 if (step.nodeType == XML_STREAM_ANY_NODE) { |
2143 match = 1; | 2147 match = 1; |
2144 } else if (step.name == NULL) { | 2148 } else if (step.name == NULL) { |
2145 if (step.ns == NULL) { | 2149 if (step.ns == NULL) { |
2146 /* | 2150 /* |
2147 * This lets through all elements/attributes. | 2151 * This lets through all elements/attributes. |
2148 */ | 2152 */ |
2149 match = 1; | 2153 match = 1; |
2150 } else if (ns != NULL) | 2154 } else if (ns != NULL) |
2151 match = xmlStrEqual(step.ns, ns); | 2155 match = xmlStrEqual(step.ns, ns); |
2152 } else if (((step.ns != NULL) == (ns != NULL)) && | 2156 } else if (((step.ns != NULL) == (ns != NULL)) && |
2153 (name != NULL) && | 2157 (name != NULL) && |
2154 (step.name[0] == name[0]) && | 2158 (step.name[0] == name[0]) && |
2155 xmlStrEqual(step.name, name) && | 2159 xmlStrEqual(step.name, name) && |
2156 ((step.ns == ns) || xmlStrEqual(step.ns, ns))) | 2160 ((step.ns == ns) || xmlStrEqual(step.ns, ns))) |
2157 { | 2161 { |
2158 » match = 1;» | 2162 » match = 1; |
2159 » }» | 2163 » } |
2160 final = step.flags & XML_STREAM_STEP_FINAL; | 2164 final = step.flags & XML_STREAM_STEP_FINAL; |
2161 » if (match) {» | 2165 » if (match) { |
2162 if (final) | 2166 if (final) |
2163 ret = 1; | 2167 ret = 1; |
2164 else | 2168 else |
2165 xmlStreamCtxtAddState(stream, 1, stream->level); | 2169 xmlStreamCtxtAddState(stream, 1, stream->level); |
2166 if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) { | 2170 if ((ret != 1) && (step.flags & XML_STREAM_STEP_IN_SET)) { |
2167 /* | 2171 /* |
2168 * Check if we have a special case like "foo//.", where | 2172 * Check if we have a special case like "foo//.", where |
2169 * "foo" is selected as well. | 2173 * "foo" is selected as well. |
2170 */ | 2174 */ |
2171 ret = 1; | 2175 ret = 1; |
2172 } | 2176 } |
2173 } | 2177 } |
2174 if (((comp->flags & XML_STREAM_DESC) == 0) && | 2178 if (((comp->flags & XML_STREAM_DESC) == 0) && |
2175 ((! match) || final)) { | 2179 ((! match) || final)) { |
2176 /* | 2180 /* |
2177 * Mark this expression as blocked for any evaluation at | 2181 * Mark this expression as blocked for any evaluation at |
2178 * deeper levels. | 2182 * deeper levels. |
2179 */ | 2183 */ |
2180 stream->blockLevel = stream->level; | 2184 stream->blockLevel = stream->level; |
2181 } | 2185 } |
2182 | 2186 |
2183 stream_next: | 2187 stream_next: |
2184 stream = stream->next; | 2188 stream = stream->next; |
2185 } /* while stream != NULL */ | 2189 } /* while stream != NULL */ |
2186 | 2190 |
2187 if (err > 0) | 2191 if (err > 0) |
2188 ret = -1; | 2192 ret = -1; |
2189 #ifdef DEBUG_STREAMING | 2193 #ifdef DEBUG_STREAMING |
2190 xmlDebugStreamCtxt(orig, ret); | 2194 xmlDebugStreamCtxt(orig, ret); |
2191 #endif | 2195 #endif |
2192 return(ret); | 2196 return(ret); |
2193 } | 2197 } |
2194 | 2198 |
2195 /** | 2199 /** |
2196 * xmlStreamPush: | 2200 * xmlStreamPush: |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2268 * xmlStreamPop: | 2272 * xmlStreamPop: |
2269 * @stream: the stream context | 2273 * @stream: the stream context |
2270 * | 2274 * |
2271 * push one level from the stream. | 2275 * push one level from the stream. |
2272 * | 2276 * |
2273 * Returns: -1 in case of error, 0 otherwise. | 2277 * Returns: -1 in case of error, 0 otherwise. |
2274 */ | 2278 */ |
2275 int | 2279 int |
2276 xmlStreamPop(xmlStreamCtxtPtr stream) { | 2280 xmlStreamPop(xmlStreamCtxtPtr stream) { |
2277 int i, lev; | 2281 int i, lev; |
2278 | 2282 |
2279 if (stream == NULL) | 2283 if (stream == NULL) |
2280 return(-1); | 2284 return(-1); |
2281 while (stream != NULL) { | 2285 while (stream != NULL) { |
2282 /* | 2286 /* |
2283 * Reset block-level. | 2287 * Reset block-level. |
2284 */ | 2288 */ |
2285 if (stream->blockLevel == stream->level) | 2289 if (stream->blockLevel == stream->level) |
2286 stream->blockLevel = -1; | 2290 stream->blockLevel = -1; |
2287 | 2291 |
2288 /* | 2292 /* |
2289 * stream->level can be zero when XML_FINAL_IS_ANY_NODE is set | 2293 * stream->level can be zero when XML_FINAL_IS_ANY_NODE is set |
2290 * (see the thread at | 2294 * (see the thread at |
2291 * http://mail.gnome.org/archives/xslt/2008-July/msg00027.html) | 2295 * http://mail.gnome.org/archives/xslt/2008-July/msg00027.html) |
2292 */ | 2296 */ |
2293 if (stream->level) | 2297 if (stream->level) |
2294 stream->level--; | 2298 stream->level--; |
2295 /* | 2299 /* |
2296 * Check evolution of existing states | 2300 * Check evolution of existing states |
2297 » */» | 2301 » */ |
2298 for (i = stream->nbState -1; i >= 0; i--) { | 2302 for (i = stream->nbState -1; i >= 0; i--) { |
2299 /* discard obsoleted states */ | 2303 /* discard obsoleted states */ |
2300 lev = stream->states[(2 * i) + 1]; | 2304 lev = stream->states[(2 * i) + 1]; |
2301 if (lev > stream->level) | 2305 if (lev > stream->level) |
2302 stream->nbState--; | 2306 stream->nbState--; |
2303 if (lev <= stream->level) | 2307 if (lev <= stream->level) |
2304 break; | 2308 break; |
2305 } | 2309 } |
2306 stream = stream->next; | 2310 stream = stream->next; |
2307 } | 2311 } |
2308 return(0); | 2312 return(0); |
2309 } | 2313 } |
2310 | 2314 |
2311 /** | 2315 /** |
2312 * xmlStreamWantsAnyNode: | 2316 * xmlStreamWantsAnyNode: |
2313 * @streamCtxt: the stream context | 2317 * @streamCtxt: the stream context |
2314 * | 2318 * |
2315 * Query if the streaming pattern additionally needs to be fed with | 2319 * Query if the streaming pattern additionally needs to be fed with |
2316 * text-, cdata-section-, comment- and processing-instruction-nodes. | 2320 * text-, cdata-section-, comment- and processing-instruction-nodes. |
2317 * If the result is 0 then only element-nodes and attribute-nodes | 2321 * If the result is 0 then only element-nodes and attribute-nodes |
2318 * need to be pushed. | 2322 * need to be pushed. |
2319 * | 2323 * |
2320 * Returns: 1 in case of need of nodes of the above described types, | 2324 * Returns: 1 in case of need of nodes of the above described types, |
2321 * 0 otherwise. -1 on API errors. | 2325 * 0 otherwise. -1 on API errors. |
2322 */ | 2326 */ |
2323 int | 2327 int |
2324 xmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt) | 2328 xmlStreamWantsAnyNode(xmlStreamCtxtPtr streamCtxt) |
2325 { | 2329 { |
2326 if (streamCtxt == NULL) | 2330 if (streamCtxt == NULL) |
2327 return(-1); | 2331 return(-1); |
2328 while (streamCtxt != NULL) { | 2332 while (streamCtxt != NULL) { |
2329 » if (streamCtxt->comp->flags & XML_STREAM_FINAL_IS_ANY_NODE)» | 2333 » if (streamCtxt->comp->flags & XML_STREAM_FINAL_IS_ANY_NODE) |
2330 return(1); | 2334 return(1); |
2331 streamCtxt = streamCtxt->next; | 2335 streamCtxt = streamCtxt->next; |
2332 } | 2336 } |
2333 return(0); | 2337 return(0); |
2334 } | 2338 } |
2335 | 2339 |
2336 /************************************************************************ | 2340 /************************************************************************ |
2337 * * | 2341 * * |
2338 * The public interfaces * | 2342 * The public interfaces * |
2339 * * | 2343 * * |
(...skipping 30 matching lines...) Expand all Loading... |
2370 while ((*or != 0) && (*or != '|')) or++; | 2374 while ((*or != 0) && (*or != '|')) or++; |
2371 if (*or == 0) | 2375 if (*or == 0) |
2372 ctxt = xmlNewPatParserContext(start, dict, namespaces); | 2376 ctxt = xmlNewPatParserContext(start, dict, namespaces); |
2373 else { | 2377 else { |
2374 tmp = xmlStrndup(start, or - start); | 2378 tmp = xmlStrndup(start, or - start); |
2375 if (tmp != NULL) { | 2379 if (tmp != NULL) { |
2376 ctxt = xmlNewPatParserContext(tmp, dict, namespaces); | 2380 ctxt = xmlNewPatParserContext(tmp, dict, namespaces); |
2377 } | 2381 } |
2378 or++; | 2382 or++; |
2379 } | 2383 } |
2380 » if (ctxt == NULL) goto error;» | 2384 » if (ctxt == NULL) goto error; |
2381 cur = xmlNewPattern(); | 2385 cur = xmlNewPattern(); |
2382 if (cur == NULL) goto error; | 2386 if (cur == NULL) goto error; |
2383 /* | 2387 /* |
2384 * Assign string dict. | 2388 * Assign string dict. |
2385 */ | 2389 */ |
2386 » if (dict) {» | 2390 » if (dict) { |
2387 cur->dict = dict; | 2391 cur->dict = dict; |
2388 xmlDictReference(dict); | 2392 xmlDictReference(dict); |
2389 } | 2393 } |
2390 if (ret == NULL) | 2394 if (ret == NULL) |
2391 ret = cur; | 2395 ret = cur; |
2392 else { | 2396 else { |
2393 cur->next = ret->next; | 2397 cur->next = ret->next; |
2394 ret->next = cur; | 2398 ret->next = cur; |
2395 } | 2399 } |
2396 cur->flags = flags; | 2400 cur->flags = flags; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2559 } | 2563 } |
2560 | 2564 |
2561 /** | 2565 /** |
2562 * xmlPatternMinDepth: | 2566 * xmlPatternMinDepth: |
2563 * @comp: the precompiled pattern | 2567 * @comp: the precompiled pattern |
2564 * | 2568 * |
2565 * Check the minimum depth reachable by a pattern, 0 mean the / or . are | 2569 * Check the minimum depth reachable by a pattern, 0 mean the / or . are |
2566 * part of the set. | 2570 * part of the set. |
2567 * | 2571 * |
2568 * Returns -1 in case of error otherwise the depth, | 2572 * Returns -1 in case of error otherwise the depth, |
2569 * | 2573 * |
2570 */ | 2574 */ |
2571 int | 2575 int |
2572 xmlPatternMinDepth(xmlPatternPtr comp) { | 2576 xmlPatternMinDepth(xmlPatternPtr comp) { |
2573 int ret = 12345678; | 2577 int ret = 12345678; |
2574 if (comp == NULL) | 2578 if (comp == NULL) |
2575 return(-1); | 2579 return(-1); |
2576 while (comp != NULL) { | 2580 while (comp != NULL) { |
2577 if (comp->stream == NULL) | 2581 if (comp->stream == NULL) |
2578 return(-1); | 2582 return(-1); |
2579 if (comp->stream->nbStep < ret) | 2583 if (comp->stream->nbStep < ret) |
(...skipping 24 matching lines...) Expand all Loading... |
2604 return(1); | 2608 return(1); |
2605 comp = comp->next; | 2609 comp = comp->next; |
2606 } | 2610 } |
2607 return(0); | 2611 return(0); |
2608 | 2612 |
2609 } | 2613 } |
2610 | 2614 |
2611 #define bottom_pattern | 2615 #define bottom_pattern |
2612 #include "elfgcchack.h" | 2616 #include "elfgcchack.h" |
2613 #endif /* LIBXML_PATTERN_ENABLED */ | 2617 #endif /* LIBXML_PATTERN_ENABLED */ |
OLD | NEW |