ReactOS 0.4.16-dev-2206-gc56950d
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#define IN_LIBXSLT
18#include "libxslt.h"
19
20#include <string.h>
21
22#include <libxml/xmlmemory.h>
23#include <libxml/tree.h>
24#include <libxml/valid.h>
25#include <libxml/hash.h>
26#include <libxml/xmlerror.h>
28#include <libxml/xpath.h>
29#include "xslt.h"
30#include "xsltInternals.h"
31#include "xsltutils.h"
32#include "imports.h"
33#include "templates.h"
34#include "keys.h"
35#include "pattern.h"
36#include "documents.h"
37
38#ifdef WITH_XSLT_DEBUG
39#define WITH_XSLT_DEBUG_PATTERN
40#endif
41
42/*
43 * Types are private:
44 */
45
46typedef enum {
63
64typedef enum {
68
72 int step;
73 xmlNodePtr node;
74};
75
82};
83
84typedef struct _xsltStepOp xsltStepOp;
91 xmlXPathCompExprPtr comp;
92 /*
93 * Optimisations for count
94 */
98};
99
101 struct _xsltCompMatch *next; /* siblings in the name hash */
102 float priority; /* the priority */
103 const xmlChar *pattern; /* the pattern */
104 const xmlChar *mode; /* the mode */
105 const xmlChar *modeURI; /* the mode URI */
106 xsltTemplatePtr template; /* the associated template */
107 xmlNodePtr node; /* the containing element */
108
110 /* TODO fix the statically allocated size steps[] */
113 xmlNsPtr *nsList; /* the namespaces in scope */
114 int nsNr; /* the number of namespaces in scope */
115 xsltStepOpPtr steps; /* ops for computation */
116};
117
121 xsltStylesheetPtr style; /* the stylesheet */
122 xsltTransformContextPtr ctxt; /* the transformation or NULL */
123 const xmlChar *cur; /* the current char being parsed */
124 const xmlChar *base; /* the full expression */
125 xmlDocPtr doc; /* the source document */
126 xmlNodePtr elem; /* the source element */
127 int error; /* error code */
128 xsltCompMatchPtr comp; /* the result */
129};
130
131/************************************************************************
132 * *
133 * Type functions *
134 * *
135 ************************************************************************/
136
144static xsltCompMatchPtr
147
149 if (cur == NULL) {
151 "xsltNewCompMatch : out of memory error\n");
152 return(NULL);
153 }
154 memset(cur, 0, sizeof(xsltCompMatch));
155 cur->maxStep = 10;
156 cur->nbStep = 0;
158 cur->maxStep);
159 if (cur->steps == NULL) {
161 "xsltNewCompMatch : out of memory error\n");
162 xmlFree(cur);
163 return(NULL);
164 }
165 cur->nsNr = 0;
166 cur->nsList = NULL;
167 cur->direct = 0;
168 return(cur);
169}
170
177static void
180 int i;
181
182 if (comp == NULL)
183 return;
184 if (comp->pattern != NULL)
185 xmlFree((xmlChar *)comp->pattern);
186 if (comp->nsList != NULL)
187 xmlFree(comp->nsList);
188 for (i = 0;i < comp->nbStep;i++) {
189 op = &comp->steps[i];
190 if (op->value != NULL)
191 xmlFree(op->value);
192 if (op->value2 != NULL)
193 xmlFree(op->value2);
194 if (op->value3 != NULL)
195 xmlFree(op->value3);
196 if (op->comp != NULL)
197 xmlXPathFreeCompExpr(op->comp);
198 }
199 xmlFree(comp->steps);
200 memset(comp, -1, sizeof(xsltCompMatch));
201 xmlFree(comp);
202}
203
210void
213
214 while (comp != NULL) {
215 cur = comp;
216 comp = comp->next;
218 }
219}
220
221static void
225}
226
236void xsltNormalizeCompSteps(void *payload,
237 void *data, const xmlChar *name ATTRIBUTE_UNUSED) {
238 xsltCompMatchPtr comp = payload;
240 int ix;
241
242 for (ix = 0; ix < comp->nbStep; ix++) {
243 comp->steps[ix].previousExtra += style->extrasNr;
244 comp->steps[ix].indexExtra += style->extrasNr;
245 comp->steps[ix].lenExtra += style->extrasNr;
246 }
247}
248
261
263 if (cur == NULL) {
265 "xsltNewParserContext : malloc failed\n");
266 return(NULL);
267 }
268 memset(cur, 0, sizeof(xsltParserContext));
269 cur->style = style;
270 cur->ctxt = ctxt;
271 return(cur);
272}
273
280static void
282 if (ctxt == NULL)
283 return;
284 memset(ctxt, -1, sizeof(xsltParserContext));
285 xmlFree(ctxt);
286}
287
300static int
302 xsltOp op, xmlChar * value, xmlChar * value2, int novar)
303{
304 if (comp->nbStep >= comp->maxStep) {
305 xsltStepOpPtr tmp;
306
307 tmp = (xsltStepOpPtr) xmlRealloc(comp->steps, comp->maxStep * 2 *
308 sizeof(xsltStepOp));
309 if (tmp == NULL) {
311 "xsltCompMatchAdd: memory re-allocation failure.\n");
312 if (ctxt->style != NULL)
313 ctxt->style->errors++;
314 return (-1);
315 }
316 comp->maxStep *= 2;
317 comp->steps = tmp;
318 }
319 comp->steps[comp->nbStep].op = op;
320 comp->steps[comp->nbStep].value = value;
321 comp->steps[comp->nbStep].value2 = value2;
322 comp->steps[comp->nbStep].value3 = NULL;
323 comp->steps[comp->nbStep].comp = NULL;
324 if (ctxt->ctxt != NULL) {
325 comp->steps[comp->nbStep].previousExtra =
327 comp->steps[comp->nbStep].indexExtra =
329 comp->steps[comp->nbStep].lenExtra =
331 } else {
332 comp->steps[comp->nbStep].previousExtra =
334 comp->steps[comp->nbStep].indexExtra =
336 comp->steps[comp->nbStep].lenExtra =
338 }
339 if (op == XSLT_OP_PREDICATE) {
340 int flags = 0;
341
342#ifdef XML_XPATH_NOVAR
343 if (novar != 0)
344 flags = XML_XPATH_NOVAR;
345#endif
346 comp->steps[comp->nbStep].comp = xsltXPathCompileFlags(ctxt->style,
347 value, flags);
348 if (comp->steps[comp->nbStep].comp == NULL) {
349 xsltTransformError(NULL, ctxt->style, ctxt->elem,
350 "Failed to compile predicate\n");
351 if (ctxt->style != NULL)
352 ctxt->style->errors++;
353 }
354 }
355 comp->nbStep++;
356 return (0);
357}
358
365static void
367 int i;
368 int j = comp->nbStep - 1;
369
370 if (j > 0) {
371 register xmlChar *tmp;
372 register xsltOp op;
373 register xmlXPathCompExprPtr expr;
374 register int t;
375 i = j - 1;
376 tmp = comp->steps[i].value;
377 comp->steps[i].value = comp->steps[j].value;
378 comp->steps[j].value = tmp;
379 tmp = comp->steps[i].value2;
380 comp->steps[i].value2 = comp->steps[j].value2;
381 comp->steps[j].value2 = tmp;
382 tmp = comp->steps[i].value3;
383 comp->steps[i].value3 = comp->steps[j].value3;
384 comp->steps[j].value3 = tmp;
385 op = comp->steps[i].op;
386 comp->steps[i].op = comp->steps[j].op;
387 comp->steps[j].op = op;
388 expr = comp->steps[i].comp;
389 comp->steps[i].comp = comp->steps[j].comp;
390 comp->steps[j].comp = expr;
391 t = comp->steps[i].previousExtra;
392 comp->steps[i].previousExtra = comp->steps[j].previousExtra;
393 comp->steps[j].previousExtra = t;
394 t = comp->steps[i].indexExtra;
395 comp->steps[i].indexExtra = comp->steps[j].indexExtra;
396 comp->steps[j].indexExtra = t;
397 t = comp->steps[i].lenExtra;
398 comp->steps[i].lenExtra = comp->steps[j].lenExtra;
399 comp->steps[j].lenExtra = t;
400 }
401}
402
410static void
412 int i = 0;
413 int j = comp->nbStep - 1;
414
415 while (j > i) {
416 register xmlChar *tmp;
417 register xsltOp op;
418 register xmlXPathCompExprPtr expr;
419 register int t;
420
421 tmp = comp->steps[i].value;
422 comp->steps[i].value = comp->steps[j].value;
423 comp->steps[j].value = tmp;
424 tmp = comp->steps[i].value2;
425 comp->steps[i].value2 = comp->steps[j].value2;
426 comp->steps[j].value2 = tmp;
427 tmp = comp->steps[i].value3;
428 comp->steps[i].value3 = comp->steps[j].value3;
429 comp->steps[j].value3 = tmp;
430 op = comp->steps[i].op;
431 comp->steps[i].op = comp->steps[j].op;
432 comp->steps[j].op = op;
433 expr = comp->steps[i].comp;
434 comp->steps[i].comp = comp->steps[j].comp;
435 comp->steps[j].comp = expr;
436 t = comp->steps[i].previousExtra;
437 comp->steps[i].previousExtra = comp->steps[j].previousExtra;
438 comp->steps[j].previousExtra = t;
439 t = comp->steps[i].indexExtra;
440 comp->steps[i].indexExtra = comp->steps[j].indexExtra;
441 comp->steps[j].indexExtra = t;
442 t = comp->steps[i].lenExtra;
443 comp->steps[i].lenExtra = comp->steps[j].lenExtra;
444 comp->steps[j].lenExtra = t;
445 j--;
446 i++;
447 }
448 xsltCompMatchAdd(ctxt, comp, XSLT_OP_END, NULL, NULL, 0);
449
450 /*
451 * Detect consecutive XSLT_OP_PREDICATE indicating a direct matching
452 * should be done.
453 */
454 for (i = 0;i < comp->nbStep - 1;i++) {
455 if ((comp->steps[i].op == XSLT_OP_PREDICATE) &&
456 (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) {
457
458 comp->direct = 1;
459 if (comp->pattern[0] != '/') {
460 xmlChar *query;
461
462 query = xmlStrdup((const xmlChar *)"//");
463 query = xmlStrcat(query, comp->pattern);
464
465 xmlFree((xmlChar *) comp->pattern);
466 comp->pattern = query;
467 }
468 break;
469 }
470 }
471}
472
473/************************************************************************
474 * *
475 * The interpreter for the precompiled patterns *
476 * *
477 ************************************************************************/
478
479static int
481 int step, xmlNodePtr node) {
482 if (states->maxstates <= states->nbstates) {
483 xsltStepState *tmp;
484 int newMax = states->maxstates == 0 ? 4 : 2 * states->maxstates;
485
486 tmp = (xsltStepStatePtr) xmlRealloc(states->states,
487 newMax * sizeof(xsltStepState));
488 if (tmp == NULL) {
490 "xsltPatPushState: memory re-allocation failure.\n");
492 return(-1);
493 }
494 states->states = tmp;
495 states->maxstates = newMax;
496 }
497 states->states[states->nbstates].step = step;
498 states->states[states->nbstates++].node = node;
499#if 0
500 fprintf(stderr, "Push: %d, %s\n", step, node->name);
501#endif
502 return(0);
503}
504
505static void
507 xmlXPathFreeObject((xmlXPathObjectPtr) obj);
508}
509
523static int
525 xmlNodePtr node, xmlNsPtr *nsList, int nsNr) {
526 xsltStepOpPtr sel = NULL;
527 xmlDocPtr prevdoc;
528 xmlDocPtr doc;
529 xmlXPathObjectPtr list;
530 int ix, j;
531 int nocache = 0;
532 int isRVT;
533
534 doc = node->doc;
535 if (XSLT_IS_RES_TREE_FRAG(doc))
536 isRVT = 1;
537 else
538 isRVT = 0;
539 sel = &comp->steps[0]; /* store extra in first step arbitrarily */
540
541 prevdoc = (xmlDocPtr)
543 ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
544 list = (xmlXPathObjectPtr)
546
547 if ((list == NULL) || (prevdoc != doc)) {
548 xmlXPathObjectPtr newlist;
549 xmlNodePtr parent = node->parent;
550 xmlDocPtr olddoc;
551 xmlNodePtr oldnode;
552 int oldNsNr, oldContextSize, oldProximityPosition;
553 xmlNsPtr *oldNamespaces;
554
555 oldnode = ctxt->xpathCtxt->node;
556 olddoc = ctxt->xpathCtxt->doc;
557 oldNsNr = ctxt->xpathCtxt->nsNr;
558 oldNamespaces = ctxt->xpathCtxt->namespaces;
559 oldContextSize = ctxt->xpathCtxt->contextSize;
560 oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
561 ctxt->xpathCtxt->node = node;
562 ctxt->xpathCtxt->doc = doc;
563 ctxt->xpathCtxt->namespaces = nsList;
564 ctxt->xpathCtxt->nsNr = nsNr;
565 newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt);
566 ctxt->xpathCtxt->node = oldnode;
567 ctxt->xpathCtxt->doc = olddoc;
568 ctxt->xpathCtxt->namespaces = oldNamespaces;
569 ctxt->xpathCtxt->nsNr = oldNsNr;
570 ctxt->xpathCtxt->contextSize = oldContextSize;
571 ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
572 if (newlist == NULL)
573 return(-1);
574 if (newlist->type != XPATH_NODESET) {
575 xmlXPathFreeObject(newlist);
576 return(-1);
577 }
578 ix = 0;
579
580 if ((parent == NULL) || (node->doc == NULL) || isRVT)
581 nocache = 1;
582
583 if (nocache == 0) {
584 if (list != NULL)
585 xmlXPathFreeObject(list);
586 list = newlist;
587
588 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) =
589 (void *) list;
591 (void *) doc;
592 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
593 0;
596 } else
597 list = newlist;
598 }
599 if ((list->nodesetval == NULL) ||
600 (list->nodesetval->nodeNr <= 0)) {
601 if (nocache == 1)
602 xmlXPathFreeObject(list);
603 return(0);
604 }
605 /* TODO: store the index and use it for the scan */
606 if (ix == 0) {
607 for (j = 0;j < list->nodesetval->nodeNr;j++) {
608 if (list->nodesetval->nodeTab[j] == node) {
609 if (nocache == 1)
610 xmlXPathFreeObject(list);
611 return(1);
612 }
613 }
614 } else {
615 }
616 if (nocache == 1)
617 xmlXPathFreeObject(list);
618 return(0);
619}
620
631static int
633 xsltStepOpPtr step) {
634 switch (step->op) {
635 case XSLT_OP_ROOT:
636 if ((node->type == XML_DOCUMENT_NODE) ||
637#ifdef LIBXML_DOCB_ENABLED
638 (node->type == XML_DOCB_DOCUMENT_NODE) ||
639#endif
640 (node->type == XML_HTML_DOCUMENT_NODE))
641 return(1);
642 if ((node->type == XML_ELEMENT_NODE) && (node->name[0] == ' '))
643 return(1);
644 return(0);
645 case XSLT_OP_ELEM:
646 if (node->type != XML_ELEMENT_NODE)
647 return(0);
648 if (step->value == NULL)
649 return(1);
650 if (step->value[0] != node->name[0])
651 return(0);
652 if (!xmlStrEqual(step->value, node->name))
653 return(0);
654
655 /* Namespace test */
656 if (node->ns == NULL) {
657 if (step->value2 != NULL)
658 return(0);
659 } else if (node->ns->href != NULL) {
660 if (step->value2 == NULL)
661 return(0);
662 if (!xmlStrEqual(step->value2, node->ns->href))
663 return(0);
664 }
665 return(1);
666 case XSLT_OP_ATTR:
667 if (node->type != XML_ATTRIBUTE_NODE)
668 return(0);
669 if (step->value != NULL) {
670 if (step->value[0] != node->name[0])
671 return(0);
672 if (!xmlStrEqual(step->value, node->name))
673 return(0);
674 }
675 /* Namespace test */
676 if (node->ns == NULL) {
677 if (step->value2 != NULL)
678 return(0);
679 } else if (step->value2 != NULL) {
680 if (!xmlStrEqual(step->value2, node->ns->href))
681 return(0);
682 }
683 return(1);
684 case XSLT_OP_ID: {
685 /* TODO Handle IDs decently, must be done differently */
686 xmlAttrPtr id;
687
688 if (node->type != XML_ELEMENT_NODE)
689 return(0);
690
691 id = xmlGetID(node->doc, step->value);
692 if ((id == NULL) || (id->parent != node))
693 return(0);
694 break;
695 }
696 case XSLT_OP_KEY: {
697 xmlNodeSetPtr list;
698 int indx;
699
700 list = xsltGetKey(ctxt, step->value,
701 step->value3, step->value2);
702 if (list == NULL)
703 return(0);
704 for (indx = 0;indx < list->nodeNr;indx++)
705 if (list->nodeTab[indx] == node)
706 break;
707 if (indx >= list->nodeNr)
708 return(0);
709 break;
710 }
711 case XSLT_OP_NS:
712 if (node->type != XML_ELEMENT_NODE)
713 return(0);
714 if (node->ns == NULL) {
715 if (step->value != NULL)
716 return(0);
717 } else if (node->ns->href != NULL) {
718 if (step->value == NULL)
719 return(0);
720 if (!xmlStrEqual(step->value, node->ns->href))
721 return(0);
722 }
723 break;
724 case XSLT_OP_ALL:
725 if (node->type != XML_ELEMENT_NODE)
726 return(0);
727 break;
728 case XSLT_OP_PI:
729 if (node->type != XML_PI_NODE)
730 return(0);
731 if (step->value != NULL) {
732 if (!xmlStrEqual(step->value, node->name))
733 return(0);
734 }
735 break;
736 case XSLT_OP_COMMENT:
737 if (node->type != XML_COMMENT_NODE)
738 return(0);
739 break;
740 case XSLT_OP_TEXT:
741 if ((node->type != XML_TEXT_NODE) &&
742 (node->type != XML_CDATA_SECTION_NODE))
743 return(0);
744 break;
745 case XSLT_OP_NODE:
746 switch (node->type) {
747 case XML_ELEMENT_NODE:
748 case XML_CDATA_SECTION_NODE:
749 case XML_PI_NODE:
750 case XML_COMMENT_NODE:
751 case XML_TEXT_NODE:
752 break;
753 default:
754 return(0);
755 }
756 break;
757 default:
759 "xsltTestStepMatch: unexpected step op %d\n",
760 step->op);
761 return(-1);
762 }
763
764 return(1);
765}
766
779static int
781 xmlNodePtr node, xsltStepOpPtr step,
782 xsltStepOpPtr sel) {
783 xmlNodePtr oldNode;
784 xmlDocPtr doc;
785 int oldCS, oldCP;
786 int pos = 0, len = 0;
787 int isRVT;
788 int match;
789
790 if (step->value == NULL)
791 return(0);
792 if (step->comp == NULL)
793 return(0);
794 if (sel == NULL)
795 return(0);
796
797 doc = node->doc;
798 if (XSLT_IS_RES_TREE_FRAG(doc))
799 isRVT = 1;
800 else
801 isRVT = 0;
802
803 /*
804 * Recompute contextSize and proximityPosition.
805 *
806 * This could be improved in the following ways:
807 *
808 * - Skip recomputation if predicates don't use position() or last()
809 * - Keep data for multiple parents. This would require a hash table
810 * or an unused member in xmlNode.
811 * - Store node test results in a bitmap to avoid computing them twice.
812 */
813 oldCS = ctxt->xpathCtxt->contextSize;
814 oldCP = ctxt->xpathCtxt->proximityPosition;
815 {
816 xmlNodePtr previous;
817 int nocache = 0;
818
819 previous = (xmlNodePtr)
821 if ((previous != NULL) &&
822 (previous->parent == node->parent)) {
823 /*
824 * just walk back to adjust the index
825 */
826 int indx = 0;
827 xmlNodePtr sibling = node;
828
829 while (sibling != NULL) {
830 if (sibling == previous)
831 break;
832 if (xsltTestStepMatch(ctxt, sibling, sel))
833 indx++;
834 sibling = sibling->prev;
835 }
836 if (sibling == NULL) {
837 /* hum going backward in document order ... */
838 indx = 0;
839 sibling = node;
840 while (sibling != NULL) {
841 if (sibling == previous)
842 break;
843 if (xsltTestStepMatch(ctxt, sibling, sel))
844 indx--;
845 sibling = sibling->next;
846 }
847 }
848 if (sibling != NULL) {
849 pos = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) + indx;
850 /*
851 * If the node is in a Value Tree we need to
852 * save len, but cannot cache the node!
853 * (bugs 153137 and 158840)
854 */
855 if (node->doc != NULL) {
856 len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
857 if (!isRVT) {
859 sel->previousExtra, ptr) = node;
860 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
861 }
862 }
863 } else
864 pos = 0;
865 } else {
866 /*
867 * recompute the index
868 */
869 xmlNodePtr parent = node->parent;
870 xmlNodePtr siblings = NULL;
871
872 if (parent) siblings = parent->children;
873
874 while (siblings != NULL) {
875 if (siblings == node) {
876 len++;
877 pos = len;
878 } else if (xsltTestStepMatch(ctxt, siblings, sel)) {
879 len++;
880 }
881 siblings = siblings->next;
882 }
883 if ((parent == NULL) || (node->doc == NULL))
884 nocache = 1;
885 else {
886 while (parent->parent != NULL)
887 parent = parent->parent;
888 if (((parent->type != XML_DOCUMENT_NODE) &&
889 (parent->type != XML_HTML_DOCUMENT_NODE)) ||
890 (parent != (xmlNodePtr) node->doc))
891 nocache = 1;
892 }
893 }
894 if (pos != 0) {
895 ctxt->xpathCtxt->contextSize = len;
896 ctxt->xpathCtxt->proximityPosition = pos;
897 /*
898 * If the node is in a Value Tree we cannot
899 * cache it !
900 */
901 if ((!isRVT) && (node->doc != NULL) &&
902 (nocache == 0)) {
904 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
905 XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
906 }
907 }
908 }
909
910 oldNode = ctxt->node;
911 ctxt->node = node;
912
913 match = xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList, comp->nsNr);
914
915 if (pos != 0) {
916 ctxt->xpathCtxt->contextSize = oldCS;
917 ctxt->xpathCtxt->proximityPosition = oldCP;
918 }
919 ctxt->node = oldNode;
920
921 return match;
922}
923
936static int
938 xmlNodePtr matchNode, const xmlChar *mode,
939 const xmlChar *modeURI) {
940 int i;
941 int found = 0;
942 xmlNodePtr node = matchNode;
943 xmlNodePtr oldInst;
944 xsltStepOpPtr step, sel = NULL;
945 xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
946
947 if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) {
949 "xsltTestCompMatch: null arg\n");
950 return(-1);
951 }
952 if (mode != NULL) {
953 if (comp->mode == NULL)
954 return(0);
955 /*
956 * both mode strings must be interned on the stylesheet dictionary
957 */
958 if (comp->mode != mode)
959 return(0);
960 } else {
961 if (comp->mode != NULL)
962 return(0);
963 }
964 if (modeURI != NULL) {
965 if (comp->modeURI == NULL)
966 return(0);
967 /*
968 * both modeURI strings must be interned on the stylesheet dictionary
969 */
970 if (comp->modeURI != modeURI)
971 return(0);
972 } else {
973 if (comp->modeURI != NULL)
974 return(0);
975 }
976
977 /* Some XPath functions rely on inst being set correctly. */
978 oldInst = ctxt->inst;
979 ctxt->inst = comp->node;
980
981 i = 0;
982restart:
983 for (;i < comp->nbStep;i++) {
984 step = &comp->steps[i];
985 if (step->op != XSLT_OP_PREDICATE)
986 sel = step;
987 switch (step->op) {
988 case XSLT_OP_END:
989 goto found;
990 case XSLT_OP_PARENT:
991 if ((node->type == XML_DOCUMENT_NODE) ||
992 (node->type == XML_HTML_DOCUMENT_NODE) ||
993#ifdef LIBXML_DOCB_ENABLED
994 (node->type == XML_DOCB_DOCUMENT_NODE) ||
995#endif
996 (node->type == XML_NAMESPACE_DECL))
997 goto rollback;
998 node = node->parent;
999 if (node == NULL)
1000 goto rollback;
1001 if (step->value == NULL)
1002 continue;
1003 if (step->value[0] != node->name[0])
1004 goto rollback;
1005 if (!xmlStrEqual(step->value, node->name))
1006 goto rollback;
1007 /* Namespace test */
1008 if (node->ns == NULL) {
1009 if (step->value2 != NULL)
1010 goto rollback;
1011 } else if (node->ns->href != NULL) {
1012 if (step->value2 == NULL)
1013 goto rollback;
1014 if (!xmlStrEqual(step->value2, node->ns->href))
1015 goto rollback;
1016 }
1017 continue;
1018 case XSLT_OP_ANCESTOR:
1019 /* TODO: implement coalescing of ANCESTOR/NODE ops */
1020 if (step->value == NULL) {
1021 step = &comp->steps[i+1];
1022 if (step->op == XSLT_OP_ROOT)
1023 goto found;
1024 /* added NS, ID and KEY as a result of bug 168208 */
1025 if ((step->op != XSLT_OP_ELEM) &&
1026 (step->op != XSLT_OP_ALL) &&
1027 (step->op != XSLT_OP_NS) &&
1028 (step->op != XSLT_OP_ID) &&
1029 (step->op != XSLT_OP_KEY))
1030 goto rollback;
1031 }
1032 if (node == NULL)
1033 goto rollback;
1034 if ((node->type == XML_DOCUMENT_NODE) ||
1035 (node->type == XML_HTML_DOCUMENT_NODE) ||
1036#ifdef LIBXML_DOCB_ENABLED
1037 (node->type == XML_DOCB_DOCUMENT_NODE) ||
1038#endif
1039 (node->type == XML_NAMESPACE_DECL))
1040 goto rollback;
1041 node = node->parent;
1042 if ((step->op != XSLT_OP_ELEM) && step->op != XSLT_OP_ALL) {
1043 xsltPatPushState(ctxt, &states, i, node);
1044 continue;
1045 }
1046 i++;
1047 sel = step;
1048 if (step->value == NULL) {
1049 xsltPatPushState(ctxt, &states, i - 1, node);
1050 continue;
1051 }
1052 while (node != NULL) {
1053 if ((node->type == XML_ELEMENT_NODE) &&
1054 (step->value[0] == node->name[0]) &&
1055 (xmlStrEqual(step->value, node->name))) {
1056 /* Namespace test */
1057 if (node->ns == NULL) {
1058 if (step->value2 == NULL)
1059 break;
1060 } else if (node->ns->href != NULL) {
1061 if ((step->value2 != NULL) &&
1062 (xmlStrEqual(step->value2, node->ns->href)))
1063 break;
1064 }
1065 }
1066 node = node->parent;
1067 }
1068 if (node == NULL)
1069 goto rollback;
1070 xsltPatPushState(ctxt, &states, i - 1, node);
1071 continue;
1072 case XSLT_OP_PREDICATE: {
1073 /*
1074 * When there is cascading XSLT_OP_PREDICATE or a predicate
1075 * after an op which hasn't been optimized yet, then use a
1076 * direct computation approach. It's not done directly
1077 * at the beginning of the routine to filter out as much
1078 * as possible this costly computation.
1079 */
1080 if (comp->direct) {
1081 found = xsltTestCompMatchDirect(ctxt, comp, matchNode,
1082 comp->nsList, comp->nsNr);
1083 goto exit;
1084 }
1085
1086 if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel))
1087 goto rollback;
1088
1089 break;
1090 }
1091 default:
1092 if (xsltTestStepMatch(ctxt, node, step) != 1)
1093 goto rollback;
1094 break;
1095 }
1096 }
1097found:
1098 found = 1;
1099exit:
1100 ctxt->inst = oldInst;
1101 if (states.states != NULL) {
1102 /* Free the rollback states */
1103 xmlFree(states.states);
1104 }
1105 return found;
1106rollback:
1107 /* got an error try to rollback */
1108 if (states.states == NULL || states.nbstates <= 0) {
1109 found = 0;
1110 goto exit;
1111 }
1112 states.nbstates--;
1113 i = states.states[states.nbstates].step;
1114 node = states.states[states.nbstates].node;
1115#if 0
1116 fprintf(stderr, "Pop: %d, %s\n", i, node->name);
1117#endif
1118 goto restart;
1119}
1120
1131int
1133 xsltCompMatchPtr comp) {
1134 int ret;
1135
1136 if ((ctxt == NULL) || (node == NULL))
1137 return(-1);
1138 while (comp != NULL) {
1139 ret = xsltTestCompMatch(ctxt, comp, node, NULL, NULL);
1140 if (ret == 1)
1141 return(1);
1142 comp = comp->next;
1143 }
1144 return(0);
1145}
1146
1154void
1156 xsltStepOpPtr sel;
1157 xmlXPathObjectPtr list;
1158
1159 if ((ctxt == NULL) || (comp == NULL))
1160 return;
1161
1162 sel = &comp->steps[0];
1163 list = (xmlXPathObjectPtr) XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
1164
1165 if (list != NULL) {
1166 xmlXPathFreeObject(list);
1167
1168 XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) = NULL;
1170 XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = 0;
1172 }
1173}
1174
1175/************************************************************************
1176 * *
1177 * Dedicated parser for templates *
1178 * *
1179 ************************************************************************/
1180
1181#define CUR (*ctxt->cur)
1182#define SKIP(val) ctxt->cur += (val)
1183#define NXT(val) ctxt->cur[(val)]
1184#define CUR_PTR ctxt->cur
1185
1186#define SKIP_BLANKS \
1187 while (xmlIsBlank_ch(CUR)) NEXT
1188
1189#define CURRENT (*ctxt->cur)
1190#define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
1191
1192
1193#define PUSH(op, val, val2, novar) \
1194 if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto error;
1195
1196#define SWAP() \
1197 xsltSwapTopCompMatch(ctxt->comp);
1198
1199#define XSLT_ERROR(X) \
1200 { xsltError(ctxt, __FILE__, __LINE__, X); \
1201 ctxt->error = (X); return; }
1202
1203#define XSLT_ERROR0(X) \
1204 { xsltError(ctxt, __FILE__, __LINE__, X); \
1205 ctxt->error = (X); return(0); }
1206
1219static xmlChar *
1221 const xmlChar *q, *cur;
1222 xmlChar *ret = NULL;
1223 int val, len;
1224
1226 if (CUR == '"') {
1227 NEXT;
1228 cur = q = CUR_PTR;
1230 while ((xmlIsCharQ(val)) && (val != '"')) {
1231 cur += len;
1233 }
1234 if (!xmlIsCharQ(val)) {
1235 ctxt->error = 1;
1236 return(NULL);
1237 } else {
1238 ret = xmlStrndup(q, cur - q);
1239 }
1240 cur += len;
1241 CUR_PTR = cur;
1242 } else if (CUR == '\'') {
1243 NEXT;
1244 cur = q = CUR_PTR;
1246 while ((xmlIsCharQ(val)) && (val != '\'')) {
1247 cur += len;
1249 }
1250 if (!xmlIsCharQ(val)) {
1251 ctxt->error = 1;
1252 return(NULL);
1253 } else {
1254 ret = xmlStrndup(q, cur - q);
1255 }
1256 cur += len;
1257 CUR_PTR = cur;
1258 } else {
1259 ctxt->error = 1;
1260 return(NULL);
1261 }
1262 return(ret);
1263}
1264
1274static xmlChar *
1276 const xmlChar *q, *cur;
1277 xmlChar *ret = NULL;
1278 int val, len;
1279
1281
1282 cur = q = CUR_PTR;
1284 if (!xmlIsBaseCharQ(val) && !xmlIsIdeographicQ(val) && (val != '_'))
1285 return(NULL);
1286
1288 xmlIsDigitQ(val) ||
1289 (val == '.') || (val == '-') ||
1290 (val == '_') ||
1293 cur += len;
1295 }
1296 ret = xmlStrndup(q, cur - q);
1297 CUR_PTR = cur;
1298 return(ret);
1299}
1300
1301/*
1302 * xsltCompileIdKeyPattern:
1303 * @ctxt: the compilation context
1304 * @name: a preparsed name
1305 * @aid: whether id/key are allowed there
1306 * @novar: flag to prohibit xslt var
1307 *
1308 * Compile the XSLT LocationIdKeyPattern
1309 * [3] IdKeyPattern ::= 'id' '(' Literal ')'
1310 * | 'key' '(' Literal ',' Literal ')'
1311 *
1312 * also handle NodeType and PI from:
1313 *
1314 * [7] NodeTest ::= NameTest
1315 * | NodeType '(' ')'
1316 * | 'processing-instruction' '(' Literal ')'
1317 */
1318static void
1320 int aid, int novar, xsltAxis axis) {
1321 xmlChar *lit = NULL;
1322 xmlChar *lit2 = NULL;
1323
1324 if (CUR != '(') {
1326 "xsltCompileIdKeyPattern : ( expected\n");
1327 ctxt->error = 1;
1328 return;
1329 }
1330 if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) {
1331 if (axis != 0) {
1333 "xsltCompileIdKeyPattern : NodeTest expected\n");
1334 ctxt->error = 1;
1335 return;
1336 }
1337 NEXT;
1339 lit = xsltScanLiteral(ctxt);
1340 if (ctxt->error) {
1342 "xsltCompileIdKeyPattern : Literal expected\n");
1343 xmlFree(lit);
1344 return;
1345 }
1347 if (CUR != ')') {
1349 "xsltCompileIdKeyPattern : ) expected\n");
1350 xmlFree(lit);
1351 ctxt->error = 1;
1352 return;
1353 }
1354 NEXT;
1355 PUSH(XSLT_OP_ID, lit, NULL, novar);
1356 lit = NULL;
1357 } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) {
1358 if (axis != 0) {
1360 "xsltCompileIdKeyPattern : NodeTest expected\n");
1361 ctxt->error = 1;
1362 return;
1363 }
1364 NEXT;
1366 lit = xsltScanLiteral(ctxt);
1367 if (ctxt->error) {
1369 "xsltCompileIdKeyPattern : Literal expected\n");
1370 xmlFree(lit);
1371 return;
1372 }
1374 if (CUR != ',') {
1376 "xsltCompileIdKeyPattern : , expected\n");
1377 xmlFree(lit);
1378 ctxt->error = 1;
1379 return;
1380 }
1381 NEXT;
1383 lit2 = xsltScanLiteral(ctxt);
1384 if (ctxt->error) {
1386 "xsltCompileIdKeyPattern : Literal expected\n");
1387 xmlFree(lit);
1388 return;
1389 }
1391 if (CUR != ')') {
1393 "xsltCompileIdKeyPattern : ) expected\n");
1394 xmlFree(lit);
1395 xmlFree(lit2);
1396 ctxt->error = 1;
1397 return;
1398 }
1399 NEXT;
1400 /* URGENT TODO: support namespace in keys */
1401 PUSH(XSLT_OP_KEY, lit, lit2, novar);
1402 lit = NULL;
1403 lit2 = NULL;
1404 } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {
1405 NEXT;
1407 if (CUR != ')') {
1408 lit = xsltScanLiteral(ctxt);
1409 if (ctxt->error) {
1411 "xsltCompileIdKeyPattern : Literal expected\n");
1412 xmlFree(lit);
1413 return;
1414 }
1416 if (CUR != ')') {
1418 "xsltCompileIdKeyPattern : ) expected\n");
1419 ctxt->error = 1;
1420 xmlFree(lit);
1421 return;
1422 }
1423 }
1424 NEXT;
1425 PUSH(XSLT_OP_PI, lit, NULL, novar);
1426 lit = NULL;
1427 } else if (xmlStrEqual(name, (const xmlChar *)"text")) {
1428 NEXT;
1430 if (CUR != ')') {
1432 "xsltCompileIdKeyPattern : ) expected\n");
1433 ctxt->error = 1;
1434 return;
1435 }
1436 NEXT;
1437 PUSH(XSLT_OP_TEXT, NULL, NULL, novar);
1438 } else if (xmlStrEqual(name, (const xmlChar *)"comment")) {
1439 NEXT;
1441 if (CUR != ')') {
1443 "xsltCompileIdKeyPattern : ) expected\n");
1444 ctxt->error = 1;
1445 return;
1446 }
1447 NEXT;
1448 PUSH(XSLT_OP_COMMENT, NULL, NULL, novar);
1449 } else if (xmlStrEqual(name, (const xmlChar *)"node")) {
1450 NEXT;
1452 if (CUR != ')') {
1454 "xsltCompileIdKeyPattern : ) expected\n");
1455 ctxt->error = 1;
1456 return;
1457 }
1458 NEXT;
1459 if (axis == AXIS_ATTRIBUTE) {
1460 PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
1461 }
1462 else {
1463 PUSH(XSLT_OP_NODE, NULL, NULL, novar);
1464 }
1465 } else if (aid) {
1467 "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n");
1468 ctxt->error = 1;
1469 return;
1470 } else {
1472 "xsltCompileIdKeyPattern : node type\n");
1473 ctxt->error = 1;
1474 return;
1475 }
1476error:
1477 return;
1478}
1479
1502static void
1504 xmlChar *name = NULL;
1505 const xmlChar *URI = NULL;
1506 xmlChar *URL = NULL;
1507 xmlChar *ret = NULL;
1508 int level;
1509 xsltAxis axis = 0;
1510
1512 if ((token == NULL) && (CUR == '@')) {
1513 NEXT;
1514 axis = AXIS_ATTRIBUTE;
1515 }
1516parse_node_test:
1517 if (token == NULL)
1518 token = xsltScanNCName(ctxt);
1519 if (token == NULL) {
1520 if (CUR == '*') {
1521 NEXT;
1522 if (axis == AXIS_ATTRIBUTE) {
1523 PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
1524 }
1525 else {
1526 PUSH(XSLT_OP_ALL, NULL, NULL, novar);
1527 }
1528 goto parse_predicate;
1529 } else {
1531 "xsltCompileStepPattern : Name expected\n");
1532 ctxt->error = 1;
1533 goto error;
1534 }
1535 }
1536
1537
1539 if (CUR == '(') {
1540 xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis);
1541 xmlFree(token);
1542 token = NULL;
1543 if (ctxt->error)
1544 goto error;
1545 } else if (CUR == ':') {
1546 NEXT;
1547 if (CUR != ':') {
1548 xmlChar *prefix = token;
1549 xmlNsPtr ns;
1550
1551 /*
1552 * This is a namespace match
1553 */
1554 token = xsltScanNCName(ctxt);
1555 ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);
1556 if (ns == NULL) {
1558 "xsltCompileStepPattern : no namespace bound to prefix %s\n",
1559 prefix);
1560 xmlFree(prefix);
1561 prefix=NULL;
1562 ctxt->error = 1;
1563 goto error;
1564 } else {
1565 URL = xmlStrdup(ns->href);
1566 }
1567 xmlFree(prefix);
1568 prefix=NULL;
1569 if (token == NULL) {
1570 if (CUR == '*') {
1571 NEXT;
1572 if (axis == AXIS_ATTRIBUTE) {
1573 PUSH(XSLT_OP_ATTR, NULL, URL, novar);
1574 URL = NULL;
1575 }
1576 else {
1577 PUSH(XSLT_OP_NS, URL, NULL, novar);
1578 URL = NULL;
1579 }
1580 } else {
1582 "xsltCompileStepPattern : Name expected\n");
1583 ctxt->error = 1;
1584 goto error;
1585 }
1586 } else {
1587 if (axis == AXIS_ATTRIBUTE) {
1588 PUSH(XSLT_OP_ATTR, token, URL, novar);
1589 token = NULL;
1590 URL = NULL;
1591 }
1592 else {
1593 PUSH(XSLT_OP_ELEM, token, URL, novar);
1594 token = NULL;
1595 URL = NULL;
1596 }
1597 }
1598 } else {
1599 if (axis != 0) {
1601 "xsltCompileStepPattern : NodeTest expected\n");
1602 ctxt->error = 1;
1603 goto error;
1604 }
1605 NEXT;
1606 if (xmlStrEqual(token, (const xmlChar *) "child")) {
1607 axis = AXIS_CHILD;
1608 } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) {
1609 axis = AXIS_ATTRIBUTE;
1610 } else {
1612 "xsltCompileStepPattern : 'child' or 'attribute' expected\n");
1613 ctxt->error = 1;
1614 goto error;
1615 }
1616 xmlFree(token);
1617 token = NULL;
1619 token = xsltScanNCName(ctxt);
1620 goto parse_node_test;
1621 }
1622 } else {
1623 URI = xsltGetQNameURI(ctxt->elem, &token);
1624 if (token == NULL) {
1625 ctxt->error = 1;
1626 goto error;
1627 }
1628 if (URI != NULL)
1629 URL = xmlStrdup(URI);
1630 if (axis == AXIS_ATTRIBUTE) {
1631 PUSH(XSLT_OP_ATTR, token, URL, novar);
1632 token = NULL;
1633 URL = NULL;
1634 }
1635 else {
1636 PUSH(XSLT_OP_ELEM, token, URL, novar);
1637 token = NULL;
1638 URL = NULL;
1639 }
1640 }
1641parse_predicate:
1643 level = 0;
1644 while (CUR == '[') {
1645 const xmlChar *q;
1646
1647 level++;
1648 NEXT;
1649 q = CUR_PTR;
1650 while (CUR != 0) {
1651 /* Skip over nested predicates */
1652 if (CUR == '[')
1653 level++;
1654 else if (CUR == ']') {
1655 level--;
1656 if (level == 0)
1657 break;
1658 } else if (CUR == '"') {
1659 NEXT;
1660 while ((CUR != 0) && (CUR != '"'))
1661 NEXT;
1662 } else if (CUR == '\'') {
1663 NEXT;
1664 while ((CUR != 0) && (CUR != '\''))
1665 NEXT;
1666 }
1667 NEXT;
1668 }
1669 if (CUR == 0) {
1671 "xsltCompileStepPattern : ']' expected\n");
1672 ctxt->error = 1;
1673 return;
1674 }
1675 ret = xmlStrndup(q, CUR_PTR - q);
1676 PUSH(XSLT_OP_PREDICATE, ret, NULL, novar);
1677 ret = NULL;
1678 /* push the predicate lower than local test */
1679 SWAP();
1680 NEXT;
1682 }
1683 return;
1684error:
1685 if (token != NULL)
1686 xmlFree(token);
1687 if (name != NULL)
1688 xmlFree(name);
1689 if (URL != NULL)
1690 xmlFree(URL);
1691 if (ret != NULL)
1692 xmlFree(ret);
1693}
1694
1708static void
1710 xsltCompileStepPattern(ctxt, token, novar);
1711 if (ctxt->error)
1712 goto error;
1714 while ((CUR != 0) && (CUR != '|')) {
1715 if ((CUR == '/') && (NXT(1) == '/')) {
1716 PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
1717 NEXT;
1718 NEXT;
1720 xsltCompileStepPattern(ctxt, NULL, novar);
1721 } else if (CUR == '/') {
1722 PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1723 NEXT;
1725 xsltCompileStepPattern(ctxt, NULL, novar);
1726 } else {
1727 ctxt->error = 1;
1728 }
1729 if (ctxt->error)
1730 goto error;
1732 }
1733error:
1734 return;
1735}
1736
1749static void
1752 if ((CUR == '/') && (NXT(1) == '/')) {
1753 /*
1754 * since we reverse the query
1755 * a leading // can be safely ignored
1756 */
1757 NEXT;
1758 NEXT;
1759 ctxt->comp->priority = 0.5; /* '//' means not 0 priority */
1761 } else if (CUR == '/') {
1762 /*
1763 * We need to find root as the parent
1764 */
1765 NEXT;
1767 PUSH(XSLT_OP_ROOT, NULL, NULL, novar);
1768 if ((CUR != 0) && (CUR != '|')) {
1769 PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1771 }
1772 } else if (CUR == '*') {
1774 } else if (CUR == '@') {
1776 } else {
1777 xmlChar *name;
1778 name = xsltScanNCName(ctxt);
1779 if (name == NULL) {
1781 "xsltCompileLocationPathPattern : Name expected\n");
1782 ctxt->error = 1;
1783 return;
1784 }
1786 if ((CUR == '(') && !xmlXPathIsNodeType(name)) {
1787 xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0);
1788 xmlFree(name);
1789 name = NULL;
1790 if (ctxt->error)
1791 return;
1792 if ((CUR == '/') && (NXT(1) == '/')) {
1793 PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
1794 NEXT;
1795 NEXT;
1798 } else if (CUR == '/') {
1799 PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1800 NEXT;
1803 }
1804 return;
1805 }
1807 }
1808error:
1809 return;
1810}
1811
1829static xsltCompMatchPtr
1831 xmlNodePtr node, xsltStylesheetPtr style,
1832 xsltTransformContextPtr runtime, int novar) {
1834 xsltCompMatchPtr element, first = NULL, previous = NULL;
1835 int current, start, end, level, j;
1836
1837 if (pattern == NULL) {
1839 "xsltCompilePattern : NULL pattern\n");
1840 return(NULL);
1841 }
1842
1843 ctxt = xsltNewParserContext(style, runtime);
1844 if (ctxt == NULL)
1845 return(NULL);
1846 ctxt->doc = doc;
1847 ctxt->elem = node;
1848 current = end = 0;
1849 while (pattern[current] != 0) {
1850 start = current;
1851 while (xmlIsBlank_ch(pattern[current]))
1852 current++;
1853 end = current;
1854 level = 0;
1855 while ((pattern[end] != 0) && ((pattern[end] != '|') || (level != 0))) {
1856 if (pattern[end] == '[')
1857 level++;
1858 else if (pattern[end] == ']')
1859 level--;
1860 else if (pattern[end] == '\'') {
1861 end++;
1862 while ((pattern[end] != 0) && (pattern[end] != '\''))
1863 end++;
1864 } else if (pattern[end] == '"') {
1865 end++;
1866 while ((pattern[end] != 0) && (pattern[end] != '"'))
1867 end++;
1868 }
1869 if (pattern[end] == 0)
1870 break;
1871 end++;
1872 }
1873 if (current == end) {
1875 "xsltCompilePattern : NULL pattern\n");
1876 goto error;
1877 }
1879 if (element == NULL) {
1880 goto error;
1881 }
1882 if (first == NULL)
1883 first = element;
1884 else if (previous != NULL)
1885 previous->next = element;
1886 previous = element;
1887
1888 ctxt->comp = element;
1889 ctxt->base = xmlStrndup(&pattern[start], end - start);
1890 if (ctxt->base == NULL)
1891 goto error;
1892 ctxt->cur = &(ctxt->base)[current - start];
1893 element->pattern = ctxt->base;
1894 element->node = node;
1895 element->nsList = xmlGetNsList(doc, node);
1896 j = 0;
1897 if (element->nsList != NULL) {
1898 while (element->nsList[j] != NULL)
1899 j++;
1900 }
1901 element->nsNr = j;
1902
1903
1904#ifdef WITH_XSLT_DEBUG_PATTERN
1906 "xsltCompilePattern : parsing '%s'\n",
1907 element->pattern);
1908#endif
1909 /*
1910 Preset default priority to be zero.
1911 This may be changed by xsltCompileLocationPathPattern.
1912 */
1913 element->priority = 0;
1914 xsltCompileLocationPathPattern(ctxt, novar);
1915 if (ctxt->error) {
1917 "xsltCompilePattern : failed to compile '%s'\n",
1918 element->pattern);
1919 if (style != NULL) style->errors++;
1920 goto error;
1921 }
1922
1923 /*
1924 * Reverse for faster interpretation.
1925 */
1927
1928 /*
1929 * Set-up the priority
1930 */
1931 if (element->priority == 0) { /* if not yet determined */
1932 if (((element->steps[0].op == XSLT_OP_ELEM) ||
1933 (element->steps[0].op == XSLT_OP_ATTR) ||
1934 (element->steps[0].op == XSLT_OP_PI)) &&
1935 (element->steps[0].value != NULL) &&
1936 (element->steps[1].op == XSLT_OP_END)) {
1937 ; /* previously preset */
1938 } else if ((element->steps[0].op == XSLT_OP_ATTR) &&
1939 (element->steps[0].value2 != NULL) &&
1940 (element->steps[1].op == XSLT_OP_END)) {
1941 element->priority = -0.25;
1942 } else if ((element->steps[0].op == XSLT_OP_NS) &&
1943 (element->steps[0].value != NULL) &&
1944 (element->steps[1].op == XSLT_OP_END)) {
1945 element->priority = -0.25;
1946 } else if ((element->steps[0].op == XSLT_OP_ATTR) &&
1947 (element->steps[0].value == NULL) &&
1948 (element->steps[0].value2 == NULL) &&
1949 (element->steps[1].op == XSLT_OP_END)) {
1950 element->priority = -0.5;
1951 } else if (((element->steps[0].op == XSLT_OP_PI) ||
1952 (element->steps[0].op == XSLT_OP_TEXT) ||
1953 (element->steps[0].op == XSLT_OP_ALL) ||
1954 (element->steps[0].op == XSLT_OP_NODE) ||
1955 (element->steps[0].op == XSLT_OP_COMMENT)) &&
1956 (element->steps[1].op == XSLT_OP_END)) {
1957 element->priority = -0.5;
1958 } else {
1959 element->priority = 0.5;
1960 }
1961 }
1962#ifdef WITH_XSLT_DEBUG_PATTERN
1964 "xsltCompilePattern : parsed %s, default priority %f\n",
1965 element->pattern, element->priority);
1966#endif
1967 if (pattern[end] == '|')
1968 end++;
1969 current = end;
1970 }
1971 if (end == 0) {
1973 "xsltCompilePattern : NULL pattern\n");
1974 if (style != NULL) style->errors++;
1975 goto error;
1976 }
1977
1979 return(first);
1980
1981error:
1982 if (ctxt != NULL)
1984 if (first != NULL)
1986 return(NULL);
1987}
1988
2006xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc,
2007 xmlNodePtr node, xsltStylesheetPtr style,
2008 xsltTransformContextPtr runtime) {
2009 return (xsltCompilePatternInternal(pattern, doc, node, style, runtime, 0));
2010}
2011
2012/************************************************************************
2013 * *
2014 * Module interfaces *
2015 * *
2016 ************************************************************************/
2017
2029int
2031 const xmlChar *mode, const xmlChar *modeURI) {
2033 /*
2034 * 'top' will point to style->xxxMatch ptr - declaring as 'void'
2035 * avoids gcc 'type-punned pointer' warning.
2036 */
2038 const xmlChar *name = NULL;
2039 float priority; /* the priority */
2040
2041 if ((style == NULL) || (cur == NULL))
2042 return(-1);
2043
2044 if (cur->next != NULL)
2045 cur->position = cur->next->position + 1;
2046
2047 /* Register named template */
2048 if (cur->name != NULL) {
2049 if (style->namedTemplates == NULL) {
2050 style->namedTemplates = xmlHashCreate(10);
2051 if (style->namedTemplates == NULL)
2052 return(-1);
2053 }
2054 else {
2055 void *dup = xmlHashLookup2(style->namedTemplates, cur->name,
2056 cur->nameURI);
2057 if (dup != NULL) {
2059 "xsl:template: error duplicate name '%s'\n",
2060 cur->name);
2061 style->errors++;
2062 return(-1);
2063 }
2064 }
2065
2066 xmlHashAddEntry2(style->namedTemplates, cur->name, cur->nameURI, cur);
2067 }
2068
2069 if (cur->match == NULL) {
2070 if (cur->name == NULL) {
2072 "xsl:template: need to specify match or name attribute\n");
2073 style->errors++;
2074 return(-1);
2075 }
2076 return(0);
2077 }
2078
2079 priority = cur->priority;
2080 pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem,
2081 style, NULL, 1);
2082 if (pat == NULL)
2083 return(-1);
2084 while (pat) {
2085 int success = 0;
2086
2087 next = pat->next;
2088 pat->next = NULL;
2089 name = NULL;
2090
2091 pat->template = cur;
2092 if (mode != NULL)
2093 pat->mode = xmlDictLookup(style->dict, mode, -1);
2094 if (modeURI != NULL)
2095 pat->modeURI = xmlDictLookup(style->dict, modeURI, -1);
2097 pat->priority = priority;
2098
2099 /*
2100 * insert it in the hash table list corresponding to its lookup name
2101 */
2102 switch (pat->steps[0].op) {
2103 case XSLT_OP_ATTR:
2104 if (pat->steps[0].value != NULL)
2105 name = pat->steps[0].value;
2106 else
2107 top = &(style->attrMatch);
2108 break;
2109 case XSLT_OP_PARENT:
2110 case XSLT_OP_ANCESTOR:
2111 top = &(style->elemMatch);
2112 break;
2113 case XSLT_OP_ROOT:
2114 top = &(style->rootMatch);
2115 break;
2116 case XSLT_OP_KEY:
2117 top = &(style->keyMatch);
2118 break;
2119 case XSLT_OP_ID:
2120 /* TODO optimize ID !!! */
2121 case XSLT_OP_NS:
2122 case XSLT_OP_ALL:
2123 top = &(style->elemMatch);
2124 break;
2125 case XSLT_OP_END:
2126 case XSLT_OP_PREDICATE:
2128 "xsltAddTemplate: invalid compiled pattern\n");
2129 xsltFreeCompMatch(pat);
2130 return(-1);
2131 /*
2132 * TODO: some flags at the top level about type based patterns
2133 * would be faster than inclusion in the hash table.
2134 */
2135 case XSLT_OP_PI:
2136 if (pat->steps[0].value != NULL)
2137 name = pat->steps[0].value;
2138 else
2139 top = &(style->piMatch);
2140 break;
2141 case XSLT_OP_COMMENT:
2142 top = &(style->commentMatch);
2143 break;
2144 case XSLT_OP_TEXT:
2145 top = &(style->textMatch);
2146 break;
2147 case XSLT_OP_ELEM:
2148 case XSLT_OP_NODE:
2149 if (pat->steps[0].value != NULL)
2150 name = pat->steps[0].value;
2151 else
2152 top = &(style->elemMatch);
2153 break;
2154 }
2155 if (name != NULL) {
2156 if (style->templatesHash == NULL) {
2157 style->templatesHash = xmlHashCreate(1024);
2158 success = (style->templatesHash != NULL) &&
2159 (xmlHashAddEntry3(style->templatesHash, name, mode,
2160 modeURI, pat) >= 0);
2161 } else {
2162 list = (xsltCompMatchPtr) xmlHashLookup3(style->templatesHash,
2163 name, mode, modeURI);
2164 if (list == NULL) {
2165 success = (xmlHashAddEntry3(style->templatesHash, name,
2166 mode, modeURI, pat) >= 0);
2167 } else {
2168 /*
2169 * Note '<=' since one must choose among the matching
2170 * template rules that are left, the one that occurs
2171 * last in the stylesheet
2172 */
2173 if (list->priority <= pat->priority) {
2174 pat->next = list;
2175 xmlHashUpdateEntry3(style->templatesHash, name,
2176 mode, modeURI, pat, NULL);
2177 } else {
2178 while (list->next != NULL) {
2179 if (list->next->priority <= pat->priority)
2180 break;
2181 list = list->next;
2182 }
2183 pat->next = list->next;
2184 list->next = pat;
2185 }
2186 success = 1;
2187 }
2188 }
2189 } else if (top != NULL) {
2190 list = *top;
2191 if (list == NULL) {
2192 *top = pat;
2193 pat->next = NULL;
2194 } else if (list->priority <= pat->priority) {
2195 pat->next = list;
2196 *top = pat;
2197 } else {
2198 while (list->next != NULL) {
2199 if (list->next->priority <= pat->priority)
2200 break;
2201 list = list->next;
2202 }
2203 pat->next = list->next;
2204 list->next = pat;
2205 }
2206 success = 1;
2207 }
2208 if (success == 0) {
2210 "xsltAddTemplate: invalid compiled pattern\n");
2211 xsltFreeCompMatch(pat);
2213 return(-1);
2214 }
2215#ifdef WITH_XSLT_DEBUG_PATTERN
2216 if (mode)
2218 "added pattern : '%s' mode '%s' priority %f\n",
2219 pat->pattern, pat->mode, pat->priority);
2220 else
2222 "added pattern : '%s' priority %f\n",
2223 pat->pattern, pat->priority);
2224#endif
2225
2226 pat = next;
2227 }
2228 return(0);
2229}
2230
2231static int
2232xsltComputeAllKeys(xsltTransformContextPtr ctxt, xmlNodePtr contextNode)
2233{
2234 if ((ctxt == NULL) || (contextNode == NULL)) {
2235 xsltTransformError(ctxt, NULL, ctxt->inst,
2236 "Internal error in xsltComputeAllKeys(): "
2237 "Bad arguments.\n");
2238 return(-1);
2239 }
2240
2241 if (ctxt->document == NULL) {
2242 /*
2243 * The document info will only be NULL if we have a RTF.
2244 */
2245 if (contextNode->doc->_private != NULL)
2246 goto doc_info_mismatch;
2247 /*
2248 * On-demand creation of the document info (needed for keys).
2249 */
2250 ctxt->document = xsltNewDocument(ctxt, contextNode->doc);
2251 if (ctxt->document == NULL)
2252 return(-1);
2253 }
2254 return xsltInitAllDocKeys(ctxt);
2255
2256doc_info_mismatch:
2257 xsltTransformError(ctxt, NULL, ctxt->inst,
2258 "Internal error in xsltComputeAllKeys(): "
2259 "The context's document info doesn't match the "
2260 "document info of the current result tree.\n");
2261 ctxt->state = XSLT_STATE_STOPPED;
2262 return(-1);
2263}
2264
2279{
2280 xsltStylesheetPtr curstyle;
2282 const xmlChar *name = NULL;
2284 float priority;
2285
2286 if ((ctxt == NULL) || (node == NULL))
2287 return(NULL);
2288
2289 if (style == NULL) {
2290 curstyle = ctxt->style;
2291 } else {
2292 curstyle = xsltNextImport(style);
2293 }
2294
2295 while ((curstyle != NULL) && (curstyle != style)) {
2297 /* TODO : handle IDs/keys here ! */
2298 if (curstyle->templatesHash != NULL) {
2299 /*
2300 * Use the top name as selector
2301 */
2302 switch (node->type) {
2303 case XML_ELEMENT_NODE:
2304 if (node->name[0] == ' ')
2305 break;
2306 /* Intentional fall-through */
2307 case XML_ATTRIBUTE_NODE:
2308 case XML_PI_NODE:
2309 name = node->name;
2310 break;
2311 case XML_DOCUMENT_NODE:
2312 case XML_HTML_DOCUMENT_NODE:
2313 case XML_TEXT_NODE:
2314 case XML_CDATA_SECTION_NODE:
2315 case XML_COMMENT_NODE:
2316 case XML_ENTITY_REF_NODE:
2317 case XML_ENTITY_NODE:
2318 case XML_DOCUMENT_TYPE_NODE:
2319 case XML_DOCUMENT_FRAG_NODE:
2320 case XML_NOTATION_NODE:
2321 case XML_DTD_NODE:
2322 case XML_ELEMENT_DECL:
2323 case XML_ATTRIBUTE_DECL:
2324 case XML_ENTITY_DECL:
2325 case XML_NAMESPACE_DECL:
2326 case XML_XINCLUDE_START:
2327 case XML_XINCLUDE_END:
2328 break;
2329 default:
2330 return(NULL);
2331
2332 }
2333 }
2334 if (name != NULL) {
2335 /*
2336 * find the list of applicable expressions based on the name
2337 */
2339 name, ctxt->mode, ctxt->modeURI);
2340 } else
2341 list = NULL;
2342 while (list != NULL) {
2343 if (xsltTestCompMatch(ctxt, list, node,
2344 ctxt->mode, ctxt->modeURI) == 1) {
2345 ret = list->template;
2346 priority = list->priority;
2347 break;
2348 }
2349 list = list->next;
2350 }
2351 list = NULL;
2352
2353 /*
2354 * find alternate generic matches
2355 */
2356 switch (node->type) {
2357 case XML_ELEMENT_NODE:
2358 if (node->name[0] == ' ')
2359 list = curstyle->rootMatch;
2360 else
2361 list = curstyle->elemMatch;
2362 break;
2363 case XML_ATTRIBUTE_NODE: {
2364 list = curstyle->attrMatch;
2365 break;
2366 }
2367 case XML_PI_NODE:
2368 list = curstyle->piMatch;
2369 break;
2370 case XML_DOCUMENT_NODE:
2371 case XML_HTML_DOCUMENT_NODE: {
2372 list = curstyle->rootMatch;
2373 break;
2374 }
2375 case XML_TEXT_NODE:
2376 case XML_CDATA_SECTION_NODE:
2377 list = curstyle->textMatch;
2378 break;
2379 case XML_COMMENT_NODE:
2380 list = curstyle->commentMatch;
2381 break;
2382 case XML_ENTITY_REF_NODE:
2383 case XML_ENTITY_NODE:
2384 case XML_DOCUMENT_TYPE_NODE:
2385 case XML_DOCUMENT_FRAG_NODE:
2386 case XML_NOTATION_NODE:
2387 case XML_DTD_NODE:
2388 case XML_ELEMENT_DECL:
2389 case XML_ATTRIBUTE_DECL:
2390 case XML_ENTITY_DECL:
2391 case XML_NAMESPACE_DECL:
2392 case XML_XINCLUDE_START:
2393 case XML_XINCLUDE_END:
2394 break;
2395 default:
2396 break;
2397 }
2398 while ((list != NULL) &&
2399 ((ret == NULL) ||
2400 (list->priority > priority) ||
2401 ((list->priority == priority) &&
2402 (list->template->position > ret->position)))) {
2403 if (xsltTestCompMatch(ctxt, list, node,
2404 ctxt->mode, ctxt->modeURI) == 1) {
2405 ret = list->template;
2406 priority = list->priority;
2407 break;
2408 }
2409 list = list->next;
2410 }
2411 /*
2412 * Some of the tests for elements can also apply to documents
2413 */
2414 if ((node->type == XML_DOCUMENT_NODE) ||
2415 (node->type == XML_HTML_DOCUMENT_NODE) ||
2416 (node->type == XML_TEXT_NODE)) {
2417 list = curstyle->elemMatch;
2418 while ((list != NULL) &&
2419 ((ret == NULL) ||
2420 (list->priority > priority) ||
2421 ((list->priority == priority) &&
2422 (list->template->position > ret->position)))) {
2423 if (xsltTestCompMatch(ctxt, list, node,
2424 ctxt->mode, ctxt->modeURI) == 1) {
2425 ret = list->template;
2426 priority = list->priority;
2427 break;
2428 }
2429 list = list->next;
2430 }
2431 } else if ((node->type == XML_PI_NODE) ||
2432 (node->type == XML_COMMENT_NODE)) {
2433 list = curstyle->elemMatch;
2434 while ((list != NULL) &&
2435 ((ret == NULL) ||
2436 (list->priority > priority) ||
2437 ((list->priority == priority) &&
2438 (list->template->position > ret->position)))) {
2439 if (xsltTestCompMatch(ctxt, list, node,
2440 ctxt->mode, ctxt->modeURI) == 1) {
2441 ret = list->template;
2442 priority = list->priority;
2443 break;
2444 }
2445 list = list->next;
2446 }
2447 }
2448
2449keyed_match:
2450 if (xsltGetSourceNodeFlags(node) & XSLT_SOURCE_NODE_HAS_KEY) {
2451 list = curstyle->keyMatch;
2452 while ((list != NULL) &&
2453 ((ret == NULL) ||
2454 (list->priority > priority) ||
2455 ((list->priority == priority) &&
2456 (list->template->position > ret->position)))) {
2457 if (xsltTestCompMatch(ctxt, list, node,
2458 ctxt->mode, ctxt->modeURI) == 1) {
2459 ret = list->template;
2460 priority = list->priority;
2461 break;
2462 }
2463 list = list->next;
2464 }
2465 }
2466 else if (ctxt->hasTemplKeyPatterns &&
2467 ((ctxt->document == NULL) ||
2468 (ctxt->document->nbKeysComputed < ctxt->nbKeys)))
2469 {
2470 /*
2471 * Compute all remaining keys for this document.
2472 *
2473 * REVISIT TODO: I think this could be further optimized.
2474 */
2475 if (xsltComputeAllKeys(ctxt, node) == -1)
2476 goto error;
2477
2478 if (xsltGetSourceNodeFlags(node) & XSLT_SOURCE_NODE_HAS_KEY)
2479 goto keyed_match;
2480 }
2481 if (ret != NULL)
2482 return(ret);
2483
2484 /*
2485 * Cycle on next curstylesheet import.
2486 */
2487 curstyle = xsltNextImport(curstyle);
2488 }
2489
2490error:
2491 return(NULL);
2492}
2493
2501void
2503}
2504
2511void
2513 if (style->templatesHash != NULL)
2515 if (style->rootMatch != NULL)
2516 xsltFreeCompMatchList(style->rootMatch);
2517 if (style->keyMatch != NULL)
2518 xsltFreeCompMatchList(style->keyMatch);
2519 if (style->elemMatch != NULL)
2520 xsltFreeCompMatchList(style->elemMatch);
2521 if (style->attrMatch != NULL)
2522 xsltFreeCompMatchList(style->attrMatch);
2523 if (style->parentMatch != NULL)
2524 xsltFreeCompMatchList(style->parentMatch);
2525 if (style->textMatch != NULL)
2526 xsltFreeCompMatchList(style->textMatch);
2527 if (style->piMatch != NULL)
2528 xsltFreeCompMatchList(style->piMatch);
2529 if (style->commentMatch != NULL)
2530 xsltFreeCompMatchList(style->commentMatch);
2531 if (style->namedTemplates != NULL)
2532 xmlHashFree(style->namedTemplates, NULL);
2533}
2534
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:118
xsltStepStates * xsltStepStatesPtr
Definition: pattern.c:77
static xmlChar * xsltScanLiteral(xsltParserContextPtr ctxt)
Definition: pattern.c:1220
#define NEXT
Definition: pattern.c:1190
static void xsltFreeParserContext(xsltParserContextPtr ctxt)
Definition: pattern.c:281
xsltAxis
Definition: pattern.c:64
@ AXIS_CHILD
Definition: pattern.c:65
@ AXIS_ATTRIBUTE
Definition: pattern.c:66
static void xsltCompileRelativePathPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar)
Definition: pattern.c:1709
static int xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr node, xsltStepOpPtr step, xsltStepOpPtr sel)
Definition: pattern.c:780
int xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, const xmlChar *mode, const xmlChar *modeURI)
Definition: pattern.c:2030
static int xsltComputeAllKeys(xsltTransformContextPtr ctxt, xmlNodePtr contextNode)
Definition: pattern.c:2232
static void xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, int aid, int novar, xsltAxis axis)
Definition: pattern.c:1319
static void xsltFreeCompMatchListEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: pattern.c:222
#define SKIP_BLANKS
Definition: pattern.c:1186
static xsltCompMatchPtr xsltNewCompMatch(void)
Definition: pattern.c:145
static void xsltReverseCompMatch(xsltParserContextPtr ctxt, xsltCompMatchPtr comp)
Definition: pattern.c:411
static void xmlXPathFreeObjectWrapper(void *obj)
Definition: pattern.c:506
static xsltParserContextPtr xsltNewParserContext(xsltStylesheetPtr style, xsltTransformContextPtr ctxt)
Definition: pattern.c:259
xsltTemplatePtr xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStylesheetPtr style)
Definition: pattern.c:2277
xsltCompMatchPtr xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node, xsltStylesheetPtr style, xsltTransformContextPtr runtime)
Definition: pattern.c:2006
static xsltCompMatchPtr xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node, xsltStylesheetPtr style, xsltTransformContextPtr runtime, int novar)
Definition: pattern.c:1830
static void xsltSwapTopCompMatch(xsltCompMatchPtr comp)
Definition: pattern.c:366
void xsltCleanupTemplates(xsltStylesheetPtr style ATTRIBUTE_UNUSED)
Definition: pattern.c:2502
static int xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp, xsltOp op, xmlChar *value, xmlChar *value2, int novar)
Definition: pattern.c:301
static xmlChar * xsltScanNCName(xsltParserContextPtr ctxt)
Definition: pattern.c:1275
static int xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr node, xmlNsPtr *nsList, int nsNr)
Definition: pattern.c:524
static int xsltPatPushState(xsltTransformContextPtr ctxt, xsltStepStates *states, int step, xmlNodePtr node)
Definition: pattern.c:480
static void xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar)
Definition: pattern.c:1503
xsltStepState * xsltStepStatePtr
Definition: pattern.c:70
static int xsltTestStepMatch(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStepOpPtr step)
Definition: pattern.c:632
int xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltCompMatchPtr comp)
Definition: pattern.c:1132
void xsltFreeCompMatchList(xsltCompMatchPtr comp)
Definition: pattern.c:211
static int xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr matchNode, const xmlChar *mode, const xmlChar *modeURI)
Definition: pattern.c:937
void xsltCompMatchClearCache(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp)
Definition: pattern.c:1155
xsltParserContext * xsltParserContextPtr
Definition: pattern.c:119
#define SWAP()
Definition: pattern.c:1196
void xsltNormalizeCompSteps(void *payload, void *data, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: pattern.c:236
static void xsltCompileLocationPathPattern(xsltParserContextPtr ctxt, int novar)
Definition: pattern.c:1750
static void xsltFreeCompMatch(xsltCompMatchPtr comp)
Definition: pattern.c:178
xsltOp
Definition: pattern.c:46
@ XSLT_OP_PREDICATE
Definition: pattern.c:61
@ XSLT_OP_PARENT
Definition: pattern.c:51
@ XSLT_OP_TEXT
Definition: pattern.c:59
@ XSLT_OP_END
Definition: pattern.c:47
@ XSLT_OP_ID
Definition: pattern.c:53
@ XSLT_OP_ALL
Definition: pattern.c:56
@ XSLT_OP_ELEM
Definition: pattern.c:49
@ XSLT_OP_NODE
Definition: pattern.c:60
@ XSLT_OP_ATTR
Definition: pattern.c:50
@ XSLT_OP_PI
Definition: pattern.c:57
@ XSLT_OP_COMMENT
Definition: pattern.c:58
@ XSLT_OP_KEY
Definition: pattern.c:54
@ XSLT_OP_ANCESTOR
Definition: pattern.c:52
@ XSLT_OP_ROOT
Definition: pattern.c:48
@ XSLT_OP_NS
Definition: pattern.c:55
void xsltFreeTemplateHashes(xsltStylesheetPtr style)
Definition: pattern.c:2512
#define NXT(val)
Definition: pattern.c:1183
#define PUSH(op, val, val2, novar)
Definition: pattern.c:1193
#define CUR_PTR
Definition: pattern.c:1184
xsltStepOp * xsltStepOpPtr
Definition: pattern.c:85
#define CUR
Definition: pattern.c:1181
UINT op
Definition: effect.c:236
int WINAPIV fprintf(FILE *file, const char *format,...)
Definition: file.c:5549
#define stderr
xsltDocumentPtr xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc)
Definition: documents.c:142
return ret
Definition: mutex.c:146
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:36
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:297
xsltCompMatch * xsltCompMatchPtr
Definition: pattern.h:29
int xsltInitAllDocKeys(xsltTransformContextPtr ctxt)
Definition: keys.c:555
xmlNodeSetPtr xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI, const xmlChar *value)
Definition: keys.c:437
#define dup
Definition: syshdrs.h:51
#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
static unsigned __int64 next
Definition: rand_nt.c:6
#define list
Definition: rosglue.h:35
#define exit(n)
Definition: config.h:202
const xmlChar * xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:824
xmlReallocFunc xmlRealloc
Definition: globals.c:214
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlMallocFunc xmlMalloc
Definition: globals.c:193
void xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc)
Definition: hash.c:229
void * xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2)
Definition: hash.c:754
xmlHashTablePtr xmlHashCreate(int size)
Definition: hash.c:160
int xmlHashUpdateEntry3(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, const xmlChar *key3, void *payload, xmlHashDeallocator dealloc)
Definition: hash.c:722
int xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, void *payload)
Definition: hash.c:639
int xmlHashAddEntry3(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, const xmlChar *key3, void *payload)
Definition: hash.c:659
void * xmlHashLookup3(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, const xmlChar *key3)
Definition: hash.c:806
#define memset(x, y, z)
Definition: compat.h:39
xmlNsPtr * nsList
Definition: pattern.c:113
const xmlChar * pattern
Definition: pattern.c:103
struct _xsltCompMatch * next
Definition: pattern.c:101
xsltTemplatePtr template
Definition: pattern.c:106
xsltStepOpPtr steps
Definition: pattern.c:115
const xmlChar * mode
Definition: pattern.c:104
float priority
Definition: pattern.c:102
xmlNodePtr node
Definition: pattern.c:107
const xmlChar * modeURI
Definition: pattern.c:105
xmlDocPtr doc
Definition: pattern.c:125
xsltStylesheetPtr style
Definition: pattern.c:121
xsltCompMatchPtr comp
Definition: pattern.c:128
const xmlChar * cur
Definition: pattern.c:123
const xmlChar * base
Definition: pattern.c:124
xsltTransformContextPtr ctxt
Definition: pattern.c:122
xmlNodePtr elem
Definition: pattern.c:126
int indexExtra
Definition: pattern.c:96
xmlChar * value
Definition: pattern.c:88
int lenExtra
Definition: pattern.c:97
int previousExtra
Definition: pattern.c:95
xmlXPathCompExprPtr comp
Definition: pattern.c:91
xmlChar * value2
Definition: pattern.c:89
xsltOp op
Definition: pattern.c:87
xmlChar * value3
Definition: pattern.c:90
xmlNodePtr node
Definition: pattern.c:73
xsltStepStatePtr states
Definition: pattern.c:81
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: query.h:86
Definition: match.c:28
Definition: name.c:39
Definition: mxnamespace.c:38
int xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, xmlNsPtr *nsList, int nsNr)
Definition: templates.c:57
Character const *const prefix
Definition: tempnam.cpp:195
Definition: dlist.c:348
Definition: pdh_main.c:96
XMLPUBFUN xmlAttrPtr xmlGetID(xmlDocPtr doc, const xmlChar *ID)
Definition: valid.c:2719
#define success(from, fromstr, to, tostr)
XMLPUBFUN xmlChar * xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:45
XMLPUBFUN xmlChar * xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
#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:55
int xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
Definition: xslt.c:840
int xsltAllocateExtra(xsltStylesheetPtr style)
Definition: xslt.c:824
const xmlChar * xsltGetQNameURI(xmlNodePtr node, xmlChar **name)
Definition: xsltutils.c:837
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:762
xmlXPathCompExprPtr xsltXPathCompileFlags(xsltStylesheetPtr style, const xmlChar *str, int flags)
Definition: xsltutils.c:2550
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:586
int xsltGetSourceNodeFlags(xmlNodePtr node)
Definition: xsltutils.c:1923
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:632
int xsltGetUTF8CharZ(const unsigned char *utf, int *len)
Definition: xsltutils.c:319
void * xsltGenericDebugContext
Definition: xsltutils.c:633
void * xsltGenericErrorContext
Definition: xsltutils.c:587