ReactOS 0.4.15-dev-5664-g3bf4ef6
pattern.c
Go to the documentation of this file.
1/*
2 * pattern.c: Implemetation of the template match compilation and lookup
3 *
4 * Reference:
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
6 *
7 * See Copyright for the status of this software.
8 *
9 * daniel@veillard.com
10 */
11
12/*
13 * TODO: handle pathological cases like *[*[@a="b"]]
14 * TODO: detect [number] at compilation, optimize accordingly
15 */
16
17#include "precomp.h"
18
19#ifdef WITH_XSLT_DEBUG
20#define WITH_XSLT_DEBUG_PATTERN
21#endif
22
23/*
24 * Types are private:
25 */
26
27typedef enum {
44
45typedef enum {
49
53 int step;
55};
56
63};
64
65typedef struct _xsltStepOp xsltStepOp;
72 xmlXPathCompExprPtr comp;
73 /*
74 * Optimisations for count
75 */
79};
80
82 struct _xsltCompMatch *next; /* siblings in the name hash */
83 float priority; /* the priority */
84 const xmlChar *pattern; /* the pattern */
85 const xmlChar *mode; /* the mode */
86 const xmlChar *modeURI; /* the mode URI */
87 xsltTemplatePtr template; /* the associated template */
88 xmlNodePtr node; /* the containing element */
89
90 int direct;
91 /* TODO fix the statically allocated size steps[] */
92 int nbStep;
94 xmlNsPtr *nsList; /* the namespaces in scope */
95 int nsNr; /* the number of namespaces in scope */
96 xsltStepOpPtr steps; /* ops for computation */
97};
98
102 xsltStylesheetPtr style; /* the stylesheet */
103 xsltTransformContextPtr ctxt; /* the transformation or NULL */
104 const xmlChar *cur; /* the current char being parsed */
105 const xmlChar *base; /* the full expression */
106 xmlDocPtr doc; /* the source document */
107 xmlNodePtr elem; /* the source element */
108 int error; /* error code */
109 xsltCompMatchPtr comp; /* the result */
110};
111
112/************************************************************************
113 * *
114 * Type functions *
115 * *
116 ************************************************************************/
117
125static xsltCompMatchPtr
128
130 if (cur == NULL) {
132 "xsltNewCompMatch : out of memory error\n");
133 return(NULL);
134 }
135 memset(cur, 0, sizeof(xsltCompMatch));
136 cur->maxStep = 10;
137 cur->nbStep = 0;
139 cur->maxStep);
140 if (cur->steps == NULL) {
142 "xsltNewCompMatch : out of memory error\n");
143 xmlFree(cur);
144 return(NULL);
145 }
146 cur->nsNr = 0;
147 cur->nsList = NULL;
148 cur->direct = 0;
149 return(cur);
150}
151
158static void
161 int i;
162
163 if (comp == NULL)
164 return;
165 if (comp->pattern != NULL)
166 xmlFree((xmlChar *)comp->pattern);
167 if (comp->nsList != NULL)
168 xmlFree(comp->nsList);
169 for (i = 0;i < comp->nbStep;i++) {
170 op = &comp->steps[i];
171 if (op->value != NULL)
172 xmlFree(op->value);
173 if (op->value2 != NULL)
174 xmlFree(op->value2);
175 if (op->value3 != NULL)
176 xmlFree(op->value3);
177 if (op->comp != NULL)
178 xmlXPathFreeCompExpr(op->comp);
179 }
180 xmlFree(comp->steps);
181 memset(comp, -1, sizeof(xsltCompMatch));
182 xmlFree(comp);
183}
184
191void
194
195 while (comp != NULL) {
196 cur = comp;
197 comp = comp->next;
199 }
200}
201
202static void
206}
207
217void xsltNormalizeCompSteps(void *payload,
218 void *data, const xmlChar *name ATTRIBUTE_UNUSED) {
219 xsltCompMatchPtr comp = payload;
221 int ix;
222
223 for (ix = 0; ix < comp->nbStep; ix++) {
224 comp->steps[ix].previousExtra += style->extrasNr;
225 comp->steps[ix].indexExtra += style->extrasNr;
226 comp->steps[ix].lenExtra += style->extrasNr;
227 }
228}
229
242
244 if (cur == NULL) {
246 "xsltNewParserContext : malloc failed\n");
247 return(NULL);
248 }
249 memset(cur, 0, sizeof(xsltParserContext));
250 cur->style = style;
251 cur->ctxt = ctxt;
252 return(cur);
253}
254
261static void
263 if (ctxt == NULL)
264 return;
265 memset(ctxt, -1, sizeof(xsltParserContext));
266 xmlFree(ctxt);
267}
268
281static int
283 xsltOp op, xmlChar * value, xmlChar * value2, int novar)
284{
285 if (comp->nbStep >= comp->maxStep) {
286 xsltStepOpPtr tmp;
287
288 tmp = (xsltStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
289 sizeof(xsltStepOp));
290 if (tmp == NULL) {
292 "xsltCompMatchAdd: memory re-allocation failure.\n");
293 if (ctxt->style != NULL)
294 ctxt->style->errors++;
295 if (value)
296 xmlFree(value);
297 if (value2)
298 xmlFree(value2);
299 return (-1);
300 }
301 comp->maxStep *= 2;
302 comp->steps = tmp;
303 }
304 comp->steps[comp->nbStep].op = op;
305 comp->steps[comp->nbStep].value = value;
306 comp->steps[comp->nbStep].value2 = value2;
307 comp->steps[comp->nbStep].value3 = NULL;
308 comp->steps[comp->nbStep].comp = NULL;
309 if (ctxt->ctxt != NULL) {
310 comp->steps[comp->nbStep].previousExtra =
312 comp->steps[comp->nbStep].indexExtra =
314 comp->steps[comp->nbStep].lenExtra =
316 } else {
317 comp->steps[comp->nbStep].previousExtra =
319 comp->steps[comp->nbStep].indexExtra =
321 comp->steps[comp->nbStep].lenExtra =
323 }
324 if (op == XSLT_OP_PREDICATE) {
325 int flags = 0;
326
327#ifdef XML_XPATH_NOVAR
328 if (novar != 0)
329 flags = XML_XPATH_NOVAR;
330#endif
331 comp->steps[comp->nbStep].comp = xsltXPathCompileFlags(ctxt->style,
332 value, flags);
333 if (comp->steps[comp->nbStep].comp == NULL) {
334 xsltTransformError(NULL, ctxt->style, ctxt->elem,
335 "Failed to compile predicate\n");
336 if (ctxt->style != NULL)
337 ctxt->style->errors++;
338 }
339 }
340 comp->nbStep++;
341 return (0);
342}
343
350static void
352 int i;
353 int j = comp->nbStep - 1;
354
355 if (j > 0) {
356 register xmlChar *tmp;
357 register xsltOp op;
358 register xmlXPathCompExprPtr expr;
359 register int t;
360 i = j - 1;
361 tmp = comp->steps[i].value;
362 comp->steps[i].value = comp->steps[j].value;
363 comp->steps[j].value = tmp;
364 tmp = comp->steps[i].value2;
365 comp->steps[i].value2 = comp->steps[j].value2;
366 comp->steps[j].value2 = tmp;
367 tmp = comp->steps[i].value3;
368 comp->steps[i].value3 = comp->steps[j].value3;
369 comp->steps[j].value3 = tmp;
370 op = comp->steps[i].op;
371 comp->steps[i].op = comp->steps[j].op;
372 comp->steps[j].op = op;
373 expr = comp->steps[i].comp;
374 comp->steps[i].comp = comp->steps[j].comp;
375 comp->steps[j].comp = expr;
376 t = comp->steps[i].previousExtra;
377 comp->steps[i].previousExtra = comp->steps[j].previousExtra;
378 comp->steps[j].previousExtra = t;
379 t = comp->steps[i].indexExtra;
380 comp->steps[i].indexExtra = comp->steps[j].indexExtra;
381 comp->steps[j].indexExtra = t;
382 t = comp->steps[i].lenExtra;
383 comp->steps[i].lenExtra = comp->steps[j].lenExtra;
384 comp->steps[j].lenExtra = t;
385 }
386}
387
395static void
397 int i = 0;
398 int j = comp->nbStep - 1;
399
400 while (j > i) {
401 register xmlChar *tmp;
402 register xsltOp op;
403 register xmlXPathCompExprPtr expr;
404 register int t;
405
406 tmp = comp->steps[i].value;
407 comp->steps[i].value = comp->steps[j].value;
408 comp->steps[j].value = tmp;
409 tmp = comp->steps[i].value2;
410 comp->steps[i].value2 = comp->steps[j].value2;
411 comp->steps[j].value2 = tmp;
412 tmp = comp->steps[i].value3;
413 comp->steps[i].value3 = comp->steps[j].value3;
414 comp->steps[j].value3 = tmp;
415 op = comp->steps[i].op;
416 comp->steps[i].op = comp->steps[j].op;
417 comp->steps[j].op = op;
418 expr = comp->steps[i].comp;
419 comp->steps[i].comp = comp->steps[j].comp;
420 comp->steps[j].comp = expr;
421 t = comp->steps[i].previousExtra;
422 comp->steps[i].previousExtra = comp->steps[j].previousExtra;
423 comp->steps[j].previousExtra = t;
424 t = comp->steps[i].indexExtra;
425 comp->steps[i].indexExtra = comp->steps[j].indexExtra;
426 comp->steps[j].indexExtra = t;
427 t = comp->steps[i].lenExtra;
428 comp->steps[i].lenExtra = comp->steps[j].lenExtra;
429 comp->steps[j].lenExtra = t;
430 j--;
431 i++;
432 }
433 xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0);
434
435 /*
436 * Detect consecutive XSLT_OP_PREDICATE indicating a direct matching
437 * should be done.
438 */
439 for (i = 0;i < comp->nbStep - 1;i++) {
440 if ((comp->steps[i].op == XSLT_OP_PREDICATE) &&
441 (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) {
442
443 comp->direct = 1;
444 if (comp->pattern[0] != '/') {
445 xmlChar *query;
446
447 query = xmlStrdup((const xmlChar *)"//");
448 query = xmlStrcat(query, comp->pattern);
449
450 xmlFree((xmlChar *) comp->pattern);
451 comp->pattern = query;
452 }
453 break;
454 }
455 }
456}
457
458/************************************************************************
459 * *
460 * The interpreter for the precompiled patterns *
461 * *
462 ************************************************************************/
463
464static int
466 int step, xmlNodePtr node) {
467 if ((states->states == NULL) || (states->maxstates <= 0)) {
468 states->maxstates = 4;
469 states->nbstates = 0;
470 states->states = xmlMalloc(4 * sizeof(xsltStepState));
471 }
472 else if (states->maxstates <= states->nbstates) {
473 xsltStepState *tmp;
474
475 tmp = (xsltStepStatePtr) xmlRealloc(states->states,
476 2 * states->maxstates * sizeof(xsltStepState));
477 if (tmp == NULL) {
479 "xsltPatPushState: memory re-allocation failure.\n");
481 return(-1);
482 }
483 states->states = tmp;
484 states->maxstates *= 2;
485 }
486 states->states[states->nbstates].step = step;
487 states->states[states->nbstates++].node = node;
488#if 0
489 fprintf(stderr, "Push: %d, %s\n", step, node->name);
490#endif
491 return(0);
492}
493
494static void
496 xmlXPathFreeObject((xmlXPathObjectPtr) obj);
497}
498
512static int
515 xsltStepOpPtr sel = NULL;
516 xmlDocPtr prevdoc;
517 xmlDocPtr doc;
518 xmlXPathObjectPtr list;
519 int ix, j;
520 int nocache = 0;
521 int isRVT;
522
523 doc = node->doc;
524 if (XSLT_IS_RES_TREE_FRAG(doc))
525 isRVT = 1;
526 else
527 isRVT = 0;
528 sel = &comp->steps[0]; /* store extra in first step arbitrarily */
529
530 prevdoc = (xmlDocPtr)
532 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
533 list = (xmlXPathObjectPtr)
535
536 if ((list == NULL) || (prevdoc != doc)) {
537 xmlXPathObjectPtr newlist;
538 xmlNodePtr parent = node->parent;
539 xmlDocPtr olddoc;
540 xmlNodePtr oldnode;
541 int oldNsNr, oldContextSize, oldProximityPosition;
542 xmlNsPtr *oldNamespaces;
543
544 oldnode = ctxt->xpathCtxt->node;
545 olddoc = ctxt->xpathCtxt->doc;
546 oldNsNr = ctxt->xpathCtxt->nsNr;
547 oldNamespaces = ctxt->xpathCtxt->namespaces;
548 oldContextSize = ctxt->xpathCtxt->contextSize;
549 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
550 ctxt->xpathCtxt->node = node;
551 ctxt->xpathCtxt->doc = doc;
552 ctxt->xpathCtxt->namespaces = nsList;
553 ctxt->xpathCtxt->nsNr = nsNr;
554 newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt);
555 ctxt->xpathCtxt->node = oldnode;
556 ctxt->xpathCtxt->doc = olddoc;
557 ctxt->xpathCtxt->namespaces = oldNamespaces;
558 ctxt->xpathCtxt->nsNr = oldNsNr;
559 ctxt->xpathCtxt->contextSize = oldContextSize;
560 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
561 if (newlist == NULL)
562 return(-1);
563 if (newlist->type != XPATH_NODESET) {
564 xmlXPathFreeObject(newlist);
565 return(-1);
566 }
567 ix = 0;
568
569 if ((parent == NULL) || (node->doc == NULL) || isRVT)
570 nocache = 1;
571
572 if (nocache == 0) {
573 if (list != NULL)
574 xmlXPathFreeObject(list);
575 list = newlist;
576
577 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) =
578 (void *) list;
580 (void *) doc;
581 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
582 0;
585 } else
586 list = newlist;
587 }
588 if ((list->nodesetval == NULL) ||
589 (list->nodesetval->nodeNr <= 0)) {
590 if (nocache == 1)
591 xmlXPathFreeObject(list);
592 return(0);
593 }
594 /* TODO: store the index and use it for the scan */
595 if (ix == 0) {
596 for (j = 0;j < list->nodesetval->nodeNr;j++) {
597 if (list->nodesetval->nodeTab[j] == node) {
598 if (nocache == 1)
599 xmlXPathFreeObject(list);
600 return(1);
601 }
602 }
603 } else {
604 }
605 if (nocache == 1)
606 xmlXPathFreeObject(list);
607 return(0);
608}
609
620static int
622 xsltStepOpPtr step) {
623 switch (step->op) {
624 case XSLT_OP_ROOT:
625 if ((node->type == XML_DOCUMENT_NODE) ||
626#ifdef LIBXML_DOCB_ENABLED
627 (node->type == XML_DOCB_DOCUMENT_NODE) ||
628#endif
629 (node->type == XML_HTML_DOCUMENT_NODE))
630 return(1);
631 if ((node->type == XML_ELEMENT_NODE) && (node->name[0] == ' '))
632 return(1);
633 return(0);
634 case XSLT_OP_ELEM:
635 if (node->type != XML_ELEMENT_NODE)
636 return(0);
637 if (step->value == NULL)
638 return(1);
639 if (step->value[0] != node->name[0])
640 return(0);
641 if (!xmlStrEqual(step->value, node->name))
642 return(0);
643
644 /* Namespace test */
645 if (node->ns == NULL) {
646 if (step->value2 != NULL)
647 return(0);
648 } else if (node->ns->href != NULL) {
649 if (step->value2 == NULL)
650 return(0);
651 if (!xmlStrEqual(step->value2, node->ns->href))
652 return(0);
653 }
654 return(1);
655 case XSLT_OP_ATTR:
656 if (node->type != XML_ATTRIBUTE_NODE)
657 return(0);
658 if (step->value != NULL) {
659 if (step->value[0] != node->name[0])
660 return(0);
661 if (!xmlStrEqual(step->value, node->name))
662 return(0);
663 }
664 /* Namespace test */
665 if (node->ns == NULL) {
666 if (step->value2 != NULL)
667 return(0);
668 } else if (step->value2 != NULL) {
669 if (!xmlStrEqual(step->value2, node->ns->href))
670 return(0);
671 }
672 return(1);
673 case XSLT_OP_ID: {
674 /* TODO Handle IDs decently, must be done differently */
676
677 if (node->type != XML_ELEMENT_NODE)
678 return(0);
679
680 id = xmlGetID(node->doc, step->value);
681 if ((id == NULL) || (id->parent != node))
682 return(0);
683 break;
684 }
685 case XSLT_OP_KEY: {
686 xmlNodeSetPtr list;
687 int indx;
688
689 list = xsltGetKey(ctxt, step->value,
690 step->value3, step->value2);
691 if (list == NULL)
692 return(0);
693 for (indx = 0;indx < list->nodeNr;indx++)
694 if (list->nodeTab[indx] == node)
695 break;
696 if (indx >= list->nodeNr)
697 return(0);
698 break;
699 }
700 case XSLT_OP_NS:
701 if (node->type != XML_ELEMENT_NODE)
702 return(0);
703 if (node->ns == NULL) {
704 if (step->value != NULL)
705 return(0);
706 } else if (node->ns->href != NULL) {
707 if (step->value == NULL)
708 return(0);
709 if (!xmlStrEqual(step->value, node->ns->href))
710 return(0);
711 }
712 break;
713 case XSLT_OP_ALL:
714 if (node->type != XML_ELEMENT_NODE)
715 return(0);
716 break;
717 case XSLT_OP_PI:
718 if (node->type != XML_PI_NODE)
719 return(0);
720 if (step->value != NULL) {
721 if (!xmlStrEqual(step->value, node->name))
722 return(0);
723 }
724 break;
725 case XSLT_OP_COMMENT:
726 if (node->type != XML_COMMENT_NODE)
727 return(0);
728 break;
729 case XSLT_OP_TEXT:
730 if ((node->type != XML_TEXT_NODE) &&
731 (node->type != XML_CDATA_SECTION_NODE))
732 return(0);
733 break;
734 case XSLT_OP_NODE:
735 switch (node->type) {
736 case XML_ELEMENT_NODE:
738 case XML_PI_NODE:
739 case XML_COMMENT_NODE:
740 case XML_TEXT_NODE:
741 break;
742 default:
743 return(0);
744 }
745 break;
746 default:
748 "xsltTestStepMatch: unexpected step op %d\n",
749 step->op);
750 return(-1);
751 }
752
753 return(1);
754}
755
768static int
771 xsltStepOpPtr sel) {
772 xmlNodePtr oldNode;
773 xmlDocPtr doc;
774 int oldCS, oldCP;
775 int pos = 0, len = 0;
776 int isRVT;
777 int match;
778
779 if (step->value == NULL)
780 return(0);
781 if (step->comp == NULL)
782 return(0);
783 if (sel == NULL)
784 return(0);
785
786 doc = node->doc;
787 if (XSLT_IS_RES_TREE_FRAG(doc))
788 isRVT = 1;
789 else
790 isRVT = 0;
791
792 /*
793 * Recompute contextSize and proximityPosition.
794 *
795 * This could be improved in the following ways:
796 *
797 * - Skip recomputation if predicates don't use position() or last()
798 * - Keep data for multiple parents. This would require a hash table
799 * or an unused member in xmlNode.
800 * - Store node test results in a bitmap to avoid computing them twice.
801 */
802 oldCS = ctxt->xpathCtxt->contextSize;
803 oldCP = ctxt->xpathCtxt->proximityPosition;
804 {
805 xmlNodePtr previous;
806 int nocache = 0;
807
808 previous = (xmlNodePtr)
810 if ((previous != NULL) &&
811 (previous->parent == node->parent)) {
812 /*
813 * just walk back to adjust the index
814 */
815 int indx = 0;
816 xmlNodePtr sibling = node;
817
818 while (sibling != NULL) {
819 if (sibling == previous)
820 break;
821 if (xsltTestStepMatch(ctxt, sibling, sel))
822 indx++;
823 sibling = sibling->prev;
824 }
825 if (sibling == NULL) {
826 /* hum going backward in document order ... */
827 indx = 0;
828 sibling = node;
829 while (sibling != NULL) {
830 if (sibling == previous)
831 break;
832 if (xsltTestStepMatch(ctxt, sibling, sel))
833 indx--;
834 sibling = sibling->next;
835 }
836 }
837 if (sibling != NULL) {
838 pos = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) + indx;
839 /*
840 * If the node is in a Value Tree we need to
841 * save len, but cannot cache the node!
842 * (bugs 153137 and 158840)
843 */
844 if (node->doc != NULL) {
845 len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
846 if (!isRVT) {
848 sel->previousExtra, ptr) = node;
849 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
850 }
851 }
852 } else
853 pos = 0;
854 } else {
855 /*
856 * recompute the index
857 */
858 xmlNodePtr parent = node->parent;
859 xmlNodePtr siblings = NULL;
860
861 if (parent) siblings = parent->children;
862
863 while (siblings != NULL) {
864 if (siblings == node) {
865 len++;
866 pos = len;
867 } else if (xsltTestStepMatch(ctxt, siblings, sel)) {
868 len++;
869 }
870 siblings = siblings->next;
871 }
872 if ((parent == NULL) || (node->doc == NULL))
873 nocache = 1;
874 else {
875 while (parent->parent != NULL)
876 parent = parent->parent;
877 if (((parent->type != XML_DOCUMENT_NODE) &&
878 (parent->type != XML_HTML_DOCUMENT_NODE)) ||
879 (parent != (xmlNodePtr) node->doc))
880 nocache = 1;
881 }
882 }
883 if (pos != 0) {
884 ctxt->xpathCtxt->contextSize = len;
885 ctxt->xpathCtxt->proximityPosition = pos;
886 /*
887 * If the node is in a Value Tree we cannot
888 * cache it !
889 */
890 if ((!isRVT) && (node->doc != NULL) &&
891 (nocache == 0)) {
893 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
894 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
895 }
896 }
897 }
898
899 oldNode = ctxt->node;
900 ctxt->node = node;
901
902 match = xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList, comp->nsNr);
903
904 if (pos != 0) {
905 ctxt->xpathCtxt->contextSize = oldCS;
906 ctxt->xpathCtxt->proximityPosition = oldCP;
907 }
908 ctxt->node = oldNode;
909
910 return match;
911}
912
925static int
927 xmlNodePtr matchNode, const xmlChar *mode,
928 const xmlChar *modeURI) {
929 int i;
930 int found = 0;
931 xmlNodePtr node = matchNode;
932 xmlNodePtr oldInst;
933 xsltStepOpPtr step, sel = NULL;
934 xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
935
936 if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) {
938 "xsltTestCompMatch: null arg\n");
939 return(-1);
940 }
941 if (mode != NULL) {
942 if (comp->mode == NULL)
943 return(0);
944 /*
945 * both mode strings must be interned on the stylesheet dictionary
946 */
947 if (comp->mode != mode)
948 return(0);
949 } else {
950 if (comp->mode != NULL)
951 return(0);
952 }
953 if (modeURI != NULL) {
954 if (comp->modeURI == NULL)
955 return(0);
956 /*
957 * both modeURI strings must be interned on the stylesheet dictionary
958 */
959 if (comp->modeURI != modeURI)
960 return(0);
961 } else {
962 if (comp->modeURI != NULL)
963 return(0);
964 }
965
966 /* Some XPath functions rely on inst being set correctly. */
967 oldInst = ctxt->inst;
968 ctxt->inst = comp->node;
969
970 i = 0;
971restart:
972 for (;i < comp->nbStep;i++) {
973 step = &comp->steps[i];
974 if (step->op != XSLT_OP_PREDICATE)
975 sel = step;
976 switch (step->op) {
977 case XSLT_OP_END:
978 goto found;
979 case XSLT_OP_PARENT:
980 if ((node->type == XML_DOCUMENT_NODE) ||
981 (node->type == XML_HTML_DOCUMENT_NODE) ||
982#ifdef LIBXML_DOCB_ENABLED
983 (node->type == XML_DOCB_DOCUMENT_NODE) ||
984#endif
985 (node->type == XML_NAMESPACE_DECL))
986 goto rollback;
987 node = node->parent;
988 if (node == NULL)
989 goto rollback;
990 if (step->value == NULL)
991 continue;
992 if (step->value[0] != node->name[0])
993 goto rollback;
994 if (!xmlStrEqual(step->value, node->name))
995 goto rollback;
996 /* Namespace test */
997 if (node->ns == NULL) {
998 if (step->value2 != NULL)
999 goto rollback;
1000 } else if (node->ns->href != NULL) {
1001 if (step->value2 == NULL)
1002 goto rollback;
1003 if (!xmlStrEqual(step->value2, node->ns->href))
1004 goto rollback;
1005 }
1006 continue;
1007 case XSLT_OP_ANCESTOR:
1008 /* TODO: implement coalescing of ANCESTOR/NODE ops */
1009 if (step->value == NULL) {
1010 step = &comp->steps[i+1];
1011 if (step->op == XSLT_OP_ROOT)
1012 goto found;
1013 /* added NS, ID and KEY as a result of bug 168208 */
1014 if ((step->op != XSLT_OP_ELEM) &&
1015 (step->op != XSLT_OP_ALL) &&
1016 (step->op != XSLT_OP_NS) &&
1017 (step->op != XSLT_OP_ID) &&
1018 (step->op != XSLT_OP_KEY))
1019 goto rollback;
1020 }
1021 if (node == NULL)
1022 goto rollback;
1023 if ((node->type == XML_DOCUMENT_NODE) ||
1024 (node->type == XML_HTML_DOCUMENT_NODE) ||
1025#ifdef LIBXML_DOCB_ENABLED
1026 (node->type == XML_DOCB_DOCUMENT_NODE) ||
1027#endif
1028 (node->type == XML_NAMESPACE_DECL))
1029 goto rollback;
1030 node = node->parent;
1031 if ((step->op != XSLT_OP_ELEM) && step->op != XSLT_OP_ALL) {
1032 xsltPatPushState(ctxt, &states, i, node);
1033 continue;
1034 }
1035 i++;
1036 sel = step;
1037 if (step->value == NULL) {
1038 xsltPatPushState(ctxt, &states, i - 1, node);
1039 continue;
1040 }
1041 while (node != NULL) {
1042 if ((node->type == XML_ELEMENT_NODE) &&
1043 (step->value[0] == node->name[0]) &&
1044 (xmlStrEqual(step->value, node->name))) {
1045 /* Namespace test */
1046 if (node->ns == NULL) {
1047 if (step->value2 == NULL)
1048 break;
1049 } else if (node->ns->href != NULL) {
1050 if ((step->value2 != NULL) &&
1051 (xmlStrEqual(step->value2, node->ns->href)))
1052 break;
1053 }
1054 }
1055 node = node->parent;
1056 }
1057 if (node == NULL)
1058 goto rollback;
1059 xsltPatPushState(ctxt, &states, i - 1, node);
1060 continue;
1061 case XSLT_OP_PREDICATE: {
1062 /*
1063 * When there is cascading XSLT_OP_PREDICATE or a predicate
1064 * after an op which hasn't been optimized yet, then use a
1065 * direct computation approach. It's not done directly
1066 * at the beginning of the routine to filter out as much
1067 * as possible this costly computation.
1068 */
1069 if (comp->direct) {
1070 found = xsltTestCompMatchDirect(ctxt, comp, matchNode,
1071 comp->nsList, comp->nsNr);
1072 goto exit;
1073 }
1074
1075 if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel))
1076 goto rollback;
1077
1078 break;
1079 }
1080 default:
1081 if (xsltTestStepMatch(ctxt, node, step) != 1)
1082 goto rollback;
1083 break;
1084 }
1085 }
1086found:
1087 found = 1;
1088exit:
1089 ctxt->inst = oldInst;
1090 if (states.states != NULL) {
1091 /* Free the rollback states */
1092 xmlFree(states.states);
1093 }
1094 return found;
1095rollback:
1096 /* got an error try to rollback */
1097 if (states.states == NULL || states.nbstates <= 0) {
1098 found = 0;
1099 goto exit;
1100 }
1101 states.nbstates--;
1102 i = states.states[states.nbstates].step;
1103 node = states.states[states.nbstates].node;
1104#if 0
1105 fprintf(stderr, "Pop: %d, %s\n", i, node->name);
1106#endif
1107 goto restart;
1108}
1109
1120int
1122 xsltCompMatchPtr comp) {
1123 int ret;
1124
1125 if ((ctxt == NULL) || (node == NULL))
1126 return(-1);
1127 while (comp != NULL) {
1128 ret = xsltTestCompMatch(ctxt, comp, node, NULL, NULL);
1129 if (ret == 1)
1130 return(1);
1131 comp = comp->next;
1132 }
1133 return(0);
1134}
1135
1143void
1145 xsltStepOpPtr sel;
1146 xmlXPathObjectPtr list;
1147
1148 if ((ctxt == NULL) || (comp == NULL))
1149 return;
1150
1151 sel = &comp->steps[0];
1152 list = (xmlXPathObjectPtr) XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
1153
1154 if (list != NULL) {
1155 xmlXPathFreeObject(list);
1156
1157 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) = NULL;
1159 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = 0;
1161 }
1162}
1163
1164/************************************************************************
1165 * *
1166 * Dedicated parser for templates *
1167 * *
1168 ************************************************************************/
1169
1170#define CUR (*ctxt->cur)
1171#define SKIP(val) ctxt->cur += (val)
1172#define NXT(val) ctxt->cur[(val)]
1173#define CUR_PTR ctxt->cur
1174
1175#define SKIP_BLANKS \
1176 while (xmlIsBlank_ch(CUR)) NEXT
1177
1178#define CURRENT (*ctxt->cur)
1179#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
1180
1181
1182#define PUSH(op, val, val2, novar) \
1183 if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto error;
1184
1185#define SWAP() \
1186 xsltSwapTopCompMatch(ctxt->comp);
1187
1188#define XSLT_ERROR(X) \
1189 { xsltError(ctxt, __FILE__, __LINE__, X); \
1190 ctxt->error = (X); return; }
1191
1192#define XSLT_ERROR0(X) \
1193 { xsltError(ctxt, __FILE__, __LINE__, X); \
1194 ctxt->error = (X); return(0); }
1195
1208static xmlChar *
1210 const xmlChar *q, *cur;
1211 xmlChar *ret = NULL;
1212 int val, len;
1213
1215 if (CUR == '"') {
1216 NEXT;
1217 cur = q = CUR_PTR;
1219 while ((xmlIsCharQ(val)) && (val != '"')) {
1220 cur += len;
1222 }
1223 if (!xmlIsCharQ(val)) {
1224 ctxt->error = 1;
1225 return(NULL);
1226 } else {
1227 ret = xmlStrndup(q, cur - q);
1228 }
1229 cur += len;
1230 CUR_PTR = cur;
1231 } else if (CUR == '\'') {
1232 NEXT;
1233 cur = q = CUR_PTR;
1235 while ((xmlIsCharQ(val)) && (val != '\'')) {
1236 cur += len;
1238 }
1239 if (!xmlIsCharQ(val)) {
1240 ctxt->error = 1;
1241 return(NULL);
1242 } else {
1243 ret = xmlStrndup(q, cur - q);
1244 }
1245 cur += len;
1246 CUR_PTR = cur;
1247 } else {
1248 ctxt->error = 1;
1249 return(NULL);
1250 }
1251 return(ret);
1252}
1253
1263static xmlChar *
1265 const xmlChar *q, *cur;
1266 xmlChar *ret = NULL;
1267 int val, len;
1268
1270
1271 cur = q = CUR_PTR;
1273 if (!xmlIsBaseCharQ(val) && !xmlIsIdeographicQ(val) && (val != '_'))
1274 return(NULL);
1275
1277 xmlIsDigitQ(val) ||
1278 (val == '.') || (val == '-') ||
1279 (val == '_') ||
1282 cur += len;
1284 }
1285 ret = xmlStrndup(q, cur - q);
1286 CUR_PTR = cur;
1287 return(ret);
1288}
1289
1290/*
1291 * xsltCompileIdKeyPattern:
1292 * @ctxt: the compilation context
1293 * @name: a preparsed name
1294 * @aid: whether id/key are allowed there
1295 * @novar: flag to prohibit xslt var
1296 *
1297 * Compile the XSLT LocationIdKeyPattern
1298 * [3] IdKeyPattern ::= 'id' '(' Literal ')'
1299 * | 'key' '(' Literal ',' Literal ')'
1300 *
1301 * also handle NodeType and PI from:
1302 *
1303 * [7] NodeTest ::= NameTest
1304 * | NodeType '(' ')'
1305 * | 'processing-instruction' '(' Literal ')'
1306 */
1307static void
1309 int aid, int novar, xsltAxis axis) {
1310 xmlChar *lit = NULL;
1311 xmlChar *lit2 = NULL;
1312
1313 if (CUR != '(') {
1315 "xsltCompileIdKeyPattern : ( expected\n");
1316 ctxt->error = 1;
1317 return;
1318 }
1319 if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) {
1320 if (axis != 0) {
1322 "xsltCompileIdKeyPattern : NodeTest expected\n");
1323 ctxt->error = 1;
1324 return;
1325 }
1326 NEXT;
1328 lit = xsltScanLiteral(ctxt);
1329 if (ctxt->error) {
1331 "xsltCompileIdKeyPattern : Literal expected\n");
1332 xmlFree(lit);
1333 return;
1334 }
1336 if (CUR != ')') {
1338 "xsltCompileIdKeyPattern : ) expected\n");
1339 xmlFree(lit);
1340 ctxt->error = 1;
1341 return;
1342 }
1343 NEXT;
1344 PUSH(XSLT_OP_ID, lit, NULL, novar);
1345 lit = NULL;
1346 } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) {
1347 if (axis != 0) {
1349 "xsltCompileIdKeyPattern : NodeTest expected\n");
1350 ctxt->error = 1;
1351 return;
1352 }
1353 NEXT;
1355 lit = xsltScanLiteral(ctxt);
1356 if (ctxt->error) {
1358 "xsltCompileIdKeyPattern : Literal expected\n");
1359 xmlFree(lit);
1360 return;
1361 }
1363 if (CUR != ',') {
1365 "xsltCompileIdKeyPattern : , expected\n");
1366 xmlFree(lit);
1367 ctxt->error = 1;
1368 return;
1369 }
1370 NEXT;
1372 lit2 = xsltScanLiteral(ctxt);
1373 if (ctxt->error) {
1375 "xsltCompileIdKeyPattern : Literal expected\n");
1376 xmlFree(lit);
1377 return;
1378 }
1380 if (CUR != ')') {
1382 "xsltCompileIdKeyPattern : ) expected\n");
1383 xmlFree(lit);
1384 xmlFree(lit2);
1385 ctxt->error = 1;
1386 return;
1387 }
1388 NEXT;
1389 /* URGENT TODO: support namespace in keys */
1390 PUSH(XSLT_OP_KEY, lit, lit2, novar);
1391 lit = NULL;
1392 lit2 = NULL;
1393 } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {
1394 NEXT;
1396 if (CUR != ')') {
1397 lit = xsltScanLiteral(ctxt);
1398 if (ctxt->error) {
1400 "xsltCompileIdKeyPattern : Literal expected\n");
1401 xmlFree(lit);
1402 return;
1403 }
1405 if (CUR != ')') {
1407 "xsltCompileIdKeyPattern : ) expected\n");
1408 ctxt->error = 1;
1409 xmlFree(lit);
1410 return;
1411 }
1412 }
1413 NEXT;
1414 PUSH(XSLT_OP_PI, lit, NULL, novar);
1415 lit = NULL;
1416 } else if (xmlStrEqual(name, (const xmlChar *)"text")) {
1417 NEXT;
1419 if (CUR != ')') {
1421 "xsltCompileIdKeyPattern : ) expected\n");
1422 ctxt->error = 1;
1423 return;
1424 }
1425 NEXT;
1426 PUSH(XSLT_OP_TEXT, NULL, NULL, novar);
1427 } else if (xmlStrEqual(name, (const xmlChar *)"comment")) {
1428 NEXT;
1430 if (CUR != ')') {
1432 "xsltCompileIdKeyPattern : ) expected\n");
1433 ctxt->error = 1;
1434 return;
1435 }
1436 NEXT;
1437 PUSH(XSLT_OP_COMMENT, NULL, NULL, novar);
1438 } else if (xmlStrEqual(name, (const xmlChar *)"node")) {
1439 NEXT;
1441 if (CUR != ')') {
1443 "xsltCompileIdKeyPattern : ) expected\n");
1444 ctxt->error = 1;
1445 return;
1446 }
1447 NEXT;
1448 if (axis == AXIS_ATTRIBUTE) {
1449 PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
1450 }
1451 else {
1452 PUSH(XSLT_OP_NODE, NULL, NULL, novar);
1453 }
1454 } else if (aid) {
1456 "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n");
1457 ctxt->error = 1;
1458 return;
1459 } else {
1461 "xsltCompileIdKeyPattern : node type\n");
1462 ctxt->error = 1;
1463 return;
1464 }
1465error:
1466 return;
1467}
1468
1491static void
1493 xmlChar *name = NULL;
1494 const xmlChar *URI = NULL;
1495 xmlChar *URL = NULL;
1496 int level;
1497 xsltAxis axis = 0;
1498
1500 if ((token == NULL) && (CUR == '@')) {
1501 NEXT;
1502 axis = AXIS_ATTRIBUTE;
1503 }
1504parse_node_test:
1505 if (token == NULL)
1506 token = xsltScanNCName(ctxt);
1507 if (token == NULL) {
1508 if (CUR == '*') {
1509 NEXT;
1510 if (axis == AXIS_ATTRIBUTE) {
1511 PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
1512 }
1513 else {
1514 PUSH(XSLT_OP_ALL, NULL, NULL, novar);
1515 }
1516 goto parse_predicate;
1517 } else {
1519 "xsltCompileStepPattern : Name expected\n");
1520 ctxt->error = 1;
1521 goto error;
1522 }
1523 }
1524
1525
1527 if (CUR == '(') {
1528 xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis);
1529 xmlFree(token);
1530 token = NULL;
1531 if (ctxt->error)
1532 goto error;
1533 } else if (CUR == ':') {
1534 NEXT;
1535 if (CUR != ':') {
1536 xmlChar *prefix = token;
1537 xmlNsPtr ns;
1538
1539 /*
1540 * This is a namespace match
1541 */
1542 token = xsltScanNCName(ctxt);
1543 ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);
1544 if (ns == NULL) {
1546 "xsltCompileStepPattern : no namespace bound to prefix %s\n",
1547 prefix);
1548 xmlFree(prefix);
1549 prefix=NULL;
1550 ctxt->error = 1;
1551 goto error;
1552 } else {
1553 URL = xmlStrdup(ns->href);
1554 }
1555 xmlFree(prefix);
1556 prefix=NULL;
1557 if (token == NULL) {
1558 if (CUR == '*') {
1559 NEXT;
1560 if (axis == AXIS_ATTRIBUTE) {
1561 PUSH(XSLT_OP_ATTR, NULL, URL, novar);
1562 URL = NULL;
1563 }
1564 else {
1565 PUSH(XSLT_OP_NS, URL, NULL, novar);
1566 URL = NULL;
1567 }
1568 } else {
1570 "xsltCompileStepPattern : Name expected\n");
1571 ctxt->error = 1;
1572 xmlFree(URL);
1573 goto error;
1574 }
1575 } else {
1576 if (axis == AXIS_ATTRIBUTE) {
1577 PUSH(XSLT_OP_ATTR, token, URL, novar);
1578 token = NULL;
1579 URL = NULL;
1580 }
1581 else {
1582 PUSH(XSLT_OP_ELEM, token, URL, novar);
1583 token = NULL;
1584 URL = NULL;
1585 }
1586 }
1587 } else {
1588 if (axis != 0) {
1590 "xsltCompileStepPattern : NodeTest expected\n");
1591 ctxt->error = 1;
1592 goto error;
1593 }
1594 NEXT;
1595 if (xmlStrEqual(token, (const xmlChar *) "child")) {
1596 axis = AXIS_CHILD;
1597 } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) {
1598 axis = AXIS_ATTRIBUTE;
1599 } else {
1601 "xsltCompileStepPattern : 'child' or 'attribute' expected\n");
1602 ctxt->error = 1;
1603 goto error;
1604 }
1605 xmlFree(token);
1606 token = NULL;
1608 token = xsltScanNCName(ctxt);
1609 goto parse_node_test;
1610 }
1611 } else {
1612 URI = xsltGetQNameURI(ctxt->elem, &token);
1613 if (token == NULL) {
1614 ctxt->error = 1;
1615 goto error;
1616 }
1617 if (URI != NULL)
1618 URL = xmlStrdup(URI);
1619 if (axis == AXIS_ATTRIBUTE) {
1620 PUSH(XSLT_OP_ATTR, token, URL, novar);
1621 token = NULL;
1622 URL = NULL;
1623 }
1624 else {
1625 PUSH(XSLT_OP_ELEM, token, URL, novar);
1626 token = NULL;
1627 URL = NULL;
1628 }
1629 }
1630parse_predicate:
1632 level = 0;
1633 while (CUR == '[') {
1634 const xmlChar *q;
1635 xmlChar *ret = NULL;
1636
1637 level++;
1638 NEXT;
1639 q = CUR_PTR;
1640 while (CUR != 0) {
1641 /* Skip over nested predicates */
1642 if (CUR == '[')
1643 level++;
1644 else if (CUR == ']') {
1645 level--;
1646 if (level == 0)
1647 break;
1648 } else if (CUR == '"') {
1649 NEXT;
1650 while ((CUR != 0) && (CUR != '"'))
1651 NEXT;
1652 } else if (CUR == '\'') {
1653 NEXT;
1654 while ((CUR != 0) && (CUR != '\''))
1655 NEXT;
1656 }
1657 NEXT;
1658 }
1659 if (CUR == 0) {
1661 "xsltCompileStepPattern : ']' expected\n");
1662 ctxt->error = 1;
1663 return;
1664 }
1665 ret = xmlStrndup(q, CUR_PTR - q);
1666 PUSH(XSLT_OP_PREDICATE, ret, NULL, novar);
1667 ret = NULL;
1668 /* push the predicate lower than local test */
1669 SWAP();
1670 NEXT;
1672 }
1673 return;
1674error:
1675 if (token != NULL)
1676 xmlFree(token);
1677 if (name != NULL)
1678 xmlFree(name);
1679}
1680
1694static void
1696 xsltCompileStepPattern(ctxt, token, novar);
1697 if (ctxt->error)
1698 goto error;
1700 while ((CUR != 0) && (CUR != '|')) {
1701 if ((CUR == '/') && (NXT(1) == '/')) {
1702 PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
1703 NEXT;
1704 NEXT;
1706 xsltCompileStepPattern(ctxt, NULL, novar);
1707 } else if (CUR == '/') {
1708 PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1709 NEXT;
1711 xsltCompileStepPattern(ctxt, NULL, novar);
1712 } else {
1713 ctxt->error = 1;
1714 }
1715 if (ctxt->error)
1716 goto error;
1718 }
1719error:
1720 return;
1721}
1722
1735static void
1738 if ((CUR == '/') && (NXT(1) == '/')) {
1739 /*
1740 * since we reverse the query
1741 * a leading // can be safely ignored
1742 */
1743 NEXT;
1744 NEXT;
1745 ctxt->comp->priority = 0.5; /* '//' means not 0 priority */
1747 } else if (CUR == '/') {
1748 /*
1749 * We need to find root as the parent
1750 */
1751 NEXT;
1753 PUSH(XSLT_OP_ROOT, NULL, NULL, novar);
1754 if ((CUR != 0) && (CUR != '|')) {
1755 PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1757 }
1758 } else if (CUR == '*') {
1760 } else if (CUR == '@') {
1762 } else {
1763 xmlChar *name;
1764 name = xsltScanNCName(ctxt);
1765 if (name == NULL) {
1767 "xsltCompileLocationPathPattern : Name expected\n");
1768 ctxt->error = 1;
1769 return;
1770 }
1772 if ((CUR == '(') && !xmlXPathIsNodeType(name)) {
1773 xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0);
1774 xmlFree(name);
1775 name = NULL;
1776 if (ctxt->error)
1777 return;
1778 if ((CUR == '/') && (NXT(1) == '/')) {
1779 PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
1780 NEXT;
1781 NEXT;
1784 } else if (CUR == '/') {
1785 PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1786 NEXT;
1789 }
1790 return;
1791 }
1793 }
1794error:
1795 return;
1796}
1797
1815static xsltCompMatchPtr
1818 xsltTransformContextPtr runtime, int novar) {
1820 xsltCompMatchPtr element, first = NULL, previous = NULL;
1821 int current, start, end, level, j;
1822
1823 if (pattern == NULL) {
1825 "xsltCompilePattern : NULL pattern\n");
1826 return(NULL);
1827 }
1828
1829 ctxt = xsltNewParserContext(style, runtime);
1830 if (ctxt == NULL)
1831 return(NULL);
1832 ctxt->doc = doc;
1833 ctxt->elem = node;
1834 current = end = 0;
1835 while (pattern[current] != 0) {
1836 start = current;
1837 while (xmlIsBlank_ch(pattern[current]))
1838 current++;
1839 end = current;
1840 level = 0;
1841 while ((pattern[end] != 0) && ((pattern[end] != '|') || (level != 0))) {
1842 if (pattern[end] == '[')
1843 level++;
1844 else if (pattern[end] == ']')
1845 level--;
1846 else if (pattern[end] == '\'') {
1847 end++;
1848 while ((pattern[end] != 0) && (pattern[end] != '\''))
1849 end++;
1850 } else if (pattern[end] == '"') {
1851 end++;
1852 while ((pattern[end] != 0) && (pattern[end] != '"'))
1853 end++;
1854 }
1855 if (pattern[end] == 0)
1856 break;
1857 end++;
1858 }
1859 if (current == end) {
1861 "xsltCompilePattern : NULL pattern\n");
1862 goto error;
1863 }
1865 if (element == NULL) {
1866 goto error;
1867 }
1868 if (first == NULL)
1869 first = element;
1870 else if (previous != NULL)
1871 previous->next = element;
1872 previous = element;
1873
1874 ctxt->comp = element;
1875 ctxt->base = xmlStrndup(&pattern[start], end - start);
1876 if (ctxt->base == NULL)
1877 goto error;
1878 ctxt->cur = &(ctxt->base)[current - start];
1879 element->pattern = ctxt->base;
1880 element->node = node;
1881 element->nsList = xmlGetNsList(doc, node);
1882 j = 0;
1883 if (element->nsList != NULL) {
1884 while (element->nsList[j] != NULL)
1885 j++;
1886 }
1887 element->nsNr = j;
1888
1889
1890#ifdef WITH_XSLT_DEBUG_PATTERN
1892 "xsltCompilePattern : parsing '%s'\n",
1893 element->pattern);
1894#endif
1895 /*
1896 Preset default priority to be zero.
1897 This may be changed by xsltCompileLocationPathPattern.
1898 */
1899 element->priority = 0;
1900 xsltCompileLocationPathPattern(ctxt, novar);
1901 if (ctxt->error) {
1903 "xsltCompilePattern : failed to compile '%s'\n",
1904 element->pattern);
1905 if (style != NULL) style->errors++;
1906 goto error;
1907 }
1908
1909 /*
1910 * Reverse for faster interpretation.
1911 */
1913
1914 /*
1915 * Set-up the priority
1916 */
1917 if (element->priority == 0) { /* if not yet determined */
1918 if (((element->steps[0].op == XSLT_OP_ELEM) ||
1919 (element->steps[0].op == XSLT_OP_ATTR) ||
1920 (element->steps[0].op == XSLT_OP_PI)) &&
1921 (element->steps[0].value != NULL) &&
1922 (element->steps[1].op == XSLT_OP_END)) {
1923 ; /* previously preset */
1924 } else if ((element->steps[0].op == XSLT_OP_ATTR) &&
1925 (element->steps[0].value2 != NULL) &&
1926 (element->steps[1].op == XSLT_OP_END)) {
1927 element->priority = -0.25;
1928 } else if ((element->steps[0].op == XSLT_OP_NS) &&
1929 (element->steps[0].value != NULL) &&
1930 (element->steps[1].op == XSLT_OP_END)) {
1931 element->priority = -0.25;
1932 } else if ((element->steps[0].op == XSLT_OP_ATTR) &&
1933 (element->steps[0].value == NULL) &&
1934 (element->steps[0].value2 == NULL) &&
1935 (element->steps[1].op == XSLT_OP_END)) {
1936 element->priority = -0.5;
1937 } else if (((element->steps[0].op == XSLT_OP_PI) ||
1938 (element->steps[0].op == XSLT_OP_TEXT) ||
1939 (element->steps[0].op == XSLT_OP_ALL) ||
1940 (element->steps[0].op == XSLT_OP_NODE) ||
1941 (element->steps[0].op == XSLT_OP_COMMENT)) &&
1942 (element->steps[1].op == XSLT_OP_END)) {
1943 element->priority = -0.5;
1944 } else {
1945 element->priority = 0.5;
1946 }
1947 }
1948#ifdef WITH_XSLT_DEBUG_PATTERN
1950 "xsltCompilePattern : parsed %s, default priority %f\n",
1951 element->pattern, element->priority);
1952#endif
1953 if (pattern[end] == '|')
1954 end++;
1955 current = end;
1956 }
1957 if (end == 0) {
1959 "xsltCompilePattern : NULL pattern\n");
1960 if (style != NULL) style->errors++;
1961 goto error;
1962 }
1963
1965 return(first);
1966
1967error:
1968 if (ctxt != NULL)
1970 if (first != NULL)
1972 return(NULL);
1973}
1974
1994 xsltTransformContextPtr runtime) {
1995 return (xsltCompilePatternInternal(pattern, doc, node, style, runtime, 0));
1996}
1997
1998/************************************************************************
1999 * *
2000 * Module interfaces *
2001 * *
2002 ************************************************************************/
2003
2015int
2017 const xmlChar *mode, const xmlChar *modeURI) {
2019 /*
2020 * 'top' will point to style->xxxMatch ptr - declaring as 'void'
2021 * avoids gcc 'type-punned pointer' warning.
2022 */
2024 const xmlChar *name = NULL;
2025 float priority; /* the priority */
2026
2027 if ((style == NULL) || (cur == NULL))
2028 return(-1);
2029
2030 if (cur->next != NULL)
2031 cur->position = cur->next->position + 1;
2032
2033 /* Register named template */
2034 if (cur->name != NULL) {
2035 if (style->namedTemplates == NULL) {
2036 style->namedTemplates = xmlHashCreate(10);
2037 if (style->namedTemplates == NULL)
2038 return(-1);
2039 }
2040 else {
2041 void *dup = xmlHashLookup2(style->namedTemplates, cur->name,
2042 cur->nameURI);
2043 if (dup != NULL) {
2045 "xsl:template: error duplicate name '%s'\n",
2046 cur->name);
2047 style->errors++;
2048 return(-1);
2049 }
2050 }
2051
2052 xmlHashAddEntry2(style->namedTemplates, cur->name, cur->nameURI, cur);
2053 }
2054
2055 if (cur->match == NULL) {
2056 if (cur->name == NULL) {
2058 "xsl:template: need to specify match or name attribute\n");
2059 style->errors++;
2060 return(-1);
2061 }
2062 return(0);
2063 }
2064
2065 priority = cur->priority;
2066 pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem,
2067 style, NULL, 1);
2068 if (pat == NULL)
2069 return(-1);
2070 while (pat) {
2071 next = pat->next;
2072 pat->next = NULL;
2073 name = NULL;
2074
2075 pat->template = cur;
2076 if (mode != NULL)
2077 pat->mode = xmlDictLookup(style->dict, mode, -1);
2078 if (modeURI != NULL)
2079 pat->modeURI = xmlDictLookup(style->dict, modeURI, -1);
2081 pat->priority = priority;
2082
2083 /*
2084 * insert it in the hash table list corresponding to its lookup name
2085 */
2086 switch (pat->steps[0].op) {
2087 case XSLT_OP_ATTR:
2088 if (pat->steps[0].value != NULL)
2089 name = pat->steps[0].value;
2090 else
2091 top = &(style->attrMatch);
2092 break;
2093 case XSLT_OP_PARENT:
2094 case XSLT_OP_ANCESTOR:
2095 top = &(style->elemMatch);
2096 break;
2097 case XSLT_OP_ROOT:
2098 top = &(style->rootMatch);
2099 break;
2100 case XSLT_OP_KEY:
2101 top = &(style->keyMatch);
2102 break;
2103 case XSLT_OP_ID:
2104 /* TODO optimize ID !!! */
2105 case XSLT_OP_NS:
2106 case XSLT_OP_ALL:
2107 top = &(style->elemMatch);
2108 break;
2109 case XSLT_OP_END:
2110 case XSLT_OP_PREDICATE:
2112 "xsltAddTemplate: invalid compiled pattern\n");
2113 xsltFreeCompMatch(pat);
2114 return(-1);
2115 /*
2116 * TODO: some flags at the top level about type based patterns
2117 * would be faster than inclusion in the hash table.
2118 */
2119 case XSLT_OP_PI:
2120 if (pat->steps[0].value != NULL)
2121 name = pat->steps[0].value;
2122 else
2123 top = &(style->piMatch);
2124 break;
2125 case XSLT_OP_COMMENT:
2126 top = &(style->commentMatch);
2127 break;
2128 case XSLT_OP_TEXT:
2129 top = &(style->textMatch);
2130 break;
2131 case XSLT_OP_ELEM:
2132 case XSLT_OP_NODE:
2133 if (pat->steps[0].value != NULL)
2134 name = pat->steps[0].value;
2135 else
2136 top = &(style->elemMatch);
2137 break;
2138 }
2139 if (name != NULL) {
2140 if (style->templatesHash == NULL) {
2141 style->templatesHash = xmlHashCreate(1024);
2142 if (style->templatesHash == NULL) {
2143 xsltFreeCompMatch(pat);
2144 return(-1);
2145 }
2146 xmlHashAddEntry3(style->templatesHash, name, mode, modeURI, pat);
2147 } else {
2148 list = (xsltCompMatchPtr) xmlHashLookup3(style->templatesHash,
2149 name, mode, modeURI);
2150 if (list == NULL) {
2151 xmlHashAddEntry3(style->templatesHash, name,
2152 mode, modeURI, pat);
2153 } else {
2154 /*
2155 * Note '<=' since one must choose among the matching
2156 * template rules that are left, the one that occurs
2157 * last in the stylesheet
2158 */
2159 if (list->priority <= pat->priority) {
2160 pat->next = list;
2161 xmlHashUpdateEntry3(style->templatesHash, name,
2162 mode, modeURI, pat, NULL);
2163 } else {
2164 while (list->next != NULL) {
2165 if (list->next->priority <= pat->priority)
2166 break;
2167 list = list->next;
2168 }
2169 pat->next = list->next;
2170 list->next = pat;
2171 }
2172 }
2173 }
2174 } else if (top != NULL) {
2175 list = *top;
2176 if (list == NULL) {
2177 *top = pat;
2178 pat->next = NULL;
2179 } else if (list->priority <= pat->priority) {
2180 pat->next = list;
2181 *top = pat;
2182 } else {
2183 while (list->next != NULL) {
2184 if (list->next->priority <= pat->priority)
2185 break;
2186 list = list->next;
2187 }
2188 pat->next = list->next;
2189 list->next = pat;
2190 }
2191 } else {
2193 "xsltAddTemplate: invalid compiled pattern\n");
2194 xsltFreeCompMatch(pat);
2195 return(-1);
2196 }
2197#ifdef WITH_XSLT_DEBUG_PATTERN
2198 if (mode)
2200 "added pattern : '%s' mode '%s' priority %f\n",
2201 pat->pattern, pat->mode, pat->priority);
2202 else
2204 "added pattern : '%s' priority %f\n",
2205 pat->pattern, pat->priority);
2206#endif
2207
2208 pat = next;
2209 }
2210 return(0);
2211}
2212
2213static int
2215{
2216 if ((ctxt == NULL) || (contextNode == NULL)) {
2217 xsltTransformError(ctxt, NULL, ctxt->inst,
2218 "Internal error in xsltComputeAllKeys(): "
2219 "Bad arguments.\n");
2220 return(-1);
2221 }
2222
2223 if (ctxt->document == NULL) {
2224 /*
2225 * The document info will only be NULL if we have a RTF.
2226 */
2227 if (contextNode->doc->_private != NULL)
2228 goto doc_info_mismatch;
2229 /*
2230 * On-demand creation of the document info (needed for keys).
2231 */
2232 ctxt->document = xsltNewDocument(ctxt, contextNode->doc);
2233 if (ctxt->document == NULL)
2234 return(-1);
2235 }
2236 return xsltInitAllDocKeys(ctxt);
2237
2238doc_info_mismatch:
2239 xsltTransformError(ctxt, NULL, ctxt->inst,
2240 "Internal error in xsltComputeAllKeys(): "
2241 "The context's document info doesn't match the "
2242 "document info of the current result tree.\n");
2243 ctxt->state = XSLT_STATE_STOPPED;
2244 return(-1);
2245}
2246
2261{
2262 xsltStylesheetPtr curstyle;
2264 const xmlChar *name = NULL;
2266 float priority;
2267 int keyed = 0;
2268
2269 if ((ctxt == NULL) || (node == NULL))
2270 return(NULL);
2271
2272 if (style == NULL) {
2273 curstyle = ctxt->style;
2274 } else {
2275 curstyle = xsltNextImport(style);
2276 }
2277
2278 while ((curstyle != NULL) && (curstyle != style)) {
2280 /* TODO : handle IDs/keys here ! */
2281 if (curstyle->templatesHash != NULL) {
2282 /*
2283 * Use the top name as selector
2284 */
2285 switch (node->type) {
2286 case XML_ELEMENT_NODE:
2287 if (node->name[0] == ' ')
2288 break;
2289 /* Intentional fall-through */
2290 case XML_ATTRIBUTE_NODE:
2291 case XML_PI_NODE:
2292 name = node->name;
2293 break;
2294 case XML_DOCUMENT_NODE:
2296 case XML_TEXT_NODE:
2298 case XML_COMMENT_NODE:
2300 case XML_ENTITY_NODE:
2303 case XML_NOTATION_NODE:
2304 case XML_DTD_NODE:
2305 case XML_ELEMENT_DECL:
2306 case XML_ATTRIBUTE_DECL:
2307 case XML_ENTITY_DECL:
2308 case XML_NAMESPACE_DECL:
2309 case XML_XINCLUDE_START:
2310 case XML_XINCLUDE_END:
2311 break;
2312 default:
2313 return(NULL);
2314
2315 }
2316 }
2317 if (name != NULL) {
2318 /*
2319 * find the list of applicable expressions based on the name
2320 */
2322 name, ctxt->mode, ctxt->modeURI);
2323 } else
2324 list = NULL;
2325 while (list != NULL) {
2326 if (xsltTestCompMatch(ctxt, list, node,
2327 ctxt->mode, ctxt->modeURI) == 1) {
2328 ret = list->template;
2329 priority = list->priority;
2330 break;
2331 }
2332 list = list->next;
2333 }
2334 list = NULL;
2335
2336 /*
2337 * find alternate generic matches
2338 */
2339 switch (node->type) {
2340 case XML_ELEMENT_NODE:
2341 if (node->name[0] == ' ')
2342 list = curstyle->rootMatch;
2343 else
2344 list = curstyle->elemMatch;
2345 if (node->psvi != NULL) keyed = 1;
2346 break;
2347 case XML_ATTRIBUTE_NODE: {
2349
2350 list = curstyle->attrMatch;
2351 attr = (xmlAttrPtr) node;
2352 if (attr->psvi != NULL) keyed = 1;
2353 break;
2354 }
2355 case XML_PI_NODE:
2356 list = curstyle->piMatch;
2357 if (node->psvi != NULL) keyed = 1;
2358 break;
2359 case XML_DOCUMENT_NODE:
2361 xmlDocPtr doc;
2362
2363 list = curstyle->rootMatch;
2364 doc = (xmlDocPtr) node;
2365 if (doc->psvi != NULL) keyed = 1;
2366 break;
2367 }
2368 case XML_TEXT_NODE:
2370 list = curstyle->textMatch;
2371 if (node->psvi != NULL) keyed = 1;
2372 break;
2373 case XML_COMMENT_NODE:
2374 list = curstyle->commentMatch;
2375 if (node->psvi != NULL) keyed = 1;
2376 break;
2378 case XML_ENTITY_NODE:
2381 case XML_NOTATION_NODE:
2382 case XML_DTD_NODE:
2383 case XML_ELEMENT_DECL:
2384 case XML_ATTRIBUTE_DECL:
2385 case XML_ENTITY_DECL:
2386 case XML_NAMESPACE_DECL:
2387 case XML_XINCLUDE_START:
2388 case XML_XINCLUDE_END:
2389 break;
2390 default:
2391 break;
2392 }
2393 while ((list != NULL) &&
2394 ((ret == NULL) ||
2395 (list->priority > priority) ||
2396 ((list->priority == priority) &&
2397 (list->template->position > ret->position)))) {
2398 if (xsltTestCompMatch(ctxt, list, node,
2399 ctxt->mode, ctxt->modeURI) == 1) {
2400 ret = list->template;
2401 priority = list->priority;
2402 break;
2403 }
2404 list = list->next;
2405 }
2406 /*
2407 * Some of the tests for elements can also apply to documents
2408 */
2409 if ((node->type == XML_DOCUMENT_NODE) ||
2410 (node->type == XML_HTML_DOCUMENT_NODE) ||
2411 (node->type == XML_TEXT_NODE)) {
2412 list = curstyle->elemMatch;
2413 while ((list != NULL) &&
2414 ((ret == NULL) ||
2415 (list->priority > priority) ||
2416 ((list->priority == priority) &&
2417 (list->template->position > ret->position)))) {
2418 if (xsltTestCompMatch(ctxt, list, node,
2419 ctxt->mode, ctxt->modeURI) == 1) {
2420 ret = list->template;
2421 priority = list->priority;
2422 break;
2423 }
2424 list = list->next;
2425 }
2426 } else if ((node->type == XML_PI_NODE) ||
2427 (node->type == XML_COMMENT_NODE)) {
2428 list = curstyle->elemMatch;
2429 while ((list != NULL) &&
2430 ((ret == NULL) ||
2431 (list->priority > priority) ||
2432 ((list->priority == priority) &&
2433 (list->template->position > ret->position)))) {
2434 if (xsltTestCompMatch(ctxt, list, node,
2435 ctxt->mode, ctxt->modeURI) == 1) {
2436 ret = list->template;
2437 priority = list->priority;
2438 break;
2439 }
2440 list = list->next;
2441 }
2442 }
2443
2444keyed_match:
2445 if (keyed) {
2446 list = curstyle->keyMatch;
2447 while ((list != NULL) &&
2448 ((ret == NULL) ||
2449 (list->priority > priority) ||
2450 ((list->priority == priority) &&
2451 (list->template->position > ret->position)))) {
2452 if (xsltTestCompMatch(ctxt, list, node,
2453 ctxt->mode, ctxt->modeURI) == 1) {
2454 ret = list->template;
2455 priority = list->priority;
2456 break;
2457 }
2458 list = list->next;
2459 }
2460 }
2461 else if (ctxt->hasTemplKeyPatterns &&
2462 ((ctxt->document == NULL) ||
2463 (ctxt->document->nbKeysComputed < ctxt->nbKeys)))
2464 {
2465 /*
2466 * Compute all remaining keys for this document.
2467 *
2468 * REVISIT TODO: I think this could be further optimized.
2469 */
2470 if (xsltComputeAllKeys(ctxt, node) == -1)
2471 goto error;
2472
2473 switch (node->type) {
2474 case XML_ELEMENT_NODE:
2475 if (node->psvi != NULL) keyed = 1;
2476 break;
2477 case XML_ATTRIBUTE_NODE:
2478 if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1;
2479 break;
2480 case XML_TEXT_NODE:
2482 case XML_COMMENT_NODE:
2483 case XML_PI_NODE:
2484 if (node->psvi != NULL) keyed = 1;
2485 break;
2486 case XML_DOCUMENT_NODE:
2488 if (((xmlDocPtr) node)->psvi != NULL) keyed = 1;
2489 break;
2490 default:
2491 break;
2492 }
2493 if (keyed)
2494 goto keyed_match;
2495 }
2496 if (ret != NULL)
2497 return(ret);
2498
2499 /*
2500 * Cycle on next curstylesheet import.
2501 */
2502 curstyle = xsltNextImport(curstyle);
2503 }
2504
2505error:
2506 return(NULL);
2507}
2508
2516void
2518}
2519
2526void
2528 if (style->templatesHash != NULL)
2530 if (style->rootMatch != NULL)
2531 xsltFreeCompMatchList(style->rootMatch);
2532 if (style->keyMatch != NULL)
2533 xsltFreeCompMatchList(style->keyMatch);
2534 if (style->elemMatch != NULL)
2535 xsltFreeCompMatchList(style->elemMatch);
2536 if (style->attrMatch != NULL)
2537 xsltFreeCompMatchList(style->attrMatch);
2538 if (style->parentMatch != NULL)
2539 xsltFreeCompMatchList(style->parentMatch);
2540 if (style->textMatch != NULL)
2541 xsltFreeCompMatchList(style->textMatch);
2542 if (style->piMatch != NULL)
2543 xsltFreeCompMatchList(style->piMatch);
2544 if (style->commentMatch != NULL)
2545 xsltFreeCompMatchList(style->commentMatch);
2546 if (style->namedTemplates != NULL)
2547 xmlHashFree(style->namedTemplates, NULL);
2548}
2549
Arabic default style
Definition: afstyles.h:94
void restart(int argc, const char *argv[])
Definition: cmds.c:2115
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY * rollback
Definition: btrfs_drv.h:1365
#define xmlIsCombiningQ(c)
Definition: chvalid.h:132
#define xmlIsBlank_ch(c)
Definition: chvalid.h:88
#define xmlIsDigitQ(c)
Definition: chvalid.h:152
#define xmlIsIdeographicQ(c)
Definition: chvalid.h:184
#define xmlIsExtenderQ(c)
Definition: chvalid.h:172
#define xmlIsCharQ(c)
Definition: chvalid.h:118
#define xmlIsBaseCharQ(c)
Definition: chvalid.h:76
Definition: list.h:37
struct list * next
Definition: list.h:38
#define NULL
Definition: types.h:112
struct _xsltParserContext xsltParserContext
Definition: pattern.c:99
xsltStepStates * xsltStepStatesPtr
Definition: pattern.c:58
static xmlChar * xsltScanLiteral(xsltParserContextPtr ctxt)
Definition: pattern.c:1209
#define NEXT
Definition: pattern.c:1179
static void xsltFreeParserContext(xsltParserContextPtr ctxt)
Definition: pattern.c:262
xsltAxis
Definition: pattern.c:45
@ AXIS_CHILD
Definition: pattern.c:46
@ AXIS_ATTRIBUTE
Definition: pattern.c:47
static void xsltCompileRelativePathPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar)
Definition: pattern.c:1695
static int xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr node, xsltStepOpPtr step, xsltStepOpPtr sel)
Definition: pattern.c:769
int xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, const xmlChar *mode, const xmlChar *modeURI)
Definition: pattern.c:2016
static int xsltComputeAllKeys(xsltTransformContextPtr ctxt, xmlNodePtr contextNode)
Definition: pattern.c:2214
static void xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, int aid, int novar, xsltAxis axis)
Definition: pattern.c:1308
static void xsltFreeCompMatchListEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: pattern.c:203
#define SKIP_BLANKS
Definition: pattern.c:1175
static xsltCompMatchPtr xsltNewCompMatch(void)
Definition: pattern.c:126
static void xsltReverseCompMatch(xsltParserContextPtr ctxt, xsltCompMatchPtr comp)
Definition: pattern.c:396
static void xmlXPathFreeObjectWrapper(void *obj)
Definition: pattern.c:495
static xsltParserContextPtr xsltNewParserContext(xsltStylesheetPtr style, xsltTransformContextPtr ctxt)
Definition: pattern.c:240
xsltTemplatePtr xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStylesheetPtr style)
Definition: pattern.c:2259
xsltCompMatchPtr xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node, xsltStylesheetPtr style, xsltTransformContextPtr runtime)
Definition: pattern.c:1992
static xsltCompMatchPtr xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node, xsltStylesheetPtr style, xsltTransformContextPtr runtime, int novar)
Definition: pattern.c:1816
static void xsltSwapTopCompMatch(xsltCompMatchPtr comp)
Definition: pattern.c:351
void xsltCleanupTemplates(xsltStylesheetPtr style ATTRIBUTE_UNUSED)
Definition: pattern.c:2517
static int xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp, xsltOp op, xmlChar *value, xmlChar *value2, int novar)
Definition: pattern.c:282
static xmlChar * xsltScanNCName(xsltParserContextPtr ctxt)
Definition: pattern.c:1264
static int xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr node, xmlNsPtr *nsList, int nsNr)
Definition: pattern.c:513
static int xsltPatPushState(xsltTransformContextPtr ctxt, xsltStepStates *states, int step, xmlNodePtr node)
Definition: pattern.c:465
static void xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar)
Definition: pattern.c:1492
xsltStepState * xsltStepStatePtr
Definition: pattern.c:51
static int xsltTestStepMatch(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStepOpPtr step)
Definition: pattern.c:621
int xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltCompMatchPtr comp)
Definition: pattern.c:1121
void xsltFreeCompMatchList(xsltCompMatchPtr comp)
Definition: pattern.c:192
static int xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr matchNode, const xmlChar *mode, const xmlChar *modeURI)
Definition: pattern.c:926
void xsltCompMatchClearCache(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp)
Definition: pattern.c:1144
xsltParserContext * xsltParserContextPtr
Definition: pattern.c:100
#define SWAP()
Definition: pattern.c:1185
void xsltNormalizeCompSteps(void *payload, void *data, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: pattern.c:217
static void xsltCompileLocationPathPattern(xsltParserContextPtr ctxt, int novar)
Definition: pattern.c:1736
static void xsltFreeCompMatch(xsltCompMatchPtr comp)
Definition: pattern.c:159
xsltOp
Definition: pattern.c:27
@ XSLT_OP_PREDICATE
Definition: pattern.c:42
@ XSLT_OP_PARENT
Definition: pattern.c:32
@ XSLT_OP_TEXT
Definition: pattern.c:40
@ XSLT_OP_END
Definition: pattern.c:28
@ XSLT_OP_ID
Definition: pattern.c:34
@ XSLT_OP_ALL
Definition: pattern.c:37
@ XSLT_OP_ELEM
Definition: pattern.c:30
@ XSLT_OP_NODE
Definition: pattern.c:41
@ XSLT_OP_ATTR
Definition: pattern.c:31
@ XSLT_OP_PI
Definition: pattern.c:38
@ XSLT_OP_COMMENT
Definition: pattern.c:39
@ XSLT_OP_KEY
Definition: pattern.c:35
@ XSLT_OP_ANCESTOR
Definition: pattern.c:33
@ XSLT_OP_ROOT
Definition: pattern.c:29
@ XSLT_OP_NS
Definition: pattern.c:36
void xsltFreeTemplateHashes(xsltStylesheetPtr style)
Definition: pattern.c:2527
#define NXT(val)
Definition: pattern.c:1172
#define PUSH(op, val, val2, novar)
Definition: pattern.c:1182
#define CUR_PTR
Definition: pattern.c:1173
xsltStepOp * xsltStepOpPtr
Definition: pattern.c:66
#define CUR
Definition: pattern.c:1170
UINT op
Definition: effect.c:236
xsltDocumentPtr xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc)
Definition: documents.c:127
r parent
Definition: btrfs.c:3010
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLint level
Definition: gl.h:1546
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble t
Definition: gl.h:2047
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLubyte * pattern
Definition: glext.h:7787
GLenum mode
Definition: glext.h:6217
GLbitfield flags
Definition: glext.h:7161
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:37
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:251
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
int xsltInitAllDocKeys(xsltTransformContextPtr ctxt)
Definition: keys.c:535
xmlNodeSetPtr xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI, const xmlChar *value)
Definition: keys.c:417
#define dup
Definition: syshdrs.h:51
xsltCompMatch * xsltCompMatchPtr
Definition: pattern.h:29
#define error(str)
Definition: mkdosfs.c:1605
struct task_struct * current
Definition: linux.c:32
static PVOID ptr
Definition: dispmode.c:27
static DWORD DWORD DWORD DWORD * steps
Definition: cursoricon.c:1638
static int priority
Definition: timer.c:163
XMLPUBFUN int XMLCALL xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len)
static unsigned __int64 next
Definition: rand_nt.c:6
#define list
Definition: rosglue.h:35
XMLPUBFUN const xmlChar *XMLCALL xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:867
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:250
XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata)
Definition: hash.c:406
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:322
XMLPUBFUN void *XMLCALL xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3)
Definition: hash.c:769
XMLPUBFUN int XMLCALL xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata, xmlHashDeallocator f)
Definition: hash.c:647
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:176
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:476
XMLPUBFUN int XMLCALL xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata)
Definition: hash.c:531
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
xmlNode * xmlNodePtr
Definition: tree.h:488
xmlDoc * xmlDocPtr
Definition: tree.h:550
#define XML_DOCB_DOCUMENT_NODE
Definition: tree.h:184
@ XML_DOCUMENT_TYPE_NODE
Definition: tree.h:169
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_ENTITY_DECL
Definition: tree.h:176
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_CDATA_SECTION_NODE
Definition: tree.h:163
@ XML_TEXT_NODE
Definition: tree.h:162
@ XML_XINCLUDE_START
Definition: tree.h:178
@ XML_ENTITY_NODE
Definition: tree.h:165
@ XML_PI_NODE
Definition: tree.h:166
@ XML_XINCLUDE_END
Definition: tree.h:179
@ XML_DOCUMENT_FRAG_NODE
Definition: tree.h:170
@ XML_COMMENT_NODE
Definition: tree.h:167
@ XML_DTD_NODE
Definition: tree.h:173
@ XML_NAMESPACE_DECL
Definition: tree.h:177
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
@ XML_ELEMENT_NODE
Definition: tree.h:160
@ XML_ELEMENT_DECL
Definition: tree.h:174
@ XML_ENTITY_REF_NODE
Definition: tree.h:164
@ XML_NOTATION_NODE
Definition: tree.h:171
@ XML_ATTRIBUTE_DECL
Definition: tree.h:175
xmlAttr * xmlAttrPtr
Definition: tree.h:433
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
Definition: tree.h:434
Definition: tree.h:551
void * psvi
Definition: tree.h:581
Definition: tree.h:489
struct _xmlNode * next
Definition: tree.h:496
struct _xmlDoc * doc
Definition: tree.h:498
struct _xmlNode * parent
Definition: tree.h:495
struct _xmlNode * prev
Definition: tree.h:497
Definition: tree.h:389
xmlNsPtr * nsList
Definition: pattern.c:94
const xmlChar * pattern
Definition: pattern.c:84
struct _xsltCompMatch * next
Definition: pattern.c:82
xsltTemplatePtr template
Definition: pattern.c:87
xsltStepOpPtr steps
Definition: pattern.c:96
const xmlChar * mode
Definition: pattern.c:85
float priority
Definition: pattern.c:83
xmlNodePtr node
Definition: pattern.c:88
const xmlChar * modeURI
Definition: pattern.c:86
xmlDocPtr doc
Definition: pattern.c:106
xsltStylesheetPtr style
Definition: pattern.c:102
xsltCompMatchPtr comp
Definition: pattern.c:109
const xmlChar * cur
Definition: pattern.c:104
const xmlChar * base
Definition: pattern.c:105
xsltTransformContextPtr ctxt
Definition: pattern.c:103
xmlNodePtr elem
Definition: pattern.c:107
int indexExtra
Definition: pattern.c:77
xmlChar * value
Definition: pattern.c:69
int lenExtra
Definition: pattern.c:78
int previousExtra
Definition: pattern.c:76
xmlXPathCompExprPtr comp
Definition: pattern.c:72
xmlChar * value2
Definition: pattern.c:70
xsltOp op
Definition: pattern.c:68
xmlChar * value3
Definition: pattern.c:71
xmlNodePtr node
Definition: pattern.c:54
xsltStepStatePtr states
Definition: pattern.c:62
struct _xsltCompMatch * rootMatch
struct _xsltCompMatch * textMatch
struct _xsltCompMatch * elemMatch
struct _xsltCompMatch * piMatch
xmlHashTablePtr templatesHash
struct _xsltCompMatch * attrMatch
struct _xsltCompMatch * commentMatch
struct _xsltCompMatch * keyMatch
xsltTransformState state
const xmlChar * modeURI
xsltDocumentPtr document
xsltStylesheetPtr style
xmlXPathContextPtr xpathCtxt
const xmlChar * mode
Definition: cookie.c:202
Definition: query.h:87
Definition: match.c:28
Definition: name.c:39
Definition: mxnamespace.c:45
int xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, xmlNsPtr *nsList, int nsNr)
Definition: templates.c:39
Definition: dlist.c:348
Definition: pdh_main.c:94
XMLPUBFUN xmlAttrPtr XMLCALL xmlGetID(xmlDocPtr doc, const xmlChar *ID)
Definition: valid.c:2874
int ret
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:42
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
unsigned char xmlChar
Definition: xmlstring.h:28
#define XSLT_RUNTIME_EXTRA(ctxt, nr, typ)
#define XSLT_PAT_NO_PRIORITY
@ XSLT_STATE_STOPPED
#define XSLT_RUNTIME_EXTRA_LST(ctxt, nr)
#define XSLT_RUNTIME_EXTRA_FREE(ctxt, nr)
#define XSLT_IS_RES_TREE_FRAG(n)
Definition: xsltInternals.h:56
int xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
Definition: xslt.c:825
int xsltAllocateExtra(xsltStylesheetPtr style)
Definition: xslt.c:809
const xmlChar * xsltGetQNameURI(xmlNodePtr node, xmlChar **name)
Definition: xsltutils.c:753
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
xmlXPathCompExprPtr xsltXPathCompileFlags(xsltStylesheetPtr style, const xmlChar *str, int flags)
Definition: xsltutils.c:2313
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:502
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:548
void * xsltGenericDebugContext
Definition: xsltutils.c:549
void * xsltGenericErrorContext
Definition: xsltutils.c:503