| 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 |