ReactOS  0.4.15-dev-440-g5f37b68
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 
27 typedef enum {
43 } xsltOp;
44 
45 typedef enum {
48 } xsltAxis;
49 
53  int step;
55 };
56 
60  int nbstates;
61  int maxstates;
63 };
64 
65 typedef struct _xsltStepOp xsltStepOp;
67 struct _xsltStepOp {
72  xmlXPathCompExprPtr comp;
73  /*
74  * Optimisations for count
75  */
78  int lenExtra;
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;
93  int maxStep;
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 
125 static xsltCompMatchPtr
127  xsltCompMatchPtr cur;
128 
129  cur = (xsltCompMatchPtr) xmlMalloc(sizeof(xsltCompMatch));
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;
138  cur-> steps = (xsltStepOpPtr) xmlMalloc(sizeof(xsltStepOp) *
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 
158 static 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 
191 void
193  xsltCompMatchPtr cur;
194 
195  while (comp != NULL) {
196  cur = comp;
197  comp = comp->next;
198  xsltFreeCompMatch(cur);
199  }
200 }
201 
202 static void
204  const xmlChar *name ATTRIBUTE_UNUSED) {
206 }
207 
217 void 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 
261 static void
263  if (ctxt == NULL)
264  return;
265  memset(ctxt, -1, sizeof(xsltParserContext));
266  xmlFree(ctxt);
267 }
268 
281 static 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 =
318  xsltAllocateExtra(ctxt->style);
319  comp->steps[comp->nbStep].indexExtra =
320  xsltAllocateExtra(ctxt->style);
321  comp->steps[comp->nbStep].lenExtra =
322  xsltAllocateExtra(ctxt->style);
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 
350 static 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 
395 static 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 and predicates on ops which
437  * haven't been optimized yet indicating a direct matching should be done.
438  */
439  for (i = 0;i < comp->nbStep - 1;i++) {
440  xsltOp op = comp->steps[i].op;
441 
442  if ((op != XSLT_OP_ELEM) &&
443  (op != XSLT_OP_ALL) &&
444  (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) {
445 
446  comp->direct = 1;
447  if (comp->pattern[0] != '/') {
448  xmlChar *query;
449 
450  query = xmlStrdup((const xmlChar *)"//");
451  query = xmlStrcat(query, comp->pattern);
452 
453  xmlFree((xmlChar *) comp->pattern);
454  comp->pattern = query;
455  }
456  break;
457  }
458  }
459 }
460 
461 /************************************************************************
462  * *
463  * The interpreter for the precompiled patterns *
464  * *
465  ************************************************************************/
466 
467 static int
469  int step, xmlNodePtr node) {
470  if ((states->states == NULL) || (states->maxstates <= 0)) {
471  states->maxstates = 4;
472  states->nbstates = 0;
473  states->states = xmlMalloc(4 * sizeof(xsltStepState));
474  }
475  else if (states->maxstates <= states->nbstates) {
476  xsltStepState *tmp;
477 
478  tmp = (xsltStepStatePtr) xmlRealloc(states->states,
479  2 * states->maxstates * sizeof(xsltStepState));
480  if (tmp == NULL) {
482  "xsltPatPushState: memory re-allocation failure.\n");
483  ctxt->state = XSLT_STATE_STOPPED;
484  return(-1);
485  }
486  states->states = tmp;
487  states->maxstates *= 2;
488  }
489  states->states[states->nbstates].step = step;
490  states->states[states->nbstates++].node = node;
491 #if 0
492  fprintf(stderr, "Push: %d, %s\n", step, node->name);
493 #endif
494  return(0);
495 }
496 
497 static void
499  xmlXPathFreeObject((xmlXPathObjectPtr) obj);
500 }
501 
515 static int
518  xsltStepOpPtr sel = NULL;
519  xmlDocPtr prevdoc;
520  xmlDocPtr doc;
521  xmlXPathObjectPtr list;
522  int ix, j;
523  int nocache = 0;
524  int isRVT;
525 
526  doc = node->doc;
527  if (XSLT_IS_RES_TREE_FRAG(doc))
528  isRVT = 1;
529  else
530  isRVT = 0;
531  sel = &comp->steps[0]; /* store extra in first step arbitrarily */
532 
533  prevdoc = (xmlDocPtr)
534  XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
535  ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
536  list = (xmlXPathObjectPtr)
537  XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
538 
539  if ((list == NULL) || (prevdoc != doc)) {
540  xmlXPathObjectPtr newlist;
541  xmlNodePtr parent = node->parent;
542  xmlDocPtr olddoc;
543  xmlNodePtr oldnode;
544  int oldNsNr, oldContextSize, oldProximityPosition;
545  xmlNsPtr *oldNamespaces;
546 
547  oldnode = ctxt->xpathCtxt->node;
548  olddoc = ctxt->xpathCtxt->doc;
549  oldNsNr = ctxt->xpathCtxt->nsNr;
550  oldNamespaces = ctxt->xpathCtxt->namespaces;
551  oldContextSize = ctxt->xpathCtxt->contextSize;
552  oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
553  ctxt->xpathCtxt->node = node;
554  ctxt->xpathCtxt->doc = doc;
555  ctxt->xpathCtxt->namespaces = nsList;
556  ctxt->xpathCtxt->nsNr = nsNr;
557  newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt);
558  ctxt->xpathCtxt->node = oldnode;
559  ctxt->xpathCtxt->doc = olddoc;
560  ctxt->xpathCtxt->namespaces = oldNamespaces;
561  ctxt->xpathCtxt->nsNr = oldNsNr;
562  ctxt->xpathCtxt->contextSize = oldContextSize;
563  ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
564  if (newlist == NULL)
565  return(-1);
566  if (newlist->type != XPATH_NODESET) {
567  xmlXPathFreeObject(newlist);
568  return(-1);
569  }
570  ix = 0;
571 
572  if ((parent == NULL) || (node->doc == NULL) || isRVT)
573  nocache = 1;
574 
575  if (nocache == 0) {
576  if (list != NULL)
577  xmlXPathFreeObject(list);
578  list = newlist;
579 
580  XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) =
581  (void *) list;
582  XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
583  (void *) doc;
584  XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
585  0;
586  XSLT_RUNTIME_EXTRA_FREE(ctxt, sel->lenExtra) =
588  } else
589  list = newlist;
590  }
591  if ((list->nodesetval == NULL) ||
592  (list->nodesetval->nodeNr <= 0)) {
593  if (nocache == 1)
594  xmlXPathFreeObject(list);
595  return(0);
596  }
597  /* TODO: store the index and use it for the scan */
598  if (ix == 0) {
599  for (j = 0;j < list->nodesetval->nodeNr;j++) {
600  if (list->nodesetval->nodeTab[j] == node) {
601  if (nocache == 1)
602  xmlXPathFreeObject(list);
603  return(1);
604  }
605  }
606  } else {
607  }
608  if (nocache == 1)
609  xmlXPathFreeObject(list);
610  return(0);
611 }
612 
625 static int
628  xsltStepOpPtr sel) {
629  xmlNodePtr oldNode;
630  xmlDocPtr doc;
631  int oldCS, oldCP;
632  int pos = 0, len = 0;
633  int isRVT;
634  int match;
635 
636  if (step->value == NULL)
637  return(0);
638  if (step->comp == NULL)
639  return(0);
640 
641  doc = node->doc;
642  if (XSLT_IS_RES_TREE_FRAG(doc))
643  isRVT = 1;
644  else
645  isRVT = 0;
646 
647  /*
648  * Recompute contextSize and proximityPosition.
649  *
650  * TODO: Make this work for additional ops. Currently, only XSLT_OP_ELEM
651  * and XSLT_OP_ALL are supported.
652  */
653  oldCS = ctxt->xpathCtxt->contextSize;
654  oldCP = ctxt->xpathCtxt->proximityPosition;
655  if ((sel != NULL) &&
656  (sel->op == XSLT_OP_ELEM) &&
657  (sel->value != NULL) &&
658  (node->type == XML_ELEMENT_NODE) &&
659  (node->parent != NULL)) {
660  xmlNodePtr previous;
661  int nocache = 0;
662 
663  previous = (xmlNodePtr)
664  XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
665  if ((previous != NULL) &&
666  (previous->parent == node->parent)) {
667  /*
668  * just walk back to adjust the index
669  */
670  int indx = 0;
671  xmlNodePtr sibling = node;
672 
673  while (sibling != NULL) {
674  if (sibling == previous)
675  break;
676  if ((sibling->type == XML_ELEMENT_NODE) &&
677  (previous->name != NULL) &&
678  (sibling->name != NULL) &&
679  (previous->name[0] == sibling->name[0]) &&
680  (xmlStrEqual(previous->name, sibling->name)))
681  {
682  if ((sel->value2 == NULL) ||
683  ((sibling->ns != NULL) &&
684  (xmlStrEqual(sel->value2, sibling->ns->href))))
685  indx++;
686  }
687  sibling = sibling->prev;
688  }
689  if (sibling == NULL) {
690  /* hum going backward in document order ... */
691  indx = 0;
692  sibling = node;
693  while (sibling != NULL) {
694  if (sibling == previous)
695  break;
696  if ((sibling->type == XML_ELEMENT_NODE) &&
697  (previous->name != NULL) &&
698  (sibling->name != NULL) &&
699  (previous->name[0] == sibling->name[0]) &&
700  (xmlStrEqual(previous->name, sibling->name)))
701  {
702  if ((sel->value2 == NULL) ||
703  ((sibling->ns != NULL) &&
704  (xmlStrEqual(sel->value2,
705  sibling->ns->href))))
706  {
707  indx--;
708  }
709  }
710  sibling = sibling->next;
711  }
712  }
713  if (sibling != NULL) {
714  pos = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) + indx;
715  /*
716  * If the node is in a Value Tree we need to
717  * save len, but cannot cache the node!
718  * (bugs 153137 and 158840)
719  */
720  if (node->doc != NULL) {
721  len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
722  if (!isRVT) {
723  XSLT_RUNTIME_EXTRA(ctxt,
724  sel->previousExtra, ptr) = node;
725  XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
726  }
727  }
728  } else
729  pos = 0;
730  } else {
731  /*
732  * recompute the index
733  */
734  xmlNodePtr parent = node->parent;
735  xmlNodePtr siblings = NULL;
736 
737  if (parent) siblings = parent->children;
738 
739  while (siblings != NULL) {
740  if (siblings->type == XML_ELEMENT_NODE) {
741  if (siblings == node) {
742  len++;
743  pos = len;
744  } else if ((node->name != NULL) &&
745  (siblings->name != NULL) &&
746  (node->name[0] == siblings->name[0]) &&
747  (xmlStrEqual(node->name, siblings->name))) {
748  if ((sel->value2 == NULL) ||
749  ((siblings->ns != NULL) &&
750  (xmlStrEqual(sel->value2, siblings->ns->href))))
751  len++;
752  }
753  }
754  siblings = siblings->next;
755  }
756  if ((parent == NULL) || (node->doc == NULL))
757  nocache = 1;
758  else {
759  while (parent->parent != NULL)
760  parent = parent->parent;
761  if (((parent->type != XML_DOCUMENT_NODE) &&
762  (parent->type != XML_HTML_DOCUMENT_NODE)) ||
763  (parent != (xmlNodePtr) node->doc))
764  nocache = 1;
765  }
766  }
767  if (pos != 0) {
768  ctxt->xpathCtxt->contextSize = len;
769  ctxt->xpathCtxt->proximityPosition = pos;
770  /*
771  * If the node is in a Value Tree we cannot
772  * cache it !
773  */
774  if ((!isRVT) && (node->doc != NULL) &&
775  (nocache == 0)) {
776  XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
777  XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
778  XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
779  }
780  }
781  } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) &&
782  (node->type == XML_ELEMENT_NODE)) {
783  xmlNodePtr previous;
784  int nocache = 0;
785 
786  previous = (xmlNodePtr)
787  XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
788  if ((previous != NULL) &&
789  (previous->parent == node->parent)) {
790  /*
791  * just walk back to adjust the index
792  */
793  int indx = 0;
794  xmlNodePtr sibling = node;
795 
796  while (sibling != NULL) {
797  if (sibling == previous)
798  break;
799  if (sibling->type == XML_ELEMENT_NODE)
800  indx++;
801  sibling = sibling->prev;
802  }
803  if (sibling == NULL) {
804  /* hum going backward in document order ... */
805  indx = 0;
806  sibling = node;
807  while (sibling != NULL) {
808  if (sibling == previous)
809  break;
810  if (sibling->type == XML_ELEMENT_NODE)
811  indx--;
812  sibling = sibling->next;
813  }
814  }
815  if (sibling != NULL) {
816  pos = XSLT_RUNTIME_EXTRA(ctxt,
817  sel->indexExtra, ival) + indx;
818  /*
819  * If the node is in a Value Tree we cannot
820  * cache it !
821  */
822  if ((node->doc != NULL) && !isRVT) {
823  len = XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival);
824  XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
825  XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
826  }
827  } else
828  pos = 0;
829  } else {
830  /*
831  * recompute the index
832  */
833  xmlNodePtr parent = node->parent;
834  xmlNodePtr siblings = NULL;
835 
836  if (parent) siblings = parent->children;
837 
838  while (siblings != NULL) {
839  if (siblings->type == XML_ELEMENT_NODE) {
840  len++;
841  if (siblings == node) {
842  pos = len;
843  }
844  }
845  siblings = siblings->next;
846  }
847  if ((parent == NULL) || (node->doc == NULL))
848  nocache = 1;
849  else {
850  while (parent->parent != NULL)
851  parent = parent->parent;
852  if (((parent->type != XML_DOCUMENT_NODE) &&
853  (parent->type != XML_HTML_DOCUMENT_NODE)) ||
854  (parent != (xmlNodePtr) node->doc))
855  nocache = 1;
856  }
857  }
858  if (pos != 0) {
859  ctxt->xpathCtxt->contextSize = len;
860  ctxt->xpathCtxt->proximityPosition = pos;
861  /*
862  * If the node is in a Value Tree we cannot
863  * cache it !
864  */
865  if ((node->doc != NULL) && (nocache == 0) && !isRVT) {
866  XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = node;
867  XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = pos;
868  XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) = len;
869  }
870  }
871  }
872 
873  oldNode = ctxt->node;
874  ctxt->node = node;
875 
876  match = xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList, comp->nsNr);
877 
878  if (pos != 0) {
879  ctxt->xpathCtxt->contextSize = oldCS;
880  ctxt->xpathCtxt->proximityPosition = oldCP;
881  }
882  ctxt->node = oldNode;
883 
884  return match;
885 }
886 
899 static int
901  xmlNodePtr matchNode, const xmlChar *mode,
902  const xmlChar *modeURI) {
903  int i;
904  int found = 0;
905  xmlNodePtr node = matchNode;
906  xmlNodePtr oldInst;
907  xsltStepOpPtr step, sel = NULL;
908  xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
909 
910  if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) {
912  "xsltTestCompMatch: null arg\n");
913  return(-1);
914  }
915  if (mode != NULL) {
916  if (comp->mode == NULL)
917  return(0);
918  /*
919  * both mode strings must be interned on the stylesheet dictionary
920  */
921  if (comp->mode != mode)
922  return(0);
923  } else {
924  if (comp->mode != NULL)
925  return(0);
926  }
927  if (modeURI != NULL) {
928  if (comp->modeURI == NULL)
929  return(0);
930  /*
931  * both modeURI strings must be interned on the stylesheet dictionary
932  */
933  if (comp->modeURI != modeURI)
934  return(0);
935  } else {
936  if (comp->modeURI != NULL)
937  return(0);
938  }
939 
940  /* Some XPath functions rely on inst being set correctly. */
941  oldInst = ctxt->inst;
942  ctxt->inst = comp->node;
943 
944  i = 0;
945 restart:
946  for (;i < comp->nbStep;i++) {
947  step = &comp->steps[i];
948  if (step->op != XSLT_OP_PREDICATE)
949  sel = step;
950  switch (step->op) {
951  case XSLT_OP_END:
952  goto found;
953  case XSLT_OP_ROOT:
954  if ((node->type == XML_DOCUMENT_NODE) ||
955 #ifdef LIBXML_DOCB_ENABLED
956  (node->type == XML_DOCB_DOCUMENT_NODE) ||
957 #endif
958  (node->type == XML_HTML_DOCUMENT_NODE))
959  continue;
960  if ((node->type == XML_ELEMENT_NODE) && (node->name[0] == ' '))
961  continue;
962  goto rollback;
963  case XSLT_OP_ELEM:
964  if (node->type != XML_ELEMENT_NODE)
965  goto rollback;
966  if (step->value == NULL)
967  continue;
968  if (step->value[0] != node->name[0])
969  goto rollback;
970  if (!xmlStrEqual(step->value, node->name))
971  goto rollback;
972 
973  /* Namespace test */
974  if (node->ns == NULL) {
975  if (step->value2 != NULL)
976  goto rollback;
977  } else if (node->ns->href != NULL) {
978  if (step->value2 == NULL)
979  goto rollback;
980  if (!xmlStrEqual(step->value2, node->ns->href))
981  goto rollback;
982  }
983  continue;
984  case XSLT_OP_ATTR:
985  if (node->type != XML_ATTRIBUTE_NODE)
986  goto rollback;
987  if (step->value != NULL) {
988  if (step->value[0] != node->name[0])
989  goto rollback;
990  if (!xmlStrEqual(step->value, node->name))
991  goto rollback;
992  }
993  /* Namespace test */
994  if (node->ns == NULL) {
995  if (step->value2 != NULL)
996  goto rollback;
997  } else if (step->value2 != NULL) {
998  if (!xmlStrEqual(step->value2, node->ns->href))
999  goto rollback;
1000  }
1001  continue;
1002  case XSLT_OP_PARENT:
1003  if ((node->type == XML_DOCUMENT_NODE) ||
1004  (node->type == XML_HTML_DOCUMENT_NODE) ||
1005 #ifdef LIBXML_DOCB_ENABLED
1006  (node->type == XML_DOCB_DOCUMENT_NODE) ||
1007 #endif
1008  (node->type == XML_NAMESPACE_DECL))
1009  goto rollback;
1010  node = node->parent;
1011  if (node == NULL)
1012  goto rollback;
1013  if (step->value == NULL)
1014  continue;
1015  if (step->value[0] != node->name[0])
1016  goto rollback;
1017  if (!xmlStrEqual(step->value, node->name))
1018  goto rollback;
1019  /* Namespace test */
1020  if (node->ns == NULL) {
1021  if (step->value2 != NULL)
1022  goto rollback;
1023  } else if (node->ns->href != NULL) {
1024  if (step->value2 == NULL)
1025  goto rollback;
1026  if (!xmlStrEqual(step->value2, node->ns->href))
1027  goto rollback;
1028  }
1029  continue;
1030  case XSLT_OP_ANCESTOR:
1031  /* TODO: implement coalescing of ANCESTOR/NODE ops */
1032  if (step->value == NULL) {
1033  step = &comp->steps[i+1];
1034  if (step->op == XSLT_OP_ROOT)
1035  goto found;
1036  /* added NS, ID and KEY as a result of bug 168208 */
1037  if ((step->op != XSLT_OP_ELEM) &&
1038  (step->op != XSLT_OP_ALL) &&
1039  (step->op != XSLT_OP_NS) &&
1040  (step->op != XSLT_OP_ID) &&
1041  (step->op != XSLT_OP_KEY))
1042  goto rollback;
1043  }
1044  if (node == NULL)
1045  goto rollback;
1046  if ((node->type == XML_DOCUMENT_NODE) ||
1047  (node->type == XML_HTML_DOCUMENT_NODE) ||
1048 #ifdef LIBXML_DOCB_ENABLED
1049  (node->type == XML_DOCB_DOCUMENT_NODE) ||
1050 #endif
1051  (node->type == XML_NAMESPACE_DECL))
1052  goto rollback;
1053  node = node->parent;
1054  if ((step->op != XSLT_OP_ELEM) && step->op != XSLT_OP_ALL) {
1055  xsltPatPushState(ctxt, &states, i, node);
1056  continue;
1057  }
1058  i++;
1059  if (step->value == NULL) {
1060  xsltPatPushState(ctxt, &states, i - 1, node);
1061  continue;
1062  }
1063  while (node != NULL) {
1064  if ((node->type == XML_ELEMENT_NODE) &&
1065  (step->value[0] == node->name[0]) &&
1066  (xmlStrEqual(step->value, node->name))) {
1067  /* Namespace test */
1068  if (node->ns == NULL) {
1069  if (step->value2 == NULL)
1070  break;
1071  } else if (node->ns->href != NULL) {
1072  if ((step->value2 != NULL) &&
1073  (xmlStrEqual(step->value2, node->ns->href)))
1074  break;
1075  }
1076  }
1077  node = node->parent;
1078  }
1079  if (node == NULL)
1080  goto rollback;
1081  xsltPatPushState(ctxt, &states, i - 1, node);
1082  continue;
1083  case XSLT_OP_ID: {
1084  /* TODO Handle IDs decently, must be done differently */
1085  xmlAttrPtr id;
1086 
1087  if (node->type != XML_ELEMENT_NODE)
1088  goto rollback;
1089 
1090  id = xmlGetID(node->doc, step->value);
1091  if ((id == NULL) || (id->parent != node))
1092  goto rollback;
1093  break;
1094  }
1095  case XSLT_OP_KEY: {
1096  xmlNodeSetPtr list;
1097  int indx;
1098 
1099  list = xsltGetKey(ctxt, step->value,
1100  step->value3, step->value2);
1101  if (list == NULL)
1102  goto rollback;
1103  for (indx = 0;indx < list->nodeNr;indx++)
1104  if (list->nodeTab[indx] == node)
1105  break;
1106  if (indx >= list->nodeNr)
1107  goto rollback;
1108  break;
1109  }
1110  case XSLT_OP_NS:
1111  if (node->type != XML_ELEMENT_NODE)
1112  goto rollback;
1113  if (node->ns == NULL) {
1114  if (step->value != NULL)
1115  goto rollback;
1116  } else if (node->ns->href != NULL) {
1117  if (step->value == NULL)
1118  goto rollback;
1119  if (!xmlStrEqual(step->value, node->ns->href))
1120  goto rollback;
1121  }
1122  break;
1123  case XSLT_OP_ALL:
1124  if (node->type != XML_ELEMENT_NODE)
1125  goto rollback;
1126  break;
1127  case XSLT_OP_PREDICATE: {
1128  /*
1129  * When there is cascading XSLT_OP_PREDICATE or a predicate
1130  * after an op which hasn't been optimized yet, then use a
1131  * direct computation approach. It's not done directly
1132  * at the beginning of the routine to filter out as much
1133  * as possible this costly computation.
1134  */
1135  if (comp->direct) {
1136  found = xsltTestCompMatchDirect(ctxt, comp, matchNode,
1137  comp->nsList, comp->nsNr);
1138  goto exit;
1139  }
1140 
1141  if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel))
1142  goto rollback;
1143 
1144  break;
1145  }
1146  case XSLT_OP_PI:
1147  if (node->type != XML_PI_NODE)
1148  goto rollback;
1149  if (step->value != NULL) {
1150  if (!xmlStrEqual(step->value, node->name))
1151  goto rollback;
1152  }
1153  break;
1154  case XSLT_OP_COMMENT:
1155  if (node->type != XML_COMMENT_NODE)
1156  goto rollback;
1157  break;
1158  case XSLT_OP_TEXT:
1159  if ((node->type != XML_TEXT_NODE) &&
1160  (node->type != XML_CDATA_SECTION_NODE))
1161  goto rollback;
1162  break;
1163  case XSLT_OP_NODE:
1164  switch (node->type) {
1165  case XML_ELEMENT_NODE:
1167  case XML_PI_NODE:
1168  case XML_COMMENT_NODE:
1169  case XML_TEXT_NODE:
1170  break;
1171  default:
1172  goto rollback;
1173  }
1174  break;
1175  }
1176  }
1177 found:
1178  found = 1;
1179 exit:
1180  ctxt->inst = oldInst;
1181  if (states.states != NULL) {
1182  /* Free the rollback states */
1183  xmlFree(states.states);
1184  }
1185  return found;
1186 rollback:
1187  /* got an error try to rollback */
1188  if (states.states == NULL || states.nbstates <= 0) {
1189  found = 0;
1190  goto exit;
1191  }
1192  states.nbstates--;
1193  i = states.states[states.nbstates].step;
1194  node = states.states[states.nbstates].node;
1195 #if 0
1196  fprintf(stderr, "Pop: %d, %s\n", i, node->name);
1197 #endif
1198  goto restart;
1199 }
1200 
1211 int
1213  xsltCompMatchPtr comp) {
1214  int ret;
1215 
1216  if ((ctxt == NULL) || (node == NULL))
1217  return(-1);
1218  while (comp != NULL) {
1219  ret = xsltTestCompMatch(ctxt, comp, node, NULL, NULL);
1220  if (ret == 1)
1221  return(1);
1222  comp = comp->next;
1223  }
1224  return(0);
1225 }
1226 
1234 void
1236  xsltStepOpPtr sel;
1237  xmlXPathObjectPtr list;
1238 
1239  if ((ctxt == NULL) || (comp == NULL))
1240  return;
1241 
1242  sel = &comp->steps[0];
1243  list = (xmlXPathObjectPtr) XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
1244 
1245  if (list != NULL) {
1246  xmlXPathFreeObject(list);
1247 
1248  XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) = NULL;
1249  XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) = NULL;
1250  XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) = 0;
1251  XSLT_RUNTIME_EXTRA_FREE(ctxt, sel->lenExtra) = NULL;
1252  }
1253 }
1254 
1255 /************************************************************************
1256  * *
1257  * Dedicated parser for templates *
1258  * *
1259  ************************************************************************/
1260 
1261 #define CUR (*ctxt->cur)
1262 #define SKIP(val) ctxt->cur += (val)
1263 #define NXT(val) ctxt->cur[(val)]
1264 #define CUR_PTR ctxt->cur
1265 
1266 #define SKIP_BLANKS \
1267  while (IS_BLANK_CH(CUR)) NEXT
1268 
1269 #define CURRENT (*ctxt->cur)
1270 #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
1271 
1272 
1273 #define PUSH(op, val, val2, novar) \
1274  if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto error;
1275 
1276 #define SWAP() \
1277  xsltSwapTopCompMatch(ctxt->comp);
1278 
1279 #define XSLT_ERROR(X) \
1280  { xsltError(ctxt, __FILE__, __LINE__, X); \
1281  ctxt->error = (X); return; }
1282 
1283 #define XSLT_ERROR0(X) \
1284  { xsltError(ctxt, __FILE__, __LINE__, X); \
1285  ctxt->error = (X); return(0); }
1286 
1299 static xmlChar *
1301  const xmlChar *q, *cur;
1302  xmlChar *ret = NULL;
1303  int val, len;
1304 
1305  SKIP_BLANKS;
1306  if (CUR == '"') {
1307  NEXT;
1308  cur = q = CUR_PTR;
1309  val = xmlStringCurrentChar(NULL, cur, &len);
1310  while ((IS_CHAR(val)) && (val != '"')) {
1311  cur += len;
1312  val = xmlStringCurrentChar(NULL, cur, &len);
1313  }
1314  if (!IS_CHAR(val)) {
1315  ctxt->error = 1;
1316  return(NULL);
1317  } else {
1318  ret = xmlStrndup(q, cur - q);
1319  }
1320  cur += len;
1321  CUR_PTR = cur;
1322  } else if (CUR == '\'') {
1323  NEXT;
1324  cur = q = CUR_PTR;
1325  val = xmlStringCurrentChar(NULL, cur, &len);
1326  while ((IS_CHAR(val)) && (val != '\'')) {
1327  cur += len;
1328  val = xmlStringCurrentChar(NULL, cur, &len);
1329  }
1330  if (!IS_CHAR(val)) {
1331  ctxt->error = 1;
1332  return(NULL);
1333  } else {
1334  ret = xmlStrndup(q, cur - q);
1335  }
1336  cur += len;
1337  CUR_PTR = cur;
1338  } else {
1339  /* XP_ERROR(XPATH_START_LITERAL_ERROR); */
1340  ctxt->error = 1;
1341  return(NULL);
1342  }
1343  return(ret);
1344 }
1345 
1355 static xmlChar *
1357  const xmlChar *q, *cur;
1358  xmlChar *ret = NULL;
1359  int val, len;
1360 
1361  SKIP_BLANKS;
1362 
1363  cur = q = CUR_PTR;
1364  val = xmlStringCurrentChar(NULL, cur, &len);
1365  if (!IS_LETTER(val) && (val != '_'))
1366  return(NULL);
1367 
1368  while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
1369  (val == '.') || (val == '-') ||
1370  (val == '_') ||
1371  (IS_COMBINING(val)) ||
1372  (IS_EXTENDER(val))) {
1373  cur += len;
1374  val = xmlStringCurrentChar(NULL, cur, &len);
1375  }
1376  ret = xmlStrndup(q, cur - q);
1377  CUR_PTR = cur;
1378  return(ret);
1379 }
1380 
1381 /*
1382  * xsltCompileIdKeyPattern:
1383  * @ctxt: the compilation context
1384  * @name: a preparsed name
1385  * @aid: whether id/key are allowed there
1386  * @novar: flag to prohibit xslt var
1387  *
1388  * Compile the XSLT LocationIdKeyPattern
1389  * [3] IdKeyPattern ::= 'id' '(' Literal ')'
1390  * | 'key' '(' Literal ',' Literal ')'
1391  *
1392  * also handle NodeType and PI from:
1393  *
1394  * [7] NodeTest ::= NameTest
1395  * | NodeType '(' ')'
1396  * | 'processing-instruction' '(' Literal ')'
1397  */
1398 static void
1400  int aid, int novar, xsltAxis axis) {
1401  xmlChar *lit = NULL;
1402  xmlChar *lit2 = NULL;
1403 
1404  if (CUR != '(') {
1406  "xsltCompileIdKeyPattern : ( expected\n");
1407  ctxt->error = 1;
1408  return;
1409  }
1410  if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) {
1411  if (axis != 0) {
1413  "xsltCompileIdKeyPattern : NodeTest expected\n");
1414  ctxt->error = 1;
1415  return;
1416  }
1417  NEXT;
1418  SKIP_BLANKS;
1419  lit = xsltScanLiteral(ctxt);
1420  if (ctxt->error) {
1422  "xsltCompileIdKeyPattern : Literal expected\n");
1423  return;
1424  }
1425  SKIP_BLANKS;
1426  if (CUR != ')') {
1428  "xsltCompileIdKeyPattern : ) expected\n");
1429  xmlFree(lit);
1430  ctxt->error = 1;
1431  return;
1432  }
1433  NEXT;
1434  PUSH(XSLT_OP_ID, lit, NULL, novar);
1435  lit = NULL;
1436  } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) {
1437  if (axis != 0) {
1439  "xsltCompileIdKeyPattern : NodeTest expected\n");
1440  ctxt->error = 1;
1441  return;
1442  }
1443  NEXT;
1444  SKIP_BLANKS;
1445  lit = xsltScanLiteral(ctxt);
1446  if (ctxt->error) {
1448  "xsltCompileIdKeyPattern : Literal expected\n");
1449  return;
1450  }
1451  SKIP_BLANKS;
1452  if (CUR != ',') {
1454  "xsltCompileIdKeyPattern : , expected\n");
1455  xmlFree(lit);
1456  ctxt->error = 1;
1457  return;
1458  }
1459  NEXT;
1460  SKIP_BLANKS;
1461  lit2 = xsltScanLiteral(ctxt);
1462  if (ctxt->error) {
1464  "xsltCompileIdKeyPattern : Literal expected\n");
1465  xmlFree(lit);
1466  return;
1467  }
1468  SKIP_BLANKS;
1469  if (CUR != ')') {
1471  "xsltCompileIdKeyPattern : ) expected\n");
1472  xmlFree(lit);
1473  xmlFree(lit2);
1474  ctxt->error = 1;
1475  return;
1476  }
1477  NEXT;
1478  /* URGENT TODO: support namespace in keys */
1479  PUSH(XSLT_OP_KEY, lit, lit2, novar);
1480  lit = NULL;
1481  lit2 = NULL;
1482  } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {
1483  NEXT;
1484  SKIP_BLANKS;
1485  if (CUR != ')') {
1486  lit = xsltScanLiteral(ctxt);
1487  if (ctxt->error) {
1489  "xsltCompileIdKeyPattern : Literal expected\n");
1490  return;
1491  }
1492  SKIP_BLANKS;
1493  if (CUR != ')') {
1495  "xsltCompileIdKeyPattern : ) expected\n");
1496  ctxt->error = 1;
1497  xmlFree(lit);
1498  return;
1499  }
1500  }
1501  NEXT;
1502  PUSH(XSLT_OP_PI, lit, NULL, novar);
1503  lit = NULL;
1504  } else if (xmlStrEqual(name, (const xmlChar *)"text")) {
1505  NEXT;
1506  SKIP_BLANKS;
1507  if (CUR != ')') {
1509  "xsltCompileIdKeyPattern : ) expected\n");
1510  ctxt->error = 1;
1511  return;
1512  }
1513  NEXT;
1514  PUSH(XSLT_OP_TEXT, NULL, NULL, novar);
1515  } else if (xmlStrEqual(name, (const xmlChar *)"comment")) {
1516  NEXT;
1517  SKIP_BLANKS;
1518  if (CUR != ')') {
1520  "xsltCompileIdKeyPattern : ) expected\n");
1521  ctxt->error = 1;
1522  return;
1523  }
1524  NEXT;
1525  PUSH(XSLT_OP_COMMENT, NULL, NULL, novar);
1526  } else if (xmlStrEqual(name, (const xmlChar *)"node")) {
1527  NEXT;
1528  SKIP_BLANKS;
1529  if (CUR != ')') {
1531  "xsltCompileIdKeyPattern : ) expected\n");
1532  ctxt->error = 1;
1533  return;
1534  }
1535  NEXT;
1536  if (axis == AXIS_ATTRIBUTE) {
1537  PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
1538  }
1539  else {
1540  PUSH(XSLT_OP_NODE, NULL, NULL, novar);
1541  }
1542  } else if (aid) {
1544  "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n");
1545  ctxt->error = 1;
1546  return;
1547  } else {
1549  "xsltCompileIdKeyPattern : node type\n");
1550  ctxt->error = 1;
1551  return;
1552  }
1553 error:
1554  return;
1555 }
1556 
1579 static void
1581  xmlChar *name = NULL;
1582  const xmlChar *URI = NULL;
1583  xmlChar *URL = NULL;
1584  int level;
1585  xsltAxis axis = 0;
1586 
1587  SKIP_BLANKS;
1588  if ((token == NULL) && (CUR == '@')) {
1589  NEXT;
1590  axis = AXIS_ATTRIBUTE;
1591  }
1592 parse_node_test:
1593  if (token == NULL)
1594  token = xsltScanNCName(ctxt);
1595  if (token == NULL) {
1596  if (CUR == '*') {
1597  NEXT;
1598  if (axis == AXIS_ATTRIBUTE) {
1599  PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
1600  }
1601  else {
1602  PUSH(XSLT_OP_ALL, NULL, NULL, novar);
1603  }
1604  goto parse_predicate;
1605  } else {
1607  "xsltCompileStepPattern : Name expected\n");
1608  ctxt->error = 1;
1609  goto error;
1610  }
1611  }
1612 
1613 
1614  SKIP_BLANKS;
1615  if (CUR == '(') {
1616  xsltCompileIdKeyPattern(ctxt, token, 0, novar, axis);
1617  xmlFree(token);
1618  token = NULL;
1619  if (ctxt->error)
1620  goto error;
1621  } else if (CUR == ':') {
1622  NEXT;
1623  if (CUR != ':') {
1624  xmlChar *prefix = token;
1625  xmlNsPtr ns;
1626 
1627  /*
1628  * This is a namespace match
1629  */
1630  token = xsltScanNCName(ctxt);
1631  ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);
1632  if (ns == NULL) {
1634  "xsltCompileStepPattern : no namespace bound to prefix %s\n",
1635  prefix);
1636  xmlFree(prefix);
1637  prefix=NULL;
1638  ctxt->error = 1;
1639  goto error;
1640  } else {
1641  URL = xmlStrdup(ns->href);
1642  }
1643  xmlFree(prefix);
1644  prefix=NULL;
1645  if (token == NULL) {
1646  if (CUR == '*') {
1647  NEXT;
1648  if (axis == AXIS_ATTRIBUTE) {
1649  PUSH(XSLT_OP_ATTR, NULL, URL, novar);
1650  URL = NULL;
1651  }
1652  else {
1653  PUSH(XSLT_OP_NS, URL, NULL, novar);
1654  URL = NULL;
1655  }
1656  } else {
1658  "xsltCompileStepPattern : Name expected\n");
1659  ctxt->error = 1;
1660  xmlFree(URL);
1661  goto error;
1662  }
1663  } else {
1664  if (axis == AXIS_ATTRIBUTE) {
1665  PUSH(XSLT_OP_ATTR, token, URL, novar);
1666  token = NULL;
1667  URL = NULL;
1668  }
1669  else {
1670  PUSH(XSLT_OP_ELEM, token, URL, novar);
1671  token = NULL;
1672  URL = NULL;
1673  }
1674  }
1675  } else {
1676  if (axis != 0) {
1678  "xsltCompileStepPattern : NodeTest expected\n");
1679  ctxt->error = 1;
1680  goto error;
1681  }
1682  NEXT;
1683  if (xmlStrEqual(token, (const xmlChar *) "child")) {
1684  axis = AXIS_CHILD;
1685  } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) {
1686  axis = AXIS_ATTRIBUTE;
1687  } else {
1689  "xsltCompileStepPattern : 'child' or 'attribute' expected\n");
1690  ctxt->error = 1;
1691  goto error;
1692  }
1693  xmlFree(token);
1694  token = NULL;
1695  SKIP_BLANKS;
1696  token = xsltScanNCName(ctxt);
1697  goto parse_node_test;
1698  }
1699  } else {
1700  URI = xsltGetQNameURI(ctxt->elem, &token);
1701  if (token == NULL) {
1702  ctxt->error = 1;
1703  goto error;
1704  }
1705  if (URI != NULL)
1706  URL = xmlStrdup(URI);
1707  if (axis == AXIS_ATTRIBUTE) {
1708  PUSH(XSLT_OP_ATTR, token, URL, novar);
1709  token = NULL;
1710  URL = NULL;
1711  }
1712  else {
1713  PUSH(XSLT_OP_ELEM, token, URL, novar);
1714  token = NULL;
1715  URL = NULL;
1716  }
1717  }
1718 parse_predicate:
1719  SKIP_BLANKS;
1720  level = 0;
1721  while (CUR == '[') {
1722  const xmlChar *q;
1723  xmlChar *ret = NULL;
1724 
1725  level++;
1726  NEXT;
1727  q = CUR_PTR;
1728  while (CUR != 0) {
1729  /* Skip over nested predicates */
1730  if (CUR == '[')
1731  level++;
1732  else if (CUR == ']') {
1733  level--;
1734  if (level == 0)
1735  break;
1736  } else if (CUR == '"') {
1737  NEXT;
1738  while ((CUR != 0) && (CUR != '"'))
1739  NEXT;
1740  } else if (CUR == '\'') {
1741  NEXT;
1742  while ((CUR != 0) && (CUR != '\''))
1743  NEXT;
1744  }
1745  NEXT;
1746  }
1747  if (CUR == 0) {
1749  "xsltCompileStepPattern : ']' expected\n");
1750  ctxt->error = 1;
1751  return;
1752  }
1753  ret = xmlStrndup(q, CUR_PTR - q);
1754  PUSH(XSLT_OP_PREDICATE, ret, NULL, novar);
1755  ret = NULL;
1756  /* push the predicate lower than local test */
1757  SWAP();
1758  NEXT;
1759  SKIP_BLANKS;
1760  }
1761  return;
1762 error:
1763  if (token != NULL)
1764  xmlFree(token);
1765  if (name != NULL)
1766  xmlFree(name);
1767 }
1768 
1782 static void
1784  xsltCompileStepPattern(ctxt, token, novar);
1785  if (ctxt->error)
1786  goto error;
1787  SKIP_BLANKS;
1788  while ((CUR != 0) && (CUR != '|')) {
1789  if ((CUR == '/') && (NXT(1) == '/')) {
1790  PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
1791  NEXT;
1792  NEXT;
1793  SKIP_BLANKS;
1794  xsltCompileStepPattern(ctxt, NULL, novar);
1795  } else if (CUR == '/') {
1796  PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1797  NEXT;
1798  SKIP_BLANKS;
1799  xsltCompileStepPattern(ctxt, NULL, novar);
1800  } else {
1801  ctxt->error = 1;
1802  }
1803  if (ctxt->error)
1804  goto error;
1805  SKIP_BLANKS;
1806  }
1807 error:
1808  return;
1809 }
1810 
1823 static void
1825  SKIP_BLANKS;
1826  if ((CUR == '/') && (NXT(1) == '/')) {
1827  /*
1828  * since we reverse the query
1829  * a leading // can be safely ignored
1830  */
1831  NEXT;
1832  NEXT;
1833  ctxt->comp->priority = 0.5; /* '//' means not 0 priority */
1834  xsltCompileRelativePathPattern(ctxt, NULL, novar);
1835  } else if (CUR == '/') {
1836  /*
1837  * We need to find root as the parent
1838  */
1839  NEXT;
1840  SKIP_BLANKS;
1841  PUSH(XSLT_OP_ROOT, NULL, NULL, novar);
1842  if ((CUR != 0) && (CUR != '|')) {
1843  PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1844  xsltCompileRelativePathPattern(ctxt, NULL, novar);
1845  }
1846  } else if (CUR == '*') {
1847  xsltCompileRelativePathPattern(ctxt, NULL, novar);
1848  } else if (CUR == '@') {
1849  xsltCompileRelativePathPattern(ctxt, NULL, novar);
1850  } else {
1851  xmlChar *name;
1852  name = xsltScanNCName(ctxt);
1853  if (name == NULL) {
1855  "xsltCompileLocationPathPattern : Name expected\n");
1856  ctxt->error = 1;
1857  return;
1858  }
1859  SKIP_BLANKS;
1860  if ((CUR == '(') && !xmlXPathIsNodeType(name)) {
1861  xsltCompileIdKeyPattern(ctxt, name, 1, novar, 0);
1862  xmlFree(name);
1863  name = NULL;
1864  if (ctxt->error)
1865  return;
1866  if ((CUR == '/') && (NXT(1) == '/')) {
1867  PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
1868  NEXT;
1869  NEXT;
1870  SKIP_BLANKS;
1871  xsltCompileRelativePathPattern(ctxt, NULL, novar);
1872  } else if (CUR == '/') {
1873  PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
1874  NEXT;
1875  SKIP_BLANKS;
1876  xsltCompileRelativePathPattern(ctxt, NULL, novar);
1877  }
1878  return;
1879  }
1880  xsltCompileRelativePathPattern(ctxt, name, novar);
1881  }
1882 error:
1883  return;
1884 }
1885 
1903 static xsltCompMatchPtr
1906  xsltTransformContextPtr runtime, int novar) {
1907  xsltParserContextPtr ctxt = NULL;
1908  xsltCompMatchPtr element, first = NULL, previous = NULL;
1909  int current, start, end, level, j;
1910 
1911  if (pattern == NULL) {
1913  "xsltCompilePattern : NULL pattern\n");
1914  return(NULL);
1915  }
1916 
1917  ctxt = xsltNewParserContext(style, runtime);
1918  if (ctxt == NULL)
1919  return(NULL);
1920  ctxt->doc = doc;
1921  ctxt->elem = node;
1922  current = end = 0;
1923  while (pattern[current] != 0) {
1924  start = current;
1925  while (IS_BLANK_CH(pattern[current]))
1926  current++;
1927  end = current;
1928  level = 0;
1929  while ((pattern[end] != 0) && ((pattern[end] != '|') || (level != 0))) {
1930  if (pattern[end] == '[')
1931  level++;
1932  else if (pattern[end] == ']')
1933  level--;
1934  else if (pattern[end] == '\'') {
1935  end++;
1936  while ((pattern[end] != 0) && (pattern[end] != '\''))
1937  end++;
1938  } else if (pattern[end] == '"') {
1939  end++;
1940  while ((pattern[end] != 0) && (pattern[end] != '"'))
1941  end++;
1942  }
1943  if (pattern[end] == 0)
1944  break;
1945  end++;
1946  }
1947  if (current == end) {
1949  "xsltCompilePattern : NULL pattern\n");
1950  goto error;
1951  }
1953  if (element == NULL) {
1954  goto error;
1955  }
1956  if (first == NULL)
1957  first = element;
1958  else if (previous != NULL)
1959  previous->next = element;
1960  previous = element;
1961 
1962  ctxt->comp = element;
1963  ctxt->base = xmlStrndup(&pattern[start], end - start);
1964  if (ctxt->base == NULL)
1965  goto error;
1966  ctxt->cur = &(ctxt->base)[current - start];
1967  element->pattern = ctxt->base;
1968  element->node = node;
1969  element->nsList = xmlGetNsList(doc, node);
1970  j = 0;
1971  if (element->nsList != NULL) {
1972  while (element->nsList[j] != NULL)
1973  j++;
1974  }
1975  element->nsNr = j;
1976 
1977 
1978 #ifdef WITH_XSLT_DEBUG_PATTERN
1980  "xsltCompilePattern : parsing '%s'\n",
1981  element->pattern);
1982 #endif
1983  /*
1984  Preset default priority to be zero.
1985  This may be changed by xsltCompileLocationPathPattern.
1986  */
1987  element->priority = 0;
1988  xsltCompileLocationPathPattern(ctxt, novar);
1989  if (ctxt->error) {
1991  "xsltCompilePattern : failed to compile '%s'\n",
1992  element->pattern);
1993  if (style != NULL) style->errors++;
1994  goto error;
1995  }
1996 
1997  /*
1998  * Reverse for faster interpretation.
1999  */
2001 
2002  /*
2003  * Set-up the priority
2004  */
2005  if (element->priority == 0) { /* if not yet determined */
2006  if (((element->steps[0].op == XSLT_OP_ELEM) ||
2007  (element->steps[0].op == XSLT_OP_ATTR) ||
2008  (element->steps[0].op == XSLT_OP_PI)) &&
2009  (element->steps[0].value != NULL) &&
2010  (element->steps[1].op == XSLT_OP_END)) {
2011  ; /* previously preset */
2012  } else if ((element->steps[0].op == XSLT_OP_ATTR) &&
2013  (element->steps[0].value2 != NULL) &&
2014  (element->steps[1].op == XSLT_OP_END)) {
2015  element->priority = -0.25;
2016  } else if ((element->steps[0].op == XSLT_OP_NS) &&
2017  (element->steps[0].value != NULL) &&
2018  (element->steps[1].op == XSLT_OP_END)) {
2019  element->priority = -0.25;
2020  } else if ((element->steps[0].op == XSLT_OP_ATTR) &&
2021  (element->steps[0].value == NULL) &&
2022  (element->steps[0].value2 == NULL) &&
2023  (element->steps[1].op == XSLT_OP_END)) {
2024  element->priority = -0.5;
2025  } else if (((element->steps[0].op == XSLT_OP_PI) ||
2026  (element->steps[0].op == XSLT_OP_TEXT) ||
2027  (element->steps[0].op == XSLT_OP_ALL) ||
2028  (element->steps[0].op == XSLT_OP_NODE) ||
2029  (element->steps[0].op == XSLT_OP_COMMENT)) &&
2030  (element->steps[1].op == XSLT_OP_END)) {
2031  element->priority = -0.5;
2032  } else {
2033  element->priority = 0.5;
2034  }
2035  }
2036 #ifdef WITH_XSLT_DEBUG_PATTERN
2038  "xsltCompilePattern : parsed %s, default priority %f\n",
2039  element->pattern, element->priority);
2040 #endif
2041  if (pattern[end] == '|')
2042  end++;
2043  current = end;
2044  }
2045  if (end == 0) {
2047  "xsltCompilePattern : NULL pattern\n");
2048  if (style != NULL) style->errors++;
2049  goto error;
2050  }
2051 
2052  xsltFreeParserContext(ctxt);
2053  return(first);
2054 
2055 error:
2056  if (ctxt != NULL)
2057  xsltFreeParserContext(ctxt);
2058  if (first != NULL)
2060  return(NULL);
2061 }
2062 
2082  xsltTransformContextPtr runtime) {
2083  return (xsltCompilePatternInternal(pattern, doc, node, style, runtime, 0));
2084 }
2085 
2086 /************************************************************************
2087  * *
2088  * Module interfaces *
2089  * *
2090  ************************************************************************/
2091 
2103 int
2105  const xmlChar *mode, const xmlChar *modeURI) {
2106  xsltCompMatchPtr pat, list, next;
2107  /*
2108  * 'top' will point to style->xxxMatch ptr - declaring as 'void'
2109  * avoids gcc 'type-punned pointer' warning.
2110  */
2111  void **top = NULL;
2112  const xmlChar *name = NULL;
2113  float priority; /* the priority */
2114 
2115  if ((style == NULL) || (cur == NULL))
2116  return(-1);
2117 
2118  /* Register named template */
2119  if (cur->name != NULL) {
2120  if (style->namedTemplates == NULL) {
2121  style->namedTemplates = xmlHashCreate(10);
2122  if (style->namedTemplates == NULL)
2123  return(-1);
2124  }
2125  else {
2126  void *dup = xmlHashLookup2(style->namedTemplates, cur->name,
2127  cur->nameURI);
2128  if (dup != NULL) {
2130  "xsl:template: error duplicate name '%s'\n",
2131  cur->name);
2132  style->errors++;
2133  return(-1);
2134  }
2135  }
2136 
2137  xmlHashAddEntry2(style->namedTemplates, cur->name, cur->nameURI, cur);
2138  }
2139 
2140  if (cur->match == NULL) {
2141  if (cur->name == NULL) {
2143  "xsl:template: need to specify match or name attribute\n");
2144  style->errors++;
2145  return(-1);
2146  }
2147  return(0);
2148  }
2149 
2150  priority = cur->priority;
2151  pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem,
2152  style, NULL, 1);
2153  if (pat == NULL)
2154  return(-1);
2155  while (pat) {
2156  next = pat->next;
2157  pat->next = NULL;
2158  name = NULL;
2159 
2160  pat->template = cur;
2161  if (mode != NULL)
2162  pat->mode = xmlDictLookup(style->dict, mode, -1);
2163  if (modeURI != NULL)
2164  pat->modeURI = xmlDictLookup(style->dict, modeURI, -1);
2166  pat->priority = priority;
2167 
2168  /*
2169  * insert it in the hash table list corresponding to its lookup name
2170  */
2171  switch (pat->steps[0].op) {
2172  case XSLT_OP_ATTR:
2173  if (pat->steps[0].value != NULL)
2174  name = pat->steps[0].value;
2175  else
2176  top = &(style->attrMatch);
2177  break;
2178  case XSLT_OP_PARENT:
2179  case XSLT_OP_ANCESTOR:
2180  top = &(style->elemMatch);
2181  break;
2182  case XSLT_OP_ROOT:
2183  top = &(style->rootMatch);
2184  break;
2185  case XSLT_OP_KEY:
2186  top = &(style->keyMatch);
2187  break;
2188  case XSLT_OP_ID:
2189  /* TODO optimize ID !!! */
2190  case XSLT_OP_NS:
2191  case XSLT_OP_ALL:
2192  top = &(style->elemMatch);
2193  break;
2194  case XSLT_OP_END:
2195  case XSLT_OP_PREDICATE:
2197  "xsltAddTemplate: invalid compiled pattern\n");
2198  xsltFreeCompMatch(pat);
2199  return(-1);
2200  /*
2201  * TODO: some flags at the top level about type based patterns
2202  * would be faster than inclusion in the hash table.
2203  */
2204  case XSLT_OP_PI:
2205  if (pat->steps[0].value != NULL)
2206  name = pat->steps[0].value;
2207  else
2208  top = &(style->piMatch);
2209  break;
2210  case XSLT_OP_COMMENT:
2211  top = &(style->commentMatch);
2212  break;
2213  case XSLT_OP_TEXT:
2214  top = &(style->textMatch);
2215  break;
2216  case XSLT_OP_ELEM:
2217  case XSLT_OP_NODE:
2218  if (pat->steps[0].value != NULL)
2219  name = pat->steps[0].value;
2220  else
2221  top = &(style->elemMatch);
2222  break;
2223  }
2224  if (name != NULL) {
2225  if (style->templatesHash == NULL) {
2226  style->templatesHash = xmlHashCreate(1024);
2227  if (style->templatesHash == NULL) {
2228  xsltFreeCompMatch(pat);
2229  return(-1);
2230  }
2231  xmlHashAddEntry3(style->templatesHash, name, mode, modeURI, pat);
2232  } else {
2233  list = (xsltCompMatchPtr) xmlHashLookup3(style->templatesHash,
2234  name, mode, modeURI);
2235  if (list == NULL) {
2236  xmlHashAddEntry3(style->templatesHash, name,
2237  mode, modeURI, pat);
2238  } else {
2239  /*
2240  * Note '<=' since one must choose among the matching
2241  * template rules that are left, the one that occurs
2242  * last in the stylesheet
2243  */
2244  if (list->priority <= pat->priority) {
2245  pat->next = list;
2246  xmlHashUpdateEntry3(style->templatesHash, name,
2247  mode, modeURI, pat, NULL);
2248  } else {
2249  while (list->next != NULL) {
2250  if (list->next->priority <= pat->priority)
2251  break;
2252  list = list->next;
2253  }
2254  pat->next = list->next;
2255  list->next = pat;
2256  }
2257  }
2258  }
2259  } else if (top != NULL) {
2260  list = *top;
2261  if (list == NULL) {
2262  *top = pat;
2263  pat->next = NULL;
2264  } else if (list->priority <= pat->priority) {
2265  pat->next = list;
2266  *top = pat;
2267  } else {
2268  while (list->next != NULL) {
2269  if (list->next->priority <= pat->priority)
2270  break;
2271  list = list->next;
2272  }
2273  pat->next = list->next;
2274  list->next = pat;
2275  }
2276  } else {
2278  "xsltAddTemplate: invalid compiled pattern\n");
2279  xsltFreeCompMatch(pat);
2280  return(-1);
2281  }
2282 #ifdef WITH_XSLT_DEBUG_PATTERN
2283  if (mode)
2285  "added pattern : '%s' mode '%s' priority %f\n",
2286  pat->pattern, pat->mode, pat->priority);
2287  else
2289  "added pattern : '%s' priority %f\n",
2290  pat->pattern, pat->priority);
2291 #endif
2292 
2293  pat = next;
2294  }
2295  return(0);
2296 }
2297 
2298 static int
2300 {
2301  if ((ctxt == NULL) || (contextNode == NULL)) {
2302  xsltTransformError(ctxt, NULL, ctxt->inst,
2303  "Internal error in xsltComputeAllKeys(): "
2304  "Bad arguments.\n");
2305  return(-1);
2306  }
2307 
2308  if (ctxt->document == NULL) {
2309  /*
2310  * The document info will only be NULL if we have a RTF.
2311  */
2312  if (contextNode->doc->_private != NULL)
2313  goto doc_info_mismatch;
2314  /*
2315  * On-demand creation of the document info (needed for keys).
2316  */
2317  ctxt->document = xsltNewDocument(ctxt, contextNode->doc);
2318  if (ctxt->document == NULL)
2319  return(-1);
2320  }
2321  return xsltInitAllDocKeys(ctxt);
2322 
2323 doc_info_mismatch:
2324  xsltTransformError(ctxt, NULL, ctxt->inst,
2325  "Internal error in xsltComputeAllKeys(): "
2326  "The context's document info doesn't match the "
2327  "document info of the current result tree.\n");
2328  ctxt->state = XSLT_STATE_STOPPED;
2329  return(-1);
2330 }
2331 
2346 {
2347  xsltStylesheetPtr curstyle;
2349  const xmlChar *name = NULL;
2351  float priority;
2352  int keyed = 0;
2353 
2354  if ((ctxt == NULL) || (node == NULL))
2355  return(NULL);
2356 
2357  if (style == NULL) {
2358  curstyle = ctxt->style;
2359  } else {
2360  curstyle = xsltNextImport(style);
2361  }
2362 
2363  while ((curstyle != NULL) && (curstyle != style)) {
2365  /* TODO : handle IDs/keys here ! */
2366  if (curstyle->templatesHash != NULL) {
2367  /*
2368  * Use the top name as selector
2369  */
2370  switch (node->type) {
2371  case XML_ELEMENT_NODE:
2372  if (node->name[0] == ' ')
2373  break;
2374  /* Intentional fall-through */
2375  case XML_ATTRIBUTE_NODE:
2376  case XML_PI_NODE:
2377  name = node->name;
2378  break;
2379  case XML_DOCUMENT_NODE:
2381  case XML_TEXT_NODE:
2383  case XML_COMMENT_NODE:
2384  case XML_ENTITY_REF_NODE:
2385  case XML_ENTITY_NODE:
2388  case XML_NOTATION_NODE:
2389  case XML_DTD_NODE:
2390  case XML_ELEMENT_DECL:
2391  case XML_ATTRIBUTE_DECL:
2392  case XML_ENTITY_DECL:
2393  case XML_NAMESPACE_DECL:
2394  case XML_XINCLUDE_START:
2395  case XML_XINCLUDE_END:
2396  break;
2397  default:
2398  return(NULL);
2399 
2400  }
2401  }
2402  if (name != NULL) {
2403  /*
2404  * find the list of applicable expressions based on the name
2405  */
2407  name, ctxt->mode, ctxt->modeURI);
2408  } else
2409  list = NULL;
2410  while (list != NULL) {
2411  if (xsltTestCompMatch(ctxt, list, node,
2412  ctxt->mode, ctxt->modeURI) == 1) {
2413  ret = list->template;
2414  priority = list->priority;
2415  break;
2416  }
2417  list = list->next;
2418  }
2419  list = NULL;
2420 
2421  /*
2422  * find alternate generic matches
2423  */
2424  switch (node->type) {
2425  case XML_ELEMENT_NODE:
2426  if (node->name[0] == ' ')
2427  list = curstyle->rootMatch;
2428  else
2429  list = curstyle->elemMatch;
2430  if (node->psvi != NULL) keyed = 1;
2431  break;
2432  case XML_ATTRIBUTE_NODE: {
2433  xmlAttrPtr attr;
2434 
2435  list = curstyle->attrMatch;
2436  attr = (xmlAttrPtr) node;
2437  if (attr->psvi != NULL) keyed = 1;
2438  break;
2439  }
2440  case XML_PI_NODE:
2441  list = curstyle->piMatch;
2442  if (node->psvi != NULL) keyed = 1;
2443  break;
2444  case XML_DOCUMENT_NODE:
2445  case XML_HTML_DOCUMENT_NODE: {
2446  xmlDocPtr doc;
2447 
2448  list = curstyle->rootMatch;
2449  doc = (xmlDocPtr) node;
2450  if (doc->psvi != NULL) keyed = 1;
2451  break;
2452  }
2453  case XML_TEXT_NODE:
2455  list = curstyle->textMatch;
2456  if (node->psvi != NULL) keyed = 1;
2457  break;
2458  case XML_COMMENT_NODE:
2459  list = curstyle->commentMatch;
2460  if (node->psvi != NULL) keyed = 1;
2461  break;
2462  case XML_ENTITY_REF_NODE:
2463  case XML_ENTITY_NODE:
2466  case XML_NOTATION_NODE:
2467  case XML_DTD_NODE:
2468  case XML_ELEMENT_DECL:
2469  case XML_ATTRIBUTE_DECL:
2470  case XML_ENTITY_DECL:
2471  case XML_NAMESPACE_DECL:
2472  case XML_XINCLUDE_START:
2473  case XML_XINCLUDE_END:
2474  break;
2475  default:
2476  break;
2477  }
2478  while ((list != NULL) &&
2479  ((ret == NULL) || (list->priority > priority))) {
2480  if (xsltTestCompMatch(ctxt, list, node,
2481  ctxt->mode, ctxt->modeURI) == 1) {
2482  ret = list->template;
2483  priority = list->priority;
2484  break;
2485  }
2486  list = list->next;
2487  }
2488  /*
2489  * Some of the tests for elements can also apply to documents
2490  */
2491  if ((node->type == XML_DOCUMENT_NODE) ||
2492  (node->type == XML_HTML_DOCUMENT_NODE) ||
2493  (node->type == XML_TEXT_NODE)) {
2494  list = curstyle->elemMatch;
2495  while ((list != NULL) &&
2496  ((ret == NULL) || (list->priority > priority))) {
2497  if (xsltTestCompMatch(ctxt, list, node,
2498  ctxt->mode, ctxt->modeURI) == 1) {
2499  ret = list->template;
2500  priority = list->priority;
2501  break;
2502  }
2503  list = list->next;
2504  }
2505  } else if ((node->type == XML_PI_NODE) ||
2506  (node->type == XML_COMMENT_NODE)) {
2507  list = curstyle->elemMatch;
2508  while ((list != NULL) &&
2509  ((ret == NULL) || (list->priority > priority))) {
2510  if (xsltTestCompMatch(ctxt, list, node,
2511  ctxt->mode, ctxt->modeURI) == 1) {
2512  ret = list->template;
2513  priority = list->priority;
2514  break;
2515  }
2516  list = list->next;
2517  }
2518  }
2519 
2520 keyed_match:
2521  if (keyed) {
2522  list = curstyle->keyMatch;
2523  while ((list != NULL) &&
2524  ((ret == NULL) || (list->priority > priority))) {
2525  if (xsltTestCompMatch(ctxt, list, node,
2526  ctxt->mode, ctxt->modeURI) == 1) {
2527  ret = list->template;
2528  priority = list->priority;
2529  break;
2530  }
2531  list = list->next;
2532  }
2533  }
2534  else if (ctxt->hasTemplKeyPatterns &&
2535  ((ctxt->document == NULL) ||
2536  (ctxt->document->nbKeysComputed < ctxt->nbKeys)))
2537  {
2538  /*
2539  * Compute all remaining keys for this document.
2540  *
2541  * REVISIT TODO: I think this could be further optimized.
2542  */
2543  if (xsltComputeAllKeys(ctxt, node) == -1)
2544  goto error;
2545 
2546  switch (node->type) {
2547  case XML_ELEMENT_NODE:
2548  if (node->psvi != NULL) keyed = 1;
2549  break;
2550  case XML_ATTRIBUTE_NODE:
2551  if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1;
2552  break;
2553  case XML_TEXT_NODE:
2555  case XML_COMMENT_NODE:
2556  case XML_PI_NODE:
2557  if (node->psvi != NULL) keyed = 1;
2558  break;
2559  case XML_DOCUMENT_NODE:
2561  if (((xmlDocPtr) node)->psvi != NULL) keyed = 1;
2562  break;
2563  default:
2564  break;
2565  }
2566  if (keyed)
2567  goto keyed_match;
2568  }
2569  if (ret != NULL)
2570  return(ret);
2571 
2572  /*
2573  * Cycle on next curstylesheet import.
2574  */
2575  curstyle = xsltNextImport(curstyle);
2576  }
2577 
2578 error:
2579  return(NULL);
2580 }
2581 
2589 void
2591 }
2592 
2599 void
2601  if (style->templatesHash != NULL)
2602  xmlHashFree((xmlHashTablePtr) style->templatesHash,
2604  if (style->rootMatch != NULL)
2605  xsltFreeCompMatchList(style->rootMatch);
2606  if (style->keyMatch != NULL)
2607  xsltFreeCompMatchList(style->keyMatch);
2608  if (style->elemMatch != NULL)
2609  xsltFreeCompMatchList(style->elemMatch);
2610  if (style->attrMatch != NULL)
2611  xsltFreeCompMatchList(style->attrMatch);
2612  if (style->parentMatch != NULL)
2613  xsltFreeCompMatchList(style->parentMatch);
2614  if (style->textMatch != NULL)
2615  xsltFreeCompMatchList(style->textMatch);
2616  if (style->piMatch != NULL)
2617  xsltFreeCompMatchList(style->piMatch);
2618  if (style->commentMatch != NULL)
2619  xsltFreeCompMatchList(style->commentMatch);
2620  if (style->namedTemplates != NULL)
2621  xmlHashFree(style->namedTemplates, NULL);
2622 }
2623 
XMLPUBFUN int XMLCALL xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata)
Definition: hash.c:536
static int xsltPatPushState(xsltTransformContextPtr ctxt, xsltStepStates *states, int step, xmlNodePtr node)
Definition: pattern.c:468
xsltOp
Definition: pattern.c:27
int indexExtra
Definition: pattern.c:77
GLint level
Definition: gl.h:1546
#define IS_EXTENDER(c)
xmlChar * value2
Definition: pattern.c:70
void xsltFreeCompMatchList(xsltCompMatchPtr comp)
Definition: pattern.c:192
const xmlChar * name
xsltOp op
Definition: pattern.c:68
LOCAL int expr(arg_t *ap, int *altp)
Definition: match.c:512
#define NXT(val)
Definition: pattern.c:1263
struct _xmlNode * prev
Definition: tree.h:497
#define error(str)
Definition: mkdosfs.c:1605
const xmlChar * name
Definition: tree.h:492
xmlNodePtr elem
Definition: pattern.c:107
xsltStepStates * xsltStepStatesPtr
Definition: pattern.c:58
Definition: match.c:28
Definition: tree.h:389
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:41
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:251
XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata)
Definition: hash.c:411
int xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, const xmlChar *mode, const xmlChar *modeURI)
Definition: pattern.c:2104
void xsltNormalizeCompSteps(void *payload, void *data, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: pattern.c:217
xsltStepState * xsltStepStatePtr
Definition: pattern.c:51
const GLint * first
Definition: glext.h:5794
#define XSLT_PAT_NO_PRIORITY
static int xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp, xsltOp op, xmlChar *value, xmlChar *value2, int novar)
Definition: pattern.c:282
const xmlChar * mode
Definition: pattern.c:85
static xmlChar * xsltScanLiteral(xsltParserContextPtr ctxt)
Definition: pattern.c:1300
GLdouble GLdouble t
Definition: gl.h:2047
xmlNodePtr elem
int xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, xmlNsPtr *nsList, int nsNr)
Definition: templates.c:39
static void xsltFreeCompMatch(xsltCompMatchPtr comp)
Definition: pattern.c:159
GLuint GLuint end
Definition: gl.h:1545
#define CUR
Definition: pattern.c:1261
xmlDocPtr doc
Definition: pattern.c:106
static int xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr node, xmlNsPtr *nsList, int nsNr)
Definition: pattern.c:516
XMLPUBFUN int XMLCALL xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len)
xmlNodePtr node
Definition: pattern.c:88
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:481
Definition: query.h:86
XMLPUBFUN xmlAttrPtr XMLCALL xmlGetID(xmlDocPtr doc, const xmlChar *ID)
Definition: valid.c:2846
const xmlChar * nameURI
static void xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name, int aid, int novar, xsltAxis axis)
Definition: pattern.c:1399
struct _xmlDoc * doc
Definition: tree.h:498
xmlXPathCompExprPtr comp
Definition: pattern.c:72
xsltCompMatchPtr comp
Definition: pattern.c:109
static int xsltTestPredicateMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr node, xsltStepOpPtr step, xsltStepOpPtr sel)
Definition: pattern.c:626
struct _xsltParserContext xsltParserContext
Definition: pattern.c:99
#define PUSH(op, val, val2, novar)
Definition: pattern.c:1273
struct node node
#define IS_COMBINING(c)
void xsltFreeTemplateHashes(xsltStylesheetPtr style)
Definition: pattern.c:2600
xsltTemplatePtr xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStylesheetPtr style)
Definition: pattern.c:2344
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
static void xmlXPathFreeObjectWrapper(void *obj)
Definition: pattern.c:498
static xmlChar * xsltScanNCName(xsltParserContextPtr ctxt)
Definition: pattern.c:1356
xsltParserContext * xsltParserContextPtr
Definition: pattern.c:100
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:327
#define XSLT_RUNTIME_EXTRA_LST(ctxt, nr)
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:502
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
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
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:526
#define IS_BLANK_CH(c)
xsltTransformState state
#define IS_CHAR(c)
static PVOID ptr
Definition: dispmode.c:27
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
static DWORD DWORD DWORD DWORD * steps
Definition: cursoricon.c:1638
smooth NULL
Definition: ftsmooth.c:416
xmlChar * value
Definition: pattern.c:69
struct _xsltCompMatch * next
Definition: pattern.c:82
static void xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar)
Definition: pattern.c:1580
xmlNode * xmlNodePtr
Definition: tree.h:488
xsltDocumentPtr document
struct match match
Definition: match.c:33
xmlXPathContextPtr xpathCtxt
static int xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, xmlNodePtr matchNode, const xmlChar *mode, const xmlChar *modeURI)
Definition: pattern.c:900
XMLPUBFUN void *XMLCALL xmlHashLookup3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3)
Definition: hash.c:774
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:249
const xmlChar * modeURI
Definition: pattern.c:86
GLuint GLfloat * val
Definition: glext.h:7180
struct _xmlNode * parent
Definition: tree.h:495
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
void restart(int argc, const char *argv[])
Definition: cmds.c:2115
const xmlChar * modeURI
int xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltCompMatchPtr comp)
Definition: pattern.c:1212
void * psvi
Definition: tree.h:581
void * xsltGenericDebugContext
Definition: xsltutils.c:549
xmlNodeSetPtr xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI, const xmlChar *value)
Definition: keys.c:417
r parent
Definition: btrfs.c:2944
static void xsltCompileRelativePathPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar)
Definition: pattern.c:1783
static xsltCompMatchPtr xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node, xsltStylesheetPtr style, xsltTransformContextPtr runtime, int novar)
Definition: pattern.c:1904
static void xsltSwapTopCompMatch(xsltCompMatchPtr comp)
Definition: pattern.c:351
struct list * next
Definition: list.h:38
UINT op
Definition: effect.c:224
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
XMLPUBFUN const xmlChar *XMLCALL xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:865
Definition: cookie.c:201
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
#define CUR_PTR
Definition: pattern.c:1264
float priority
Definition: pattern.c:83
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static void xsltFreeParserContext(xsltParserContextPtr ctxt)
Definition: pattern.c:262
const xmlChar * pattern
Definition: pattern.c:84
xsltCompMatch * xsltCompMatchPtr
Definition: pattern.h:29
GLbitfield flags
Definition: glext.h:7161
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:181
void * xsltGenericErrorContext
Definition: xsltutils.c:503
static xsltParserContextPtr xsltNewParserContext(xsltStylesheetPtr style, xsltTransformContextPtr ctxt)
Definition: pattern.c:240
Definition: tree.h:489
XMLPUBFUN int XMLCALL xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata, xmlHashDeallocator f)
Definition: hash.c:652
int ret
xmlAttr * xmlAttrPtr
Definition: tree.h:433
xmlNodePtr node
Definition: pattern.c:54
#define ATTRIBUTE_UNUSED
Definition: win32config.h:132
#define XSLT_RUNTIME_EXTRA(ctxt, nr, typ)
__u8 attr
Definition: mkdosfs.c:359
Definition: mxnamespace.c:44
xsltStepOpPtr steps
Definition: pattern.c:96
unsigned char xmlChar
Definition: xmlstring.h:28
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
#define LIBXML_DOCB_ENABLED
Definition: xmlversion.h:238
xsltStepOp * xsltStepOpPtr
Definition: pattern.c:66
GLenum mode
Definition: glext.h:6217
xsltTransformContextPtr ctxt
Definition: pattern.c:103
xsltAxis
Definition: pattern.c:45
GLsizei const GLfloat * value
Definition: glext.h:6069
#define XSLT_RUNTIME_EXTRA_FREE(ctxt, nr)
xmlElementType type
Definition: tree.h:491
#define SWAP()
Definition: pattern.c:1276
int xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
Definition: xslt.c:825
int lenExtra
Definition: pattern.c:78
#define IS_LETTER(c)
xmlDoc * xmlDocPtr
Definition: tree.h:550
const xmlChar * base
Definition: pattern.c:105
const xmlChar * cur
Definition: pattern.c:104
xsltStylesheetPtr style
static unsigned __int64 next
Definition: rand_nt.c:6
static int xsltComputeAllKeys(xsltTransformContextPtr ctxt, xmlNodePtr contextNode)
Definition: pattern.c:2299
int xsltInitAllDocKeys(xsltTransformContextPtr ctxt)
Definition: keys.c:535
xsltStylesheetPtr style
Definition: pattern.c:102
#define XSLT_IS_RES_TREE_FRAG(n)
Definition: xsltInternals.h:56
const xmlChar * mode
xmlChar * value3
Definition: pattern.c:71
struct _xmlNode * next
Definition: tree.h:496
GLuint start
Definition: gl.h:1545
static void xsltFreeCompMatchListEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: pattern.c:203
int xsltAllocateExtra(xsltStylesheetPtr style)
Definition: xslt.c:809
#define list
Definition: rosglue.h:35
xsltCompMatchPtr xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node, xsltStylesheetPtr style, xsltTransformContextPtr runtime)
Definition: pattern.c:2080
void xsltCompMatchClearCache(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp)
Definition: pattern.c:1235
_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:1357
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:247
Definition: tree.h:551
xmlXPathCompExprPtr xsltXPathCompileFlags(xsltStylesheetPtr style, const xmlChar *str, int flags)
Definition: xsltutils.c:2276
#define IS_DIGIT(c)
void xsltCleanupTemplates(xsltStylesheetPtr style ATTRIBUTE_UNUSED)
Definition: pattern.c:2590
Definition: tree.h:434
Definition: name.c:38
_Check_return_ _CRTIMP int __cdecl dup(_In_ int _FileHandle)
xmlNsPtr * nsList
Definition: pattern.c:94
GLenum GLuint id
Definition: glext.h:5579
FILE * stderr
static int priority
Definition: timer.c:163
static void xsltCompileLocationPathPattern(xsltParserContextPtr ctxt, int novar)
Definition: pattern.c:1824
static void xsltReverseCompMatch(xsltParserContextPtr ctxt, xsltCompMatchPtr comp)
Definition: pattern.c:396
xmlNs * ns
Definition: tree.h:501
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
xsltTemplatePtr template
Definition: pattern.c:87
xmlChar * match
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:157
void exit(int exitcode)
Definition: _exit.c:33
#define NEXT
Definition: pattern.c:1270
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
xsltStepStatePtr states
Definition: pattern.c:62
Arabic default style
Definition: afstyles.h:93
const xmlChar * href
Definition: tree.h:392
#define memset(x, y, z)
Definition: compat.h:39
int previousExtra
Definition: pattern.c:76
GLenum query
Definition: glext.h:7781
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:66
#define SKIP_BLANKS
Definition: pattern.c:1266
xsltDocumentPtr xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc)
Definition: documents.c:127
struct task_struct * current
Definition: linux.c:32
static xsltCompMatchPtr xsltNewCompMatch(void)
Definition: pattern.c:126
GLubyte * pattern
Definition: glext.h:7787
Definition: dlist.c:348
GLuint const GLchar * name
Definition: glext.h:6031
const xmlChar * xsltGetQNameURI(xmlNodePtr node, xmlChar **name)
Definition: xsltutils.c:753