Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: third_party/libxslt/libxslt/pattern.c

Issue 1193533007: Upgrade to libxml 2.9.2 and libxslt 1.1.28 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove suppressions, have landed in blink now Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * pattern.c: Implemetation of the template match compilation and lookup 2 * pattern.c: Implemetation of the template match compilation and lookup
3 * 3 *
4 * Reference: 4 * Reference:
5 * http://www.w3.org/TR/1999/REC-xslt-19991116 5 * http://www.w3.org/TR/1999/REC-xslt-19991116
6 * 6 *
7 * See Copyright for the status of this software. 7 * See Copyright for the status of this software.
8 * 8 *
9 * daniel@veillard.com 9 * daniel@veillard.com
10 */ 10 */
11 11
12 /* 12 /*
13 * TODO: handle pathological cases like *[*[@a="b"]] 13 * TODO: handle pathological cases like *[*[@a="b"]]
14 * TODO: detect [number] at compilation, optimize accordingly 14 * TODO: detect [number] at compilation, optimize accordingly
15 */ 15 */
16 16
17 #define IN_LIBXSLT 17 #define IN_LIBXSLT
18 #include "libxslt.h" 18 #include "libxslt.h"
19 19
20 #include <string.h> 20 #include <string.h>
21 21
22 #include <libxml/xmlmemory.h> 22 #include <libxml/xmlmemory.h>
23 #include <libxml/tree.h> 23 #include <libxml/tree.h>
24 #include <libxml/valid.h> 24 #include <libxml/valid.h>
25 #include <libxml/hash.h> 25 #include <libxml/hash.h>
26 #include <libxml/xmlerror.h> 26 #include <libxml/xmlerror.h>
27 #include <libxml/parserInternals.h> 27 #include <libxml/parserInternals.h>
28 #include <libxml/xpath.h>
28 #include "xslt.h" 29 #include "xslt.h"
29 #include "xsltInternals.h" 30 #include "xsltInternals.h"
30 #include "xsltutils.h" 31 #include "xsltutils.h"
31 #include "imports.h" 32 #include "imports.h"
32 #include "templates.h" 33 #include "templates.h"
33 #include "keys.h" 34 #include "keys.h"
34 #include "pattern.h" 35 #include "pattern.h"
35 #include "documents.h" 36 #include "documents.h"
36 37
37 #ifdef WITH_XSLT_DEBUG 38 #ifdef WITH_XSLT_DEBUG
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 xsltTransformContextPtr ctxt; /* the transformation or NULL */ 121 xsltTransformContextPtr ctxt; /* the transformation or NULL */
121 const xmlChar *cur; /* the current char being parsed */ 122 const xmlChar *cur; /* the current char being parsed */
122 const xmlChar *base; /* the full expression */ 123 const xmlChar *base; /* the full expression */
123 xmlDocPtr doc; /* the source document */ 124 xmlDocPtr doc; /* the source document */
124 xmlNodePtr elem; /* the source element */ 125 xmlNodePtr elem; /* the source element */
125 int error; /* error code */ 126 int error; /* error code */
126 xsltCompMatchPtr comp; /* the result */ 127 xsltCompMatchPtr comp; /* the result */
127 }; 128 };
128 129
129 /************************************************************************ 130 /************************************************************************
130 * » » » » » » » » » * 131 *» » » » » » » » » *
131 * » » » Type functions »» » » » * 132 *» » » Type functions» » » » » *
132 * » » » » » » » » » * 133 *» » » » » » » » » *
133 ************************************************************************/ 134 ************************************************************************/
134 135
135 /** 136 /**
136 * xsltNewCompMatch: 137 * xsltNewCompMatch:
137 * 138 *
138 * Create a new XSLT CompMatch 139 * Create a new XSLT CompMatch
139 * 140 *
140 * Returns the newly allocated xsltCompMatchPtr or NULL in case of error 141 * Returns the newly allocated xsltCompMatchPtr or NULL in case of error
141 */ 142 */
142 static xsltCompMatchPtr 143 static xsltCompMatchPtr
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 if (comp->nbStep >= comp->maxStep) { 297 if (comp->nbStep >= comp->maxStep) {
297 xsltStepOpPtr tmp; 298 xsltStepOpPtr tmp;
298 299
299 tmp = (xsltStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 * 300 tmp = (xsltStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
300 sizeof(xsltStepOp)); 301 sizeof(xsltStepOp));
301 if (tmp == NULL) { 302 if (tmp == NULL) {
302 xsltGenericError(xsltGenericErrorContext, 303 xsltGenericError(xsltGenericErrorContext,
303 "xsltCompMatchAdd: memory re-allocation failure.\n"); 304 "xsltCompMatchAdd: memory re-allocation failure.\n");
304 if (ctxt->style != NULL) 305 if (ctxt->style != NULL)
305 ctxt->style->errors++; 306 ctxt->style->errors++;
307 if (value)
308 xmlFree(value);
309 if (value2)
310 xmlFree(value2);
306 return (-1); 311 return (-1);
307 } 312 }
308 comp->maxStep *= 2; 313 comp->maxStep *= 2;
309 comp->steps = tmp; 314 comp->steps = tmp;
310 } 315 }
311 comp->steps[comp->nbStep].op = op; 316 comp->steps[comp->nbStep].op = op;
312 comp->steps[comp->nbStep].value = value; 317 comp->steps[comp->nbStep].value = value;
313 comp->steps[comp->nbStep].value2 = value2; 318 comp->steps[comp->nbStep].value2 = value2;
314 comp->steps[comp->nbStep].value3 = NULL; 319 comp->steps[comp->nbStep].value3 = NULL;
315 comp->steps[comp->nbStep].comp = NULL; 320 comp->steps[comp->nbStep].comp = NULL;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 * reverse the two top steps. 366 * reverse the two top steps.
362 */ 367 */
363 static void 368 static void
364 xsltSwapTopCompMatch(xsltCompMatchPtr comp) { 369 xsltSwapTopCompMatch(xsltCompMatchPtr comp) {
365 int i; 370 int i;
366 int j = comp->nbStep - 1; 371 int j = comp->nbStep - 1;
367 372
368 if (j > 0) { 373 if (j > 0) {
369 register xmlChar *tmp; 374 register xmlChar *tmp;
370 register xsltOp op; 375 register xsltOp op;
371 » register xmlXPathCompExprPtr expr; 376 » register xmlXPathCompExprPtr expr;
372 register int t; 377 register int t;
373 i = j - 1; 378 i = j - 1;
374 tmp = comp->steps[i].value; 379 tmp = comp->steps[i].value;
375 comp->steps[i].value = comp->steps[j].value; 380 comp->steps[i].value = comp->steps[j].value;
376 comp->steps[j].value = tmp; 381 comp->steps[j].value = tmp;
377 tmp = comp->steps[i].value2; 382 tmp = comp->steps[i].value2;
378 comp->steps[i].value2 = comp->steps[j].value2; 383 comp->steps[i].value2 = comp->steps[j].value2;
379 comp->steps[j].value2 = tmp; 384 comp->steps[j].value2 = tmp;
380 tmp = comp->steps[i].value3; 385 tmp = comp->steps[i].value3;
381 comp->steps[i].value3 = comp->steps[j].value3; 386 comp->steps[i].value3 = comp->steps[j].value3;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 comp->steps[j].indexExtra = t; 444 comp->steps[j].indexExtra = t;
440 t = comp->steps[i].lenExtra; 445 t = comp->steps[i].lenExtra;
441 comp->steps[i].lenExtra = comp->steps[j].lenExtra; 446 comp->steps[i].lenExtra = comp->steps[j].lenExtra;
442 comp->steps[j].lenExtra = t; 447 comp->steps[j].lenExtra = t;
443 j--; 448 j--;
444 i++; 449 i++;
445 } 450 }
446 xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0); 451 xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0);
447 452
448 /* 453 /*
449 * detect consecutive XSLT_OP_PREDICATE indicating a direct 454 * Detect consecutive XSLT_OP_PREDICATE and predicates on ops which
450 * matching should be done. 455 * haven't been optimized yet indicating a direct matching should be done.
451 */ 456 */
452 for (i = 0;i < comp->nbStep - 1;i++) { 457 for (i = 0;i < comp->nbStep - 1;i++) {
453 if ((comp->steps[i].op == XSLT_OP_PREDICATE) && 458 xsltOp op = comp->steps[i].op;
459
460 if ((op != XSLT_OP_ELEM) &&
461 (op != XSLT_OP_ALL) &&
454 (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) { 462 (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) {
455 463
456 comp->direct = 1; 464 comp->direct = 1;
457 if (comp->pattern[0] != '/') { 465 if (comp->pattern[0] != '/') {
458 xmlChar *query; 466 xmlChar *query;
459 467
460 query = xmlStrdup((const xmlChar *)"//"); 468 query = xmlStrdup((const xmlChar *)"//");
461 query = xmlStrcat(query, comp->pattern); 469 query = xmlStrcat(query, comp->pattern);
462 470
463 xmlFree((xmlChar *) comp->pattern); 471 xmlFree((xmlChar *) comp->pattern);
464 comp->pattern = query; 472 comp->pattern = query;
465 } 473 }
466 break; 474 break;
467 } 475 }
468 } 476 }
469 } 477 }
470 478
471 /************************************************************************ 479 /************************************************************************
472 * » » » » » » » » » * 480 *» » » » » » » » » *
473 * » » The interpreter for the precompiled patterns» » * 481 *» » The interpreter for the precompiled patterns» » *
474 * » » » » » » » » » * 482 *» » » » » » » » » *
475 ************************************************************************/ 483 ************************************************************************/
476 484
477 static int 485 static int
478 xsltPatPushState(xsltTransformContextPtr ctxt, xsltStepStates *states, 486 xsltPatPushState(xsltTransformContextPtr ctxt, xsltStepStates *states,
479 int step, xmlNodePtr node) { 487 int step, xmlNodePtr node) {
480 if ((states->states == NULL) || (states->maxstates <= 0)) { 488 if ((states->states == NULL) || (states->maxstates <= 0)) {
481 states->maxstates = 4; 489 states->maxstates = 4;
482 states->nbstates = 0; 490 states->nbstates = 0;
483 states->states = xmlMalloc(4 * sizeof(xsltStepState)); 491 states->states = xmlMalloc(4 * sizeof(xsltStepState));
484 } 492 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 isRVT = 1; 541 isRVT = 1;
534 else 542 else
535 isRVT = 0; 543 isRVT = 0;
536 sel = &comp->steps[0]; /* store extra in first step arbitrarily */ 544 sel = &comp->steps[0]; /* store extra in first step arbitrarily */
537 545
538 prevdoc = (xmlDocPtr) 546 prevdoc = (xmlDocPtr)
539 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr); 547 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
540 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival); 548 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
541 list = (xmlXPathObjectPtr) 549 list = (xmlXPathObjectPtr)
542 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra); 550 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
543 551
544 if ((list == NULL) || (prevdoc != doc)) { 552 if ((list == NULL) || (prevdoc != doc)) {
545 xmlXPathObjectPtr newlist; 553 xmlXPathObjectPtr newlist;
546 xmlNodePtr parent = node->parent; 554 xmlNodePtr parent = node->parent;
547 xmlDocPtr olddoc; 555 xmlDocPtr olddoc;
548 xmlNodePtr oldnode; 556 xmlNodePtr oldnode;
549 » int oldNsNr; 557 » int oldNsNr, oldContextSize, oldProximityPosition;
550 xmlNsPtr *oldNamespaces; 558 xmlNsPtr *oldNamespaces;
551 559
552 oldnode = ctxt->xpathCtxt->node; 560 oldnode = ctxt->xpathCtxt->node;
553 olddoc = ctxt->xpathCtxt->doc; 561 olddoc = ctxt->xpathCtxt->doc;
554 oldNsNr = ctxt->xpathCtxt->nsNr; 562 oldNsNr = ctxt->xpathCtxt->nsNr;
555 oldNamespaces = ctxt->xpathCtxt->namespaces; 563 oldNamespaces = ctxt->xpathCtxt->namespaces;
564 oldContextSize = ctxt->xpathCtxt->contextSize;
565 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
556 ctxt->xpathCtxt->node = node; 566 ctxt->xpathCtxt->node = node;
557 ctxt->xpathCtxt->doc = doc; 567 ctxt->xpathCtxt->doc = doc;
558 ctxt->xpathCtxt->namespaces = nsList; 568 ctxt->xpathCtxt->namespaces = nsList;
559 ctxt->xpathCtxt->nsNr = nsNr; 569 ctxt->xpathCtxt->nsNr = nsNr;
560 newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt); 570 newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt);
561 ctxt->xpathCtxt->node = oldnode; 571 ctxt->xpathCtxt->node = oldnode;
562 ctxt->xpathCtxt->doc = olddoc; 572 ctxt->xpathCtxt->doc = olddoc;
563 ctxt->xpathCtxt->namespaces = oldNamespaces; 573 ctxt->xpathCtxt->namespaces = oldNamespaces;
564 ctxt->xpathCtxt->nsNr = oldNsNr; 574 ctxt->xpathCtxt->nsNr = oldNsNr;
575 ctxt->xpathCtxt->contextSize = oldContextSize;
576 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
565 if (newlist == NULL) 577 if (newlist == NULL)
566 return(-1); 578 return(-1);
567 if (newlist->type != XPATH_NODESET) { 579 if (newlist->type != XPATH_NODESET) {
568 xmlXPathFreeObject(newlist); 580 xmlXPathFreeObject(newlist);
569 return(-1); 581 return(-1);
570 } 582 }
571 ix = 0; 583 ix = 0;
572 584
573 if ((parent == NULL) || (node->doc == NULL) || isRVT) 585 if ((parent == NULL) || (node->doc == NULL) || isRVT)
574 nocache = 1; 586 nocache = 1;
575 » 587
576 if (nocache == 0) { 588 if (nocache == 0) {
577 if (list != NULL) 589 if (list != NULL)
578 xmlXPathFreeObject(list); 590 xmlXPathFreeObject(list);
579 list = newlist; 591 list = newlist;
580 592
581 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) = 593 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) =
582 (void *) list; 594 (void *) list;
583 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = 595 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
584 (void *) doc; 596 (void *) doc;
585 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = 597 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
(...skipping 19 matching lines...) Expand all
605 } 617 }
606 } 618 }
607 } else { 619 } else {
608 } 620 }
609 if (nocache == 1) 621 if (nocache == 1)
610 xmlXPathFreeObject(list); 622 xmlXPathFreeObject(list);
611 return(0); 623 return(0);
612 } 624 }
613 625
614 /** 626 /**
627 * xsltTestPredicateMatch:
628 * @ctxt: a XSLT process context
629 * @comp: the precompiled pattern
630 * @node: a node
631 * @step: the predicate step
632 * @sel: the previous step
633 *
634 * Test whether the node matches the predicate
635 *
636 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
637 */
638 static int
639 xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
640 xmlNodePtr node, xsltStepOpPtr step,
641 xsltStepOpPtr sel) {
642 xmlNodePtr oldNode;
643 xmlDocPtr doc;
644 int oldCS, oldCP;
645 int pos = 0, len = 0;
646 int isRVT;
647 int match;
648
649 if (step->value == NULL)
650 return(0);
651 if (step->comp == NULL)
652 return(0);
653
654 doc = node->doc;
655 if (XSLT_IS_RES_TREE_FRAG(doc))
656 isRVT = 1;
657 else
658 isRVT = 0;
659
660 /*
661 * Recompute contextSize and proximityPosition.
662 *
663 * TODO: Make this work for additional ops. Currently, only XSLT_OP_ELEM
664 * and XSLT_OP_ALL are supported.
665 */
666 oldCS = ctxt->xpathCtxt->contextSize;
667 oldCP = ctxt->xpathCtxt->proximityPosition;
668 if ((sel != NULL) &&
669 (sel->op == XSLT_OP_ELEM) &&
670 (sel->value != NULL) &&
671 (node->type == XML_ELEMENT_NODE) &&
672 (node->parent != NULL)) {
673 xmlNodePtr previous;
674 int nocache = 0;
675
676 previous = (xmlNodePtr)
677 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
678 if ((previous != NULL) &&
679 (previous->parent == node->parent)) {
680 /*
681 * just walk back to adjust the index
682 */
683 int indx = 0;
684 xmlNodePtr sibling = node;
685
686 while (sibling != NULL) {
687 if (sibling == previous)
688 break;
689 if ((sibling->type == XML_ELEMENT_NODE) &&
690 (previous->name != NULL) &&
691 (sibling->name != NULL) &&
692 (previous->name[0] == sibling->name[0]) &&
693 (xmlStrEqual(previous->name, sibling->name)))
694 {
695 if ((sel->value2 == NULL) ||
696 ((sibling->ns != NULL) &&
697 (xmlStrEqual(sel->value2, sibling->ns->href))))
698 indx++;
699 }
700 sibling = sibling->prev;
701 }
702 if (sibling == NULL) {
703 /* hum going backward in document order ... */
704 indx = 0;
705 sibling = node;
706 while (sibling != NULL) {
707 if (sibling == previous)
708 break;
709 if ((sibling->type == XML_ELEMENT_NODE) &&
710 (previous->name != NULL) &&
711 (sibling->name != NULL) &&
712 (previous->name[0] == sibling->name[0]) &&
713 (xmlStrEqual(previous->name, sibling->name)))
714 {
715 if ((sel->value2 == NULL) ||
716 ((sibling->ns != NULL) &&
717 (xmlStrEqual(sel->value2,
718 sibling->ns->href))))
719 {
720 indx--;
721 }
722 }
723 sibling = sibling->next;
724 }
725 }
726 if (sibling != NULL) {
727 pos = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) + indx;
728 /*
729 * If the node is in a Value Tree we need to
730 * save len, but cannot cache the node!
731 * (bugs 153137 and 158840)
732 */
733 if (node->doc != NULL) {
734 len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
735 if (!isRVT) {
736 XSLT_RUNTIME_EXTRA(ctxt,
737 sel->previousExtra, ptr) = node;
738 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
739 }
740 }
741 } else
742 pos = 0;
743 } else {
744 /*
745 * recompute the index
746 */
747 xmlNodePtr parent = node->parent;
748 xmlNodePtr siblings = NULL;
749
750 if (parent) siblings = parent->children;
751
752 while (siblings != NULL) {
753 if (siblings->type == XML_ELEMENT_NODE) {
754 if (siblings == node) {
755 len++;
756 pos = len;
757 } else if ((node->name != NULL) &&
758 (siblings->name != NULL) &&
759 (node->name[0] == siblings->name[0]) &&
760 (xmlStrEqual(node->name, siblings->name))) {
761 if ((sel->value2 == NULL) ||
762 ((siblings->ns != NULL) &&
763 (xmlStrEqual(sel->value2, siblings->ns->href))))
764 len++;
765 }
766 }
767 siblings = siblings->next;
768 }
769 if ((parent == NULL) || (node->doc == NULL))
770 nocache = 1;
771 else {
772 while (parent->parent != NULL)
773 parent = parent->parent;
774 if (((parent->type != XML_DOCUMENT_NODE) &&
775 (parent->type != XML_HTML_DOCUMENT_NODE)) ||
776 (parent != (xmlNodePtr) node->doc))
777 nocache = 1;
778 }
779 }
780 if (pos != 0) {
781 ctxt->xpathCtxt->contextSize = len;
782 ctxt->xpathCtxt->proximityPosition = pos;
783 /*
784 * If the node is in a Value Tree we cannot
785 * cache it !
786 */
787 if ((!isRVT) && (node->doc != NULL) &&
788 (nocache == 0)) {
789 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
790 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
791 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
792 }
793 }
794 } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) &&
795 (node->type == XML_ELEMENT_NODE)) {
796 xmlNodePtr previous;
797 int nocache = 0;
798
799 previous = (xmlNodePtr)
800 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
801 if ((previous != NULL) &&
802 (previous->parent == node->parent)) {
803 /*
804 * just walk back to adjust the index
805 */
806 int indx = 0;
807 xmlNodePtr sibling = node;
808
809 while (sibling != NULL) {
810 if (sibling == previous)
811 break;
812 if (sibling->type == XML_ELEMENT_NODE)
813 indx++;
814 sibling = sibling->prev;
815 }
816 if (sibling == NULL) {
817 /* hum going backward in document order ... */
818 indx = 0;
819 sibling = node;
820 while (sibling != NULL) {
821 if (sibling == previous)
822 break;
823 if (sibling->type == XML_ELEMENT_NODE)
824 indx--;
825 sibling = sibling->next;
826 }
827 }
828 if (sibling != NULL) {
829 pos = XSLT_RUNTIME_EXTRA(ctxt,
830 sel->indexExtra, ival) + indx;
831 /*
832 * If the node is in a Value Tree we cannot
833 * cache it !
834 */
835 if ((node->doc != NULL) && !isRVT) {
836 len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
837 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
838 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
839 }
840 } else
841 pos = 0;
842 } else {
843 /*
844 * recompute the index
845 */
846 xmlNodePtr parent = node->parent;
847 xmlNodePtr siblings = NULL;
848
849 if (parent) siblings = parent->children;
850
851 while (siblings != NULL) {
852 if (siblings->type == XML_ELEMENT_NODE) {
853 len++;
854 if (siblings == node) {
855 pos = len;
856 }
857 }
858 siblings = siblings->next;
859 }
860 if ((parent == NULL) || (node->doc == NULL))
861 nocache = 1;
862 else {
863 while (parent->parent != NULL)
864 parent = parent->parent;
865 if (((parent->type != XML_DOCUMENT_NODE) &&
866 (parent->type != XML_HTML_DOCUMENT_NODE)) ||
867 (parent != (xmlNodePtr) node->doc))
868 nocache = 1;
869 }
870 }
871 if (pos != 0) {
872 ctxt->xpathCtxt->contextSize = len;
873 ctxt->xpathCtxt->proximityPosition = pos;
874 /*
875 * If the node is in a Value Tree we cannot
876 * cache it !
877 */
878 if ((node->doc != NULL) && (nocache == 0) && !isRVT) {
879 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
880 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
881 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
882 }
883 }
884 }
885
886 oldNode = ctxt->node;
887 ctxt->node = node;
888
889 match = xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList, comp->nsNr);
890
891 if (pos != 0) {
892 ctxt->xpathCtxt->contextSize = oldCS;
893 ctxt->xpathCtxt->proximityPosition = oldCP;
894 }
895 ctxt->node = oldNode;
896
897 return match;
898 }
899
900 /**
615 * xsltTestCompMatch: 901 * xsltTestCompMatch:
616 * @ctxt: a XSLT process context 902 * @ctxt: a XSLT process context
617 * @comp: the precompiled pattern 903 * @comp: the precompiled pattern
618 * @node: a node 904 * @node: a node
619 * @mode: the mode name or NULL 905 * @mode: the mode name or NULL
620 * @modeURI: the mode URI or NULL 906 * @modeURI: the mode URI or NULL
621 * 907 *
622 * Test whether the node matches the pattern 908 * Test whether the node matches the pattern
623 * 909 *
624 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure 910 * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
625 */ 911 */
626 static int 912 static int
627 xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, 913 xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
628 » xmlNodePtr node, const xmlChar *mode, 914 » xmlNodePtr matchNode, const xmlChar *mode,
629 const xmlChar *modeURI) { 915 const xmlChar *modeURI) {
630 int i; 916 int i;
917 xmlNodePtr node = matchNode;
631 xsltStepOpPtr step, sel = NULL; 918 xsltStepOpPtr step, sel = NULL;
632 xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */ 919 xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
633 920
634 if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) { 921 if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) {
635 xsltTransformError(ctxt, NULL, node, 922 xsltTransformError(ctxt, NULL, node,
636 "xsltTestCompMatch: null arg\n"); 923 "xsltTestCompMatch: null arg\n");
637 return(-1); 924 return(-1);
638 } 925 }
639 if (mode != NULL) { 926 if (mode != NULL) {
640 if (comp->mode == NULL) 927 if (comp->mode == NULL)
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 goto rollback; 1034 goto rollback;
748 } 1035 }
749 continue; 1036 continue;
750 case XSLT_OP_ANCESTOR: 1037 case XSLT_OP_ANCESTOR:
751 /* TODO: implement coalescing of ANCESTOR/NODE ops */ 1038 /* TODO: implement coalescing of ANCESTOR/NODE ops */
752 if (step->value == NULL) { 1039 if (step->value == NULL) {
753 step = &comp->steps[i+1]; 1040 step = &comp->steps[i+1];
754 if (step->op == XSLT_OP_ROOT) 1041 if (step->op == XSLT_OP_ROOT)
755 goto found; 1042 goto found;
756 /* added NS, ID and KEY as a result of bug 168208 */ 1043 /* added NS, ID and KEY as a result of bug 168208 */
757 » » if ((step->op != XSLT_OP_ELEM) && 1044 » » if ((step->op != XSLT_OP_ELEM) &&
758 » » » (step->op != XSLT_OP_ALL) && 1045 » » » (step->op != XSLT_OP_ALL) &&
759 (step->op != XSLT_OP_NS) && 1046 (step->op != XSLT_OP_NS) &&
760 (step->op != XSLT_OP_ID) && 1047 (step->op != XSLT_OP_ID) &&
761 (step->op != XSLT_OP_KEY)) 1048 (step->op != XSLT_OP_KEY))
762 goto rollback; 1049 goto rollback;
763 } 1050 }
764 if (node == NULL) 1051 if (node == NULL)
765 goto rollback; 1052 goto rollback;
766 if ((node->type == XML_DOCUMENT_NODE) || 1053 if ((node->type == XML_DOCUMENT_NODE) ||
767 (node->type == XML_HTML_DOCUMENT_NODE) || 1054 (node->type == XML_HTML_DOCUMENT_NODE) ||
768 #ifdef LIBXML_DOCB_ENABLED 1055 #ifdef LIBXML_DOCB_ENABLED
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 goto rollback; 1125 goto rollback;
839 if (!xmlStrEqual(step->value, node->ns->href)) 1126 if (!xmlStrEqual(step->value, node->ns->href))
840 goto rollback; 1127 goto rollback;
841 } 1128 }
842 break; 1129 break;
843 case XSLT_OP_ALL: 1130 case XSLT_OP_ALL:
844 if (node->type != XML_ELEMENT_NODE) 1131 if (node->type != XML_ELEMENT_NODE)
845 goto rollback; 1132 goto rollback;
846 break; 1133 break;
847 case XSLT_OP_PREDICATE: { 1134 case XSLT_OP_PREDICATE: {
848 xmlNodePtr oldNode;
849 xmlDocPtr doc;
850 int oldCS, oldCP;
851 int pos = 0, len = 0;
852 int isRVT;
853
854 /* 1135 /*
855 » » * when there is cascading XSLT_OP_PREDICATE, then use a 1136 » » * When there is cascading XSLT_OP_PREDICATE or a predicate
1137 » » * after an op which hasn't been optimized yet, then use a
856 * direct computation approach. It's not done directly 1138 * direct computation approach. It's not done directly
857 * at the beginning of the routine to filter out as much 1139 * at the beginning of the routine to filter out as much
858 * as possible this costly computation. 1140 * as possible this costly computation.
859 */ 1141 */
860 if (comp->direct) { 1142 if (comp->direct) {
861 if (states.states != NULL) { 1143 if (states.states != NULL) {
862 /* Free the rollback states */ 1144 /* Free the rollback states */
863 xmlFree(states.states); 1145 xmlFree(states.states);
864 } 1146 }
865 » » return(xsltTestCompMatchDirect(ctxt, comp, node, 1147 » » return(xsltTestCompMatchDirect(ctxt, comp, matchNode,
866 » » » » » » comp->nsList, comp->nsNr)); 1148 » » » » » » comp->nsList, comp->nsNr));
867 } 1149 }
868 1150
869 » » doc = node->doc; 1151 » » if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel))
870 » » if (XSLT_IS_RES_TREE_FRAG(doc)) 1152 » » goto rollback;
871 » » isRVT = 1;
872 » » else
873 » » isRVT = 0;
874 1153
875 /*
876 * Depending on the last selection, one may need to
877 * recompute contextSize and proximityPosition.
878 */
879 oldCS = ctxt->xpathCtxt->contextSize;
880 oldCP = ctxt->xpathCtxt->proximityPosition;
881 if ((sel != NULL) &&
882 (sel->op == XSLT_OP_ELEM) &&
883 (sel->value != NULL) &&
884 (node->type == XML_ELEMENT_NODE) &&
885 (node->parent != NULL)) {
886 xmlNodePtr previous;
887 int ix, nocache = 0;
888
889 previous = (xmlNodePtr)
890 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
891 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
892 if ((previous != NULL) &&
893 (previous->parent == node->parent)) {
894 /*
895 * just walk back to adjust the index
896 */
897 int indx = 0;
898 xmlNodePtr sibling = node;
899
900 while (sibling != NULL) {
901 if (sibling == previous)
902 break;
903 if ((previous->type == XML_ELEMENT_NODE) &&
904 (previous->name != NULL) &&
905 (sibling->name != NULL) &&
906 (previous->name[0] == sibling->name[0]) &&
907 (xmlStrEqual(previous->name, sibling->name)))
908 {
909 if ((sel->value2 == NULL) ||
910 ((sibling->ns != NULL) &&
911 (xmlStrEqual(sel->value2,
912 sibling->ns->href))))
913 indx++;
914 }
915 sibling = sibling->prev;
916 }
917 if (sibling == NULL) {
918 /* hum going backward in document order ... */
919 indx = 0;
920 sibling = node;
921 while (sibling != NULL) {
922 if (sibling == previous)
923 break;
924 if ((previous->type == XML_ELEMENT_NODE) &&
925 (previous->name != NULL) &&
926 (sibling->name != NULL) &&
927 (previous->name[0] == sibling->name[0]) &&
928 (xmlStrEqual(previous->name, sibling->name)) )
929 {
930 if ((sel->value2 == NULL) ||
931 ((sibling->ns != NULL) &&
932 (xmlStrEqual(sel->value2,
933 sibling->ns->href))))
934 {
935 indx--;
936 }
937 }
938 sibling = sibling->next;
939 }
940 }
941 if (sibling != NULL) {
942 pos = ix + indx;
943 /*
944 * If the node is in a Value Tree we need to
945 * save len, but cannot cache the node!
946 * (bugs 153137 and 158840)
947 */
948 if (node->doc != NULL) {
949 len = XSLT_RUNTIME_EXTRA(ctxt,
950 sel->lenExtra, ival);
951 if (!isRVT) {
952 XSLT_RUNTIME_EXTRA(ctxt,
953 sel->previousExtra, ptr) = node;
954 XSLT_RUNTIME_EXTRA(ctxt,
955 sel->indexExtra, ival) = pos;
956 }
957 }
958 ix = pos;
959 } else
960 pos = 0;
961 } else {
962 /*
963 * recompute the index
964 */
965 xmlNodePtr parent = node->parent;
966 xmlNodePtr siblings = NULL;
967
968 if (parent) siblings = parent->children;
969
970 while (siblings != NULL) {
971 if (siblings->type == XML_ELEMENT_NODE) {
972 if (siblings == node) {
973 len++;
974 pos = len;
975 } else if ((node->name != NULL) &&
976 (siblings->name != NULL) &&
977 (node->name[0] == siblings->name[0]) &&
978 (xmlStrEqual(node->name, siblings->name))) {
979 if ((sel->value2 == NULL) ||
980 ((siblings->ns != NULL) &&
981 (xmlStrEqual(sel->value2,
982 siblings->ns->href))))
983 len++;
984 }
985 }
986 siblings = siblings->next;
987 }
988 if ((parent == NULL) || (node->doc == NULL))
989 nocache = 1;
990 else {
991 while (parent->parent != NULL)
992 parent = parent->parent;
993 if (((parent->type != XML_DOCUMENT_NODE) &&
994 (parent->type != XML_HTML_DOCUMENT_NODE)) ||
995 (parent != (xmlNodePtr) node->doc))
996 nocache = 1;
997 }
998 }
999 if (pos != 0) {
1000 ctxt->xpathCtxt->contextSize = len;
1001 ctxt->xpathCtxt->proximityPosition = pos;
1002 /*
1003 * If the node is in a Value Tree we cannot
1004 * cache it !
1005 */
1006 if ((!isRVT) && (node->doc != NULL) &&
1007 (nocache == 0)) {
1008 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
1009 node;
1010 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
1011 pos;
1012 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) =
1013 len;
1014 }
1015 }
1016 } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) &&
1017 (node->type == XML_ELEMENT_NODE)) {
1018 xmlNodePtr previous;
1019 int ix, nocache = 0;
1020
1021 previous = (xmlNodePtr)
1022 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
1023 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
1024 if ((previous != NULL) &&
1025 (previous->parent == node->parent)) {
1026 /*
1027 * just walk back to adjust the index
1028 */
1029 int indx = 0;
1030 xmlNodePtr sibling = node;
1031
1032 while (sibling != NULL) {
1033 if (sibling == previous)
1034 break;
1035 if (sibling->type == XML_ELEMENT_NODE)
1036 indx++;
1037 sibling = sibling->prev;
1038 }
1039 if (sibling == NULL) {
1040 /* hum going backward in document order ... */
1041 indx = 0;
1042 sibling = node;
1043 while (sibling != NULL) {
1044 if (sibling == previous)
1045 break;
1046 if (sibling->type == XML_ELEMENT_NODE)
1047 indx--;
1048 sibling = sibling->next;
1049 }
1050 }
1051 if (sibling != NULL) {
1052 pos = ix + indx;
1053 /*
1054 * If the node is in a Value Tree we cannot
1055 * cache it !
1056 */
1057 if ((node->doc != NULL) && !isRVT) {
1058 len = XSLT_RUNTIME_EXTRA(ctxt,
1059 sel->lenExtra, ival);
1060 XSLT_RUNTIME_EXTRA(ctxt,
1061 sel->previousExtra, ptr) = node;
1062 XSLT_RUNTIME_EXTRA(ctxt,
1063 sel->indexExtra, ival) = pos;
1064 }
1065 } else
1066 pos = 0;
1067 } else {
1068 /*
1069 * recompute the index
1070 */
1071 xmlNodePtr parent = node->parent;
1072 xmlNodePtr siblings = NULL;
1073
1074 if (parent) siblings = parent->children;
1075
1076 while (siblings != NULL) {
1077 if (siblings->type == XML_ELEMENT_NODE) {
1078 len++;
1079 if (siblings == node) {
1080 pos = len;
1081 }
1082 }
1083 siblings = siblings->next;
1084 }
1085 if ((parent == NULL) || (node->doc == NULL))
1086 nocache = 1;
1087 else {
1088 while (parent->parent != NULL)
1089 parent = parent->parent;
1090 if (((parent->type != XML_DOCUMENT_NODE) &&
1091 (parent->type != XML_HTML_DOCUMENT_NODE)) ||
1092 (parent != (xmlNodePtr) node->doc))
1093 nocache = 1;
1094 }
1095 }
1096 if (pos != 0) {
1097 ctxt->xpathCtxt->contextSize = len;
1098 ctxt->xpathCtxt->proximityPosition = pos;
1099 /*
1100 * If the node is in a Value Tree we cannot
1101 * cache it !
1102 */
1103 if ((node->doc != NULL) && (nocache == 0) && !isRVT) {
1104 XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
1105 node;
1106 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
1107 pos;
1108 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) =
1109 len;
1110 }
1111 }
1112 }
1113 oldNode = ctxt->node;
1114 ctxt->node = node;
1115
1116 if (step->value == NULL)
1117 goto wrong_index;
1118 if (step->comp == NULL)
1119 goto wrong_index;
1120
1121 if (!xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList,
1122 comp->nsNr))
1123 goto wrong_index;
1124
1125 if (pos != 0) {
1126 ctxt->xpathCtxt->contextSize = oldCS;
1127 ctxt->xpathCtxt->proximityPosition = oldCP;
1128 }
1129 ctxt->node = oldNode;
1130 break; 1154 break;
1131 wrong_index:
1132 if (pos != 0) {
1133 ctxt->xpathCtxt->contextSize = oldCS;
1134 ctxt->xpathCtxt->proximityPosition = oldCP;
1135 }
1136 ctxt->node = oldNode;
1137 goto rollback;
1138 } 1155 }
1139 case XSLT_OP_PI: 1156 case XSLT_OP_PI:
1140 if (node->type != XML_PI_NODE) 1157 if (node->type != XML_PI_NODE)
1141 goto rollback; 1158 goto rollback;
1142 if (step->value != NULL) { 1159 if (step->value != NULL) {
1143 if (!xmlStrEqual(step->value, node->name)) 1160 if (!xmlStrEqual(step->value, node->name))
1144 goto rollback; 1161 goto rollback;
1145 } 1162 }
1146 break; 1163 break;
1147 case XSLT_OP_COMMENT: 1164 case XSLT_OP_COMMENT:
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1220 * * 1237 * *
1221 * Dedicated parser for templates * 1238 * Dedicated parser for templates *
1222 * * 1239 * *
1223 ************************************************************************/ 1240 ************************************************************************/
1224 1241
1225 #define CUR (*ctxt->cur) 1242 #define CUR (*ctxt->cur)
1226 #define SKIP(val) ctxt->cur += (val) 1243 #define SKIP(val) ctxt->cur += (val)
1227 #define NXT(val) ctxt->cur[(val)] 1244 #define NXT(val) ctxt->cur[(val)]
1228 #define CUR_PTR ctxt->cur 1245 #define CUR_PTR ctxt->cur
1229 1246
1230 #define SKIP_BLANKS » » » » » » » \ 1247 #define SKIP_BLANKS» » » » » » » \
1231 while (IS_BLANK_CH(CUR)) NEXT 1248 while (IS_BLANK_CH(CUR)) NEXT
1232 1249
1233 #define CURRENT (*ctxt->cur) 1250 #define CURRENT (*ctxt->cur)
1234 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur) 1251 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
1235 1252
1236 1253
1237 #define PUSH(op, val, val2, novar) » » » » » » \ 1254 #define PUSH(op, val, val2, novar)» » » » » » \
1238 if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto e rror; 1255 if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto e rror;
1239 1256
1240 #define SWAP() »» » » » » \ 1257 #define SWAP()» » » » » » \
1241 xsltSwapTopCompMatch(ctxt->comp); 1258 xsltSwapTopCompMatch(ctxt->comp);
1242 1259
1243 #define XSLT_ERROR(X) \ 1260 #define XSLT_ERROR(X) \
1244 { xsltError(ctxt, __FILE__, __LINE__, X); \ 1261 { xsltError(ctxt, __FILE__, __LINE__, X); \
1245 ctxt->error = (X); return; } 1262 ctxt->error = (X); return; }
1246 1263
1247 #define XSLT_ERROR0(X) \ 1264 #define XSLT_ERROR0(X) \
1248 { xsltError(ctxt, __FILE__, __LINE__, X); \ 1265 { xsltError(ctxt, __FILE__, __LINE__, X); \
1249 ctxt->error = (X); return(0); } 1266 ctxt->error = (X); return(0); }
1250 1267
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1374 if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) { 1391 if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) {
1375 if (axis != 0) { 1392 if (axis != 0) {
1376 xsltTransformError(NULL, NULL, NULL, 1393 xsltTransformError(NULL, NULL, NULL,
1377 "xsltCompileIdKeyPattern : NodeTest expected\n"); 1394 "xsltCompileIdKeyPattern : NodeTest expected\n");
1378 ctxt->error = 1; 1395 ctxt->error = 1;
1379 return; 1396 return;
1380 } 1397 }
1381 NEXT; 1398 NEXT;
1382 SKIP_BLANKS; 1399 SKIP_BLANKS;
1383 lit = xsltScanLiteral(ctxt); 1400 lit = xsltScanLiteral(ctxt);
1384 » if (ctxt->error) 1401 » if (ctxt->error) {
1402 » xsltTransformError(NULL, NULL, NULL,
1403 » » "xsltCompileIdKeyPattern : Literal expected\n");
1385 return; 1404 return;
1405 }
1386 SKIP_BLANKS; 1406 SKIP_BLANKS;
1387 if (CUR != ')') { 1407 if (CUR != ')') {
1388 xsltTransformError(NULL, NULL, NULL, 1408 xsltTransformError(NULL, NULL, NULL,
1389 "xsltCompileIdKeyPattern : ) expected\n"); 1409 "xsltCompileIdKeyPattern : ) expected\n");
1410 xmlFree(lit);
1390 ctxt->error = 1; 1411 ctxt->error = 1;
1391 return; 1412 return;
1392 } 1413 }
1393 NEXT; 1414 NEXT;
1394 PUSH(XSLT_OP_ID, lit, NULL, novar); 1415 PUSH(XSLT_OP_ID, lit, NULL, novar);
1416 lit = NULL;
1395 } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) { 1417 } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) {
1396 if (axis != 0) { 1418 if (axis != 0) {
1397 xsltTransformError(NULL, NULL, NULL, 1419 xsltTransformError(NULL, NULL, NULL,
1398 "xsltCompileIdKeyPattern : NodeTest expected\n"); 1420 "xsltCompileIdKeyPattern : NodeTest expected\n");
1399 ctxt->error = 1; 1421 ctxt->error = 1;
1400 return; 1422 return;
1401 } 1423 }
1402 NEXT; 1424 NEXT;
1403 SKIP_BLANKS; 1425 SKIP_BLANKS;
1404 lit = xsltScanLiteral(ctxt); 1426 lit = xsltScanLiteral(ctxt);
1405 » if (ctxt->error) 1427 » if (ctxt->error) {
1428 » xsltTransformError(NULL, NULL, NULL,
1429 » » "xsltCompileIdKeyPattern : Literal expected\n");
1406 return; 1430 return;
1431 }
1407 SKIP_BLANKS; 1432 SKIP_BLANKS;
1408 if (CUR != ',') { 1433 if (CUR != ',') {
1409 xsltTransformError(NULL, NULL, NULL, 1434 xsltTransformError(NULL, NULL, NULL,
1410 "xsltCompileIdKeyPattern : , expected\n"); 1435 "xsltCompileIdKeyPattern : , expected\n");
1436 xmlFree(lit);
1411 ctxt->error = 1; 1437 ctxt->error = 1;
1412 return; 1438 return;
1413 } 1439 }
1414 NEXT; 1440 NEXT;
1415 SKIP_BLANKS; 1441 SKIP_BLANKS;
1416 lit2 = xsltScanLiteral(ctxt); 1442 lit2 = xsltScanLiteral(ctxt);
1417 » if (ctxt->error) 1443 » if (ctxt->error) {
1444 » xsltTransformError(NULL, NULL, NULL,
1445 » » "xsltCompileIdKeyPattern : Literal expected\n");
1446 » xmlFree(lit);
1418 return; 1447 return;
1448 }
1419 SKIP_BLANKS; 1449 SKIP_BLANKS;
1420 if (CUR != ')') { 1450 if (CUR != ')') {
1421 xsltTransformError(NULL, NULL, NULL, 1451 xsltTransformError(NULL, NULL, NULL,
1422 "xsltCompileIdKeyPattern : ) expected\n"); 1452 "xsltCompileIdKeyPattern : ) expected\n");
1453 xmlFree(lit);
1454 xmlFree(lit2);
1423 ctxt->error = 1; 1455 ctxt->error = 1;
1424 return; 1456 return;
1425 } 1457 }
1426 NEXT; 1458 NEXT;
1427 /* URGENT TODO: support namespace in keys */ 1459 /* URGENT TODO: support namespace in keys */
1428 PUSH(XSLT_OP_KEY, lit, lit2, novar); 1460 PUSH(XSLT_OP_KEY, lit, lit2, novar);
1461 lit = NULL;
1462 lit2 = NULL;
1429 } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) { 1463 } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {
1430 NEXT; 1464 NEXT;
1431 SKIP_BLANKS; 1465 SKIP_BLANKS;
1432 if (CUR != ')') { 1466 if (CUR != ')') {
1433 lit = xsltScanLiteral(ctxt); 1467 lit = xsltScanLiteral(ctxt);
1434 » if (ctxt->error) 1468 » if (ctxt->error) {
1469 » » xsltTransformError(NULL, NULL, NULL,
1470 » » » "xsltCompileIdKeyPattern : Literal expected\n");
1435 return; 1471 return;
1472 }
1436 SKIP_BLANKS; 1473 SKIP_BLANKS;
1437 if (CUR != ')') { 1474 if (CUR != ')') {
1438 xsltTransformError(NULL, NULL, NULL, 1475 xsltTransformError(NULL, NULL, NULL,
1439 "xsltCompileIdKeyPattern : ) expected\n"); 1476 "xsltCompileIdKeyPattern : ) expected\n");
1440 ctxt->error = 1; 1477 ctxt->error = 1;
1441 return; 1478 return;
1442 } 1479 }
1443 } 1480 }
1444 NEXT; 1481 NEXT;
1445 PUSH(XSLT_OP_PI, lit, NULL, novar); 1482 PUSH(XSLT_OP_PI, lit, NULL, novar);
1483 lit = NULL;
1446 } else if (xmlStrEqual(name, (const xmlChar *)"text")) { 1484 } else if (xmlStrEqual(name, (const xmlChar *)"text")) {
1447 NEXT; 1485 NEXT;
1448 SKIP_BLANKS; 1486 SKIP_BLANKS;
1449 if (CUR != ')') { 1487 if (CUR != ')') {
1450 xsltTransformError(NULL, NULL, NULL, 1488 xsltTransformError(NULL, NULL, NULL,
1451 "xsltCompileIdKeyPattern : ) expected\n"); 1489 "xsltCompileIdKeyPattern : ) expected\n");
1452 ctxt->error = 1; 1490 ctxt->error = 1;
1453 return; 1491 return;
1454 } 1492 }
1455 NEXT; 1493 NEXT;
(...skipping 30 matching lines...) Expand all
1486 "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n"); 1524 "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n");
1487 ctxt->error = 1; 1525 ctxt->error = 1;
1488 return; 1526 return;
1489 } else { 1527 } else {
1490 xsltTransformError(NULL, NULL, NULL, 1528 xsltTransformError(NULL, NULL, NULL,
1491 "xsltCompileIdKeyPattern : node type\n"); 1529 "xsltCompileIdKeyPattern : node type\n");
1492 ctxt->error = 1; 1530 ctxt->error = 1;
1493 return; 1531 return;
1494 } 1532 }
1495 error: 1533 error:
1496 if (name != NULL) 1534 return;
1497 » xmlFree(name);
1498 } 1535 }
1499 1536
1500 /** 1537 /**
1501 * xsltCompileStepPattern: 1538 * xsltCompileStepPattern:
1502 * @ctxt: the compilation context 1539 * @ctxt: the compilation context
1503 * @token: a posible precompiled name 1540 * @token: a posible precompiled name
1504 * @novar: flag to prohibit xslt variables from pattern 1541 * @novar: flag to prohibit xslt variables from pattern
1505 * 1542 *
1506 * Compile the XSLT StepPattern and generates a precompiled 1543 * Compile the XSLT StepPattern and generates a precompiled
1507 * form suitable for fast matching. 1544 * form suitable for fast matching.
1508 * 1545 *
1509 * [5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate* 1546 * [5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate*
1510 * [6] ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier 1547 * [6] ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier
1511 * | ('child' | 'attribute') '::' 1548 * | ('child' | 'attribute') '::'
1512 * from XPath 1549 * from XPath
1513 * [7] NodeTest ::= NameTest 1550 * [7] NodeTest ::= NameTest
1514 * | NodeType '(' ')' 1551 * | NodeType '(' ')'
1515 * | 'processing-instruction' '(' Literal ')' 1552 * | 'processing-instruction' '(' Literal ')'
1516 * [8] Predicate ::= '[' PredicateExpr ']' 1553 * [8] Predicate ::= '[' PredicateExpr ']'
1517 * [9] PredicateExpr ::= Expr 1554 * [9] PredicateExpr ::= Expr
1518 * [13] AbbreviatedAxisSpecifier ::= '@'? 1555 * [13] AbbreviatedAxisSpecifier ::= '@'?
1519 * [37] NameTest ::= '*' | NCName ':' '*' | QName 1556 * [37] NameTest ::= '*' | NCName ':' '*' | QName
(...skipping 30 matching lines...) Expand all
1550 "xsltCompileStepPattern : Name expected\n"); 1587 "xsltCompileStepPattern : Name expected\n");
1551 ctxt->error = 1; 1588 ctxt->error = 1;
1552 goto error; 1589 goto error;
1553 } 1590 }
1554 } 1591 }
1555 1592
1556 1593
1557 SKIP_BLANKS; 1594 SKIP_BLANKS;
1558 if (CUR == '(') { 1595 if (CUR == '(') {
1559 xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis); 1596 xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis);
1597 xmlFree(token);
1598 token = NULL;
1560 if (ctxt->error) 1599 if (ctxt->error)
1561 goto error; 1600 goto error;
1562 } else if (CUR == ':') { 1601 } else if (CUR == ':') {
1563 NEXT; 1602 NEXT;
1564 if (CUR != ':') { 1603 if (CUR != ':') {
1565 xmlChar *prefix = token; 1604 xmlChar *prefix = token;
1566 xmlNsPtr ns; 1605 xmlNsPtr ns;
1567 1606
1568 /* 1607 /*
1569 * This is a namespace match 1608 * This is a namespace match
1570 */ 1609 */
1571 token = xsltScanNCName(ctxt); 1610 token = xsltScanNCName(ctxt);
1572 ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix); 1611 ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);
1573 if (ns == NULL) { 1612 if (ns == NULL) {
1574 xsltTransformError(NULL, NULL, NULL, 1613 xsltTransformError(NULL, NULL, NULL,
1575 "xsltCompileStepPattern : no namespace bound to prefix %s\n", 1614 "xsltCompileStepPattern : no namespace bound to prefix %s\n",
1576 prefix); 1615 prefix);
1577 xmlFree(prefix); 1616 xmlFree(prefix);
1617 prefix=NULL;
1578 ctxt->error = 1; 1618 ctxt->error = 1;
1579 goto error; 1619 goto error;
1580 } else { 1620 } else {
1581 URL = xmlStrdup(ns->href); 1621 URL = xmlStrdup(ns->href);
1582 } 1622 }
1583 xmlFree(prefix); 1623 xmlFree(prefix);
1624 prefix=NULL;
1584 if (token == NULL) { 1625 if (token == NULL) {
1585 if (CUR == '*') { 1626 if (CUR == '*') {
1586 NEXT; 1627 NEXT;
1587 if (axis == AXIS_ATTRIBUTE) { 1628 if (axis == AXIS_ATTRIBUTE) {
1588 PUSH(XSLT_OP_ATTR, NULL, URL, novar); 1629 PUSH(XSLT_OP_ATTR, NULL, URL, novar);
1630 URL = NULL;
1589 } 1631 }
1590 else { 1632 else {
1591 PUSH(XSLT_OP_NS, URL, NULL, novar); 1633 PUSH(XSLT_OP_NS, URL, NULL, novar);
1634 URL = NULL;
1592 } 1635 }
1593 } else { 1636 } else {
1594 xsltTransformError(NULL, NULL, NULL, 1637 xsltTransformError(NULL, NULL, NULL,
1595 "xsltCompileStepPattern : Name expected\n"); 1638 "xsltCompileStepPattern : Name expected\n");
1596 ctxt->error = 1; 1639 ctxt->error = 1;
1597 goto error; 1640 goto error;
1598 } 1641 }
1599 } else { 1642 } else {
1600 if (axis == AXIS_ATTRIBUTE) { 1643 if (axis == AXIS_ATTRIBUTE) {
1601 PUSH(XSLT_OP_ATTR, token, URL, novar); 1644 PUSH(XSLT_OP_ATTR, token, URL, novar);
1645 token = NULL;
1646 URL = NULL;
1602 } 1647 }
1603 else { 1648 else {
1604 PUSH(XSLT_OP_ELEM, token, URL, novar); 1649 PUSH(XSLT_OP_ELEM, token, URL, novar);
1650 token = NULL;
1651 URL = NULL;
1605 } 1652 }
1606 } 1653 }
1607 } else { 1654 } else {
1608 if (axis != 0) { 1655 if (axis != 0) {
1609 xsltTransformError(NULL, NULL, NULL, 1656 xsltTransformError(NULL, NULL, NULL,
1610 "xsltCompileStepPattern : NodeTest expected\n"); 1657 "xsltCompileStepPattern : NodeTest expected\n");
1611 ctxt->error = 1; 1658 ctxt->error = 1;
1612 goto error; 1659 goto error;
1613 } 1660 }
1614 NEXT; 1661 NEXT;
1615 if (xmlStrEqual(token, (const xmlChar *) "child")) { 1662 if (xmlStrEqual(token, (const xmlChar *) "child")) {
1616 axis = AXIS_CHILD; 1663 axis = AXIS_CHILD;
1617 } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) { 1664 } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) {
1618 axis = AXIS_ATTRIBUTE; 1665 axis = AXIS_ATTRIBUTE;
1619 } else { 1666 } else {
1620 xsltTransformError(NULL, NULL, NULL, 1667 xsltTransformError(NULL, NULL, NULL,
1621 "xsltCompileStepPattern : 'child' or 'attribute' expected\n" ); 1668 "xsltCompileStepPattern : 'child' or 'attribute' expected\n" );
1622 ctxt->error = 1; 1669 ctxt->error = 1;
1623 goto error; 1670 goto error;
1624 } 1671 }
1625 xmlFree(token); 1672 xmlFree(token);
1673 token = NULL;
1626 SKIP_BLANKS; 1674 SKIP_BLANKS;
1627 token = xsltScanNCName(ctxt); 1675 token = xsltScanNCName(ctxt);
1628 goto parse_node_test; 1676 goto parse_node_test;
1629 } 1677 }
1630 } else { 1678 } else {
1631 URI = xsltGetQNameURI(ctxt->elem, &token); 1679 URI = xsltGetQNameURI(ctxt->elem, &token);
1632 if (token == NULL) { 1680 if (token == NULL) {
1633 ctxt->error = 1; 1681 ctxt->error = 1;
1634 goto error; 1682 goto error;
1635 } 1683 }
1636 if (URI != NULL) 1684 if (URI != NULL)
1637 URL = xmlStrdup(URI); 1685 URL = xmlStrdup(URI);
1638 if (axis == AXIS_ATTRIBUTE) { 1686 if (axis == AXIS_ATTRIBUTE) {
1639 PUSH(XSLT_OP_ATTR, token, URL, novar); 1687 PUSH(XSLT_OP_ATTR, token, URL, novar);
1688 token = NULL;
1689 URL = NULL;
1640 } 1690 }
1641 else { 1691 else {
1642 PUSH(XSLT_OP_ELEM, token, URL, novar); 1692 PUSH(XSLT_OP_ELEM, token, URL, novar);
1693 token = NULL;
1694 URL = NULL;
1643 } 1695 }
1644 } 1696 }
1645 parse_predicate: 1697 parse_predicate:
1646 SKIP_BLANKS; 1698 SKIP_BLANKS;
1647 level = 0; 1699 level = 0;
1648 while (CUR == '[') { 1700 while (CUR == '[') {
1649 const xmlChar *q; 1701 const xmlChar *q;
1650 xmlChar *ret = NULL; 1702 xmlChar *ret = NULL;
1651 1703
1652 level++; 1704 level++;
(...skipping 19 matching lines...) Expand all
1672 NEXT; 1724 NEXT;
1673 } 1725 }
1674 if (CUR == 0) { 1726 if (CUR == 0) {
1675 xsltTransformError(NULL, NULL, NULL, 1727 xsltTransformError(NULL, NULL, NULL,
1676 "xsltCompileStepPattern : ']' expected\n"); 1728 "xsltCompileStepPattern : ']' expected\n");
1677 ctxt->error = 1; 1729 ctxt->error = 1;
1678 return; 1730 return;
1679 } 1731 }
1680 ret = xmlStrndup(q, CUR_PTR - q); 1732 ret = xmlStrndup(q, CUR_PTR - q);
1681 PUSH(XSLT_OP_PREDICATE, ret, NULL, novar); 1733 PUSH(XSLT_OP_PREDICATE, ret, NULL, novar);
1734 ret = NULL;
1682 /* push the predicate lower than local test */ 1735 /* push the predicate lower than local test */
1683 SWAP(); 1736 SWAP();
1684 NEXT; 1737 NEXT;
1685 SKIP_BLANKS; 1738 SKIP_BLANKS;
1686 } 1739 }
1687 return; 1740 return;
1688 error: 1741 error:
1689 if (token != NULL) 1742 if (token != NULL)
1690 xmlFree(token); 1743 xmlFree(token);
1691 if (name != NULL) 1744 if (name != NULL)
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1780 name = xsltScanNCName(ctxt); 1833 name = xsltScanNCName(ctxt);
1781 if (name == NULL) { 1834 if (name == NULL) {
1782 xsltTransformError(NULL, NULL, NULL, 1835 xsltTransformError(NULL, NULL, NULL,
1783 "xsltCompileLocationPathPattern : Name expected\n"); 1836 "xsltCompileLocationPathPattern : Name expected\n");
1784 ctxt->error = 1; 1837 ctxt->error = 1;
1785 return; 1838 return;
1786 } 1839 }
1787 SKIP_BLANKS; 1840 SKIP_BLANKS;
1788 if ((CUR == '(') && !xmlXPathIsNodeType(name)) { 1841 if ((CUR == '(') && !xmlXPathIsNodeType(name)) {
1789 xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0); 1842 xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0);
1790 » if (ctxt->error) 1843 » xmlFree(name);
1791 » » return; 1844 » name = NULL;
1792 if ((CUR == '/') && (NXT(1) == '/')) { 1845 if ((CUR == '/') && (NXT(1) == '/')) {
1793 PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar); 1846 PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
1794 NEXT; 1847 NEXT;
1795 NEXT; 1848 NEXT;
1796 SKIP_BLANKS; 1849 SKIP_BLANKS;
1797 xsltCompileRelativePathPattern(ctxt, NULL, novar); 1850 xsltCompileRelativePathPattern(ctxt, NULL, novar);
1798 } else if (CUR == '/') { 1851 } else if (CUR == '/') {
1799 PUSH(XSLT_OP_PARENT, NULL, NULL, novar); 1852 PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1800 NEXT; 1853 NEXT;
1801 SKIP_BLANKS; 1854 SKIP_BLANKS;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1859 level--; 1912 level--;
1860 else if (pattern[end] == '\'') { 1913 else if (pattern[end] == '\'') {
1861 end++; 1914 end++;
1862 while ((pattern[end] != 0) && (pattern[end] != '\'')) 1915 while ((pattern[end] != 0) && (pattern[end] != '\''))
1863 end++; 1916 end++;
1864 } else if (pattern[end] == '"') { 1917 } else if (pattern[end] == '"') {
1865 end++; 1918 end++;
1866 while ((pattern[end] != 0) && (pattern[end] != '"')) 1919 while ((pattern[end] != 0) && (pattern[end] != '"'))
1867 end++; 1920 end++;
1868 } 1921 }
1869 if (pattern[end] == 0) 1922 » if (pattern[end] == 0)
1870 break; 1923 » break;
1871 end++; 1924 end++;
1872 } 1925 }
1873 if (current == end) { 1926 if (current == end) {
1874 xsltTransformError(NULL, NULL, node, 1927 xsltTransformError(NULL, NULL, node,
1875 "xsltCompilePattern : NULL pattern\n"); 1928 "xsltCompilePattern : NULL pattern\n");
1876 goto error; 1929 goto error;
1877 } 1930 }
1878 element = xsltNewCompMatch(); 1931 element = xsltNewCompMatch();
1879 if (element == NULL) { 1932 if (element == NULL) {
1880 goto error; 1933 goto error;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2037 const xmlChar *name = NULL; 2090 const xmlChar *name = NULL;
2038 float priority; /* the priority */ 2091 float priority; /* the priority */
2039 2092
2040 if ((style == NULL) || (cur == NULL) || (cur->match == NULL)) 2093 if ((style == NULL) || (cur == NULL) || (cur->match == NULL))
2041 return(-1); 2094 return(-1);
2042 2095
2043 priority = cur->priority; 2096 priority = cur->priority;
2044 pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem, 2097 pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem,
2045 style, NULL, 1); 2098 style, NULL, 1);
2046 if (pat == NULL) 2099 if (pat == NULL)
2047 » return(-1); 2100 » return(-1);
2048 while (pat) { 2101 while (pat) {
2049 next = pat->next; 2102 next = pat->next;
2050 pat->next = NULL; 2103 pat->next = NULL;
2051 name = NULL; 2104 name = NULL;
2052 » 2105
2053 pat->template = cur; 2106 pat->template = cur;
2054 if (mode != NULL) 2107 if (mode != NULL)
2055 pat->mode = xmlDictLookup(style->dict, mode, -1); 2108 pat->mode = xmlDictLookup(style->dict, mode, -1);
2056 if (modeURI != NULL) 2109 if (modeURI != NULL)
2057 pat->modeURI = xmlDictLookup(style->dict, modeURI, -1); 2110 pat->modeURI = xmlDictLookup(style->dict, modeURI, -1);
2058 if (priority != XSLT_PAT_NO_PRIORITY) 2111 if (priority != XSLT_PAT_NO_PRIORITY)
2059 pat->priority = priority; 2112 pat->priority = priority;
2060 2113
2061 /* 2114 /*
2062 * insert it in the hash table list corresponding to its lookup name 2115 * insert it in the hash table list corresponding to its lookup name
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
2429 { 2482 {
2430 /* 2483 /*
2431 * Compute all remaining keys for this document. 2484 * Compute all remaining keys for this document.
2432 * 2485 *
2433 * REVISIT TODO: I think this could be further optimized. 2486 * REVISIT TODO: I think this could be further optimized.
2434 */ 2487 */
2435 if (xsltComputeAllKeys(ctxt, node) == -1) 2488 if (xsltComputeAllKeys(ctxt, node) == -1)
2436 goto error; 2489 goto error;
2437 2490
2438 switch (node->type) { 2491 switch (node->type) {
2439 » » case XML_ELEMENT_NODE:» » 2492 » » case XML_ELEMENT_NODE:
2440 if (node->psvi != NULL) keyed = 1; 2493 if (node->psvi != NULL) keyed = 1;
2441 break; 2494 break;
2442 case XML_ATTRIBUTE_NODE: 2495 case XML_ATTRIBUTE_NODE:
2443 if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1; 2496 if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1;
2444 break; 2497 break;
2445 case XML_TEXT_NODE: 2498 case XML_TEXT_NODE:
2446 case XML_CDATA_SECTION_NODE: 2499 case XML_CDATA_SECTION_NODE:
2447 case XML_COMMENT_NODE: 2500 case XML_COMMENT_NODE:
2448 » » case XML_PI_NODE:» » 2501 » » case XML_PI_NODE:
2449 if (node->psvi != NULL) keyed = 1; 2502 if (node->psvi != NULL) keyed = 1;
2450 break; 2503 break;
2451 case XML_DOCUMENT_NODE: 2504 case XML_DOCUMENT_NODE:
2452 case XML_HTML_DOCUMENT_NODE: 2505 case XML_HTML_DOCUMENT_NODE:
2453 if (((xmlDocPtr) node)->psvi != NULL) keyed = 1; 2506 if (((xmlDocPtr) node)->psvi != NULL) keyed = 1;
2454 » » break;» » 2507 » » break;
2455 default: 2508 default:
2456 break; 2509 break;
2457 } 2510 }
2458 if (keyed) 2511 if (keyed)
2459 goto keyed_match; 2512 goto keyed_match;
2460 } 2513 }
2461 if (ret != NULL) 2514 if (ret != NULL)
2462 return(ret); 2515 return(ret);
2463 2516
2464 /* 2517 /*
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2504 if (style->parentMatch != NULL) 2557 if (style->parentMatch != NULL)
2505 xsltFreeCompMatchList(style->parentMatch); 2558 xsltFreeCompMatchList(style->parentMatch);
2506 if (style->textMatch != NULL) 2559 if (style->textMatch != NULL)
2507 xsltFreeCompMatchList(style->textMatch); 2560 xsltFreeCompMatchList(style->textMatch);
2508 if (style->piMatch != NULL) 2561 if (style->piMatch != NULL)
2509 xsltFreeCompMatchList(style->piMatch); 2562 xsltFreeCompMatchList(style->piMatch);
2510 if (style->commentMatch != NULL) 2563 if (style->commentMatch != NULL)
2511 xsltFreeCompMatchList(style->commentMatch); 2564 xsltFreeCompMatchList(style->commentMatch);
2512 } 2565 }
2513 2566
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698