ReactOS 0.4.16-dev-329-g9223134
variables.c
Go to the documentation of this file.
1/*
2 * variables.c: Implementation of the variable storage 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#include "precomp.h"
13
14#ifdef WITH_XSLT_DEBUG
15 #define WITH_XSLT_DEBUG_VARIABLE
16#endif
17
18#ifdef XSLT_REFACTORED
19const xmlChar *xsltDocFragFake = (const xmlChar *) " fake node libxslt";
20#endif
21
23 (const xmlChar *) " var/param being computed";
24
25#define XSLT_VAR_GLOBAL (1<<0)
26#define XSLT_VAR_IN_SELECT (1<<1)
27#define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable)
28
29/************************************************************************
30 * *
31 * Result Value Tree (Result Tree Fragment) interfaces *
32 * *
33 ************************************************************************/
45{
47
48 /*
49 * Question: Why is this function public?
50 * Answer: It is called by the EXSLT module.
51 */
52 if (ctxt == NULL)
53 return(NULL);
54
55 /*
56 * Reuse a RTF from the cache if available.
57 */
58 if (ctxt->cache->RVT) {
59 container = ctxt->cache->RVT;
60 ctxt->cache->RVT = (xmlDocPtr) container->next;
61 /* clear the internal pointers */
62 container->next = NULL;
63 container->prev = NULL;
64 if (ctxt->cache->nbRVT > 0)
65 ctxt->cache->nbRVT--;
66#ifdef XSLT_DEBUG_PROFILE_CACHE
67 ctxt->cache->dbgReusedRVTs++;
68#endif
69 return(container);
70 }
71
73 if (container == NULL)
74 return(NULL);
75 container->dict = ctxt->dict;
78 container->doc = container;
79 container->parent = NULL;
80 return(container);
81}
82
98int
100{
101 if ((ctxt == NULL) || (RVT == NULL))
102 return(-1);
103
104 RVT->prev = NULL;
105 RVT->psvi = XSLT_RVT_LOCAL;
106
107 /*
108 * We'll restrict the lifetime of user-created fragments
109 * insinde an xsl:variable and xsl:param to the lifetime of the
110 * var/param itself.
111 */
112 if (ctxt->contextVariable != NULL) {
113 RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
114 XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
115 return(0);
116 }
117
118 RVT->next = (xmlNodePtr) ctxt->tmpRVT;
119 if (ctxt->tmpRVT != NULL)
120 ctxt->tmpRVT->prev = (xmlNodePtr) RVT;
121 ctxt->tmpRVT = RVT;
122 return(0);
123}
124
137int
139 xmlDocPtr RVT)
140{
141 if ((ctxt == NULL) || (RVT == NULL))
142 return(-1);
143
144 RVT->prev = NULL;
145 RVT->psvi = XSLT_RVT_LOCAL;
146
147 /*
148 * When evaluating "select" expressions of xsl:variable
149 * and xsl:param, we need to bind newly created tree fragments
150 * to the variable itself; otherwise the fragment will be
151 * freed before we leave the scope of a var.
152 */
153 if ((ctxt->contextVariable != NULL) &&
155 {
156 RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
157 XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
158 return(0);
159 }
160 /*
161 * Store the fragment in the scope of the current instruction.
162 * If not reference by a returning instruction (like EXSLT's function),
163 * then this fragment will be freed, when the instruction exits.
164 */
165 RVT->next = (xmlNodePtr) ctxt->localRVT;
166 if (ctxt->localRVT != NULL)
167 ctxt->localRVT->prev = (xmlNodePtr) RVT;
168 ctxt->localRVT = RVT;
169 return(0);
170}
171
186int
189{
191 "xsltExtensionInstructionResultFinalize is unsupported "
192 "in this release of libxslt.\n");
193 return(-1);
194}
195
212int
215 xmlXPathObjectPtr obj ATTRIBUTE_UNUSED)
216{
217 return(0);
218}
219
236int
237xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
238 int i;
240 xmlDocPtr doc;
241
242 if ((ctxt == NULL) || (obj == NULL))
243 return(-1);
244
245 /*
246 * OPTIMIZE TODO: If no local variables/params and no local tree
247 * fragments were created, then we don't need to analyse the XPath
248 * objects for tree fragments.
249 */
250
251 if ((obj->type != XPATH_NODESET) && (obj->type != XPATH_XSLT_TREE))
252 return(0);
253 if ((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0))
254 return(0);
255
256 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
257 cur = obj->nodesetval->nodeTab[i];
258 if (cur->type == XML_NAMESPACE_DECL) {
259 /*
260 * The XPath module sets the owner element of a ns-node on
261 * the ns->next field.
262 */
263 if ((((xmlNsPtr) cur)->next != NULL) &&
264 (((xmlNsPtr) cur)->next->type == XML_ELEMENT_NODE))
265 {
266 cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
267 doc = cur->doc;
268 } else {
269 xsltTransformError(ctxt, NULL, ctxt->inst,
270 "Internal error in xsltFlagRVTs(): "
271 "Cannot retrieve the doc of a namespace node.\n");
272 return(-1);
273 }
274 } else {
275 doc = cur->doc;
276 }
277 if (doc == NULL) {
278 xsltTransformError(ctxt, NULL, ctxt->inst,
279 "Internal error in xsltFlagRVTs(): "
280 "Cannot retrieve the doc of a node.\n");
281 return(-1);
282 }
283 if (doc->name && (doc->name[0] == ' ') &&
284 doc->psvi != XSLT_RVT_GLOBAL) {
285 /*
286 * This is a result tree fragment.
287 * We store ownership information in the @psvi field.
288 * TODO: How do we know if this is a doc acquired via the
289 * document() function?
290 */
291#ifdef WITH_XSLT_DEBUG_VARIABLE
293 "Flagging RVT %p: %p -> %p\n", doc, doc->psvi, val));
294#endif
295
296 if (val == XSLT_RVT_LOCAL) {
297 if (doc->psvi == XSLT_RVT_FUNC_RESULT)
298 doc->psvi = XSLT_RVT_LOCAL;
299 } else if (val == XSLT_RVT_GLOBAL) {
300 if (doc->psvi != XSLT_RVT_LOCAL) {
302 "xsltFlagRVTs: Invalid transition %p => GLOBAL\n",
303 doc->psvi);
304 doc->psvi = XSLT_RVT_GLOBAL;
305 return(-1);
306 }
307
308 /* Will be registered as persistant in xsltReleaseLocalRVTs. */
309 doc->psvi = XSLT_RVT_GLOBAL;
310 } else if (val == XSLT_RVT_FUNC_RESULT) {
311 doc->psvi = val;
312 }
313 }
314 }
315
316 return(0);
317}
318
327void
329{
330 if (RVT == NULL)
331 return;
332
333 if (ctxt && (ctxt->cache->nbRVT < 40)) {
334 /*
335 * Store the Result Tree Fragment.
336 * Free the document info.
337 */
338 if (RVT->_private != NULL) {
340 xmlFree(RVT->_private);
341 RVT->_private = NULL;
342 }
343 /*
344 * Clear the document tree.
345 */
346 if (RVT->children != NULL) {
348 RVT->children = NULL;
349 RVT->last = NULL;
350 }
351 if (RVT->ids != NULL) {
353 RVT->ids = NULL;
354 }
355
356 /*
357 * Reset the ownership information.
358 */
359 RVT->psvi = NULL;
360
361 RVT->next = (xmlNodePtr) ctxt->cache->RVT;
362 ctxt->cache->RVT = RVT;
363
364 ctxt->cache->nbRVT++;
365
366#ifdef XSLT_DEBUG_PROFILE_CACHE
367 ctxt->cache->dbgCachedRVTs++;
368#endif
369 return;
370 }
371 /*
372 * Free it.
373 */
374 if (RVT->_private != NULL) {
376 xmlFree(RVT->_private);
377 }
378 xmlFreeDoc(RVT);
379}
380
393int
395{
396 if ((ctxt == NULL) || (RVT == NULL)) return(-1);
397
398 RVT->psvi = XSLT_RVT_GLOBAL;
399 RVT->prev = NULL;
400 RVT->next = (xmlNodePtr) ctxt->persistRVT;
401 if (ctxt->persistRVT != NULL)
402 ctxt->persistRVT->prev = (xmlNodePtr) RVT;
403 ctxt->persistRVT = RVT;
404 return(0);
405}
406
415void
417{
419
420 if (ctxt == NULL)
421 return;
422 /*
423 * Local fragments.
424 */
425 cur = ctxt->localRVT;
426 while (cur != NULL) {
427 next = (xmlDocPtr) cur->next;
428 if (cur->_private != NULL) {
429 xsltFreeDocumentKeys(cur->_private);
430 xmlFree(cur->_private);
431 }
433 cur = next;
434 }
435 ctxt->localRVT = NULL;
436 /*
437 * User-created per-template fragments.
438 */
439 cur = ctxt->tmpRVT;
440 while (cur != NULL) {
441 next = (xmlDocPtr) cur->next;
442 if (cur->_private != NULL) {
443 xsltFreeDocumentKeys(cur->_private);
444 xmlFree(cur->_private);
445 }
447 cur = next;
448 }
449 ctxt->tmpRVT = NULL;
450 /*
451 * Global fragments.
452 */
453 cur = ctxt->persistRVT;
454 while (cur != NULL) {
455 next = (xmlDocPtr) cur->next;
456 if (cur->_private != NULL) {
457 xsltFreeDocumentKeys(cur->_private);
458 xmlFree(cur->_private);
459 }
461 cur = next;
462 }
463 ctxt->persistRVT = NULL;
464}
465
466/************************************************************************
467 * *
468 * Module interfaces *
469 * *
470 ************************************************************************/
471
479static xsltStackElemPtr
481{
483 /*
484 * Reuse a stack item from the cache if available.
485 */
486 if (ctxt && ctxt->cache->stackItems) {
487 ret = ctxt->cache->stackItems;
488 ctxt->cache->stackItems = ret->next;
489 ret->next = NULL;
490 ctxt->cache->nbStackItems--;
491#ifdef XSLT_DEBUG_PROFILE_CACHE
492 ctxt->cache->dbgReusedVars++;
493#endif
494 return(ret);
495 }
497 if (ret == NULL) {
499 "xsltNewStackElem : malloc failed\n");
500 return(NULL);
501 }
502 memset(ret, 0, sizeof(xsltStackElem));
503 ret->context = ctxt;
504 return(ret);
505}
506
515static xsltStackElemPtr
518
520 if (cur == NULL) {
522 "xsltCopyStackElem : malloc failed\n");
523 return(NULL);
524 }
525 memset(cur, 0, sizeof(xsltStackElem));
526 cur->context = elem->context;
527 cur->name = elem->name;
528 cur->nameURI = elem->nameURI;
529 cur->select = elem->select;
530 cur->tree = elem->tree;
531 cur->comp = elem->comp;
532 return(cur);
533}
534
541static void
543 if (elem == NULL)
544 return;
545 if (elem->value != NULL)
546 xmlXPathFreeObject(elem->value);
547 /*
548 * Release the list of temporary Result Tree Fragments.
549 */
550 if (elem->context) {
552
553 while (elem->fragment != NULL) {
554 cur = elem->fragment;
555 elem->fragment = (xmlDocPtr) cur->next;
556
557 if (cur->psvi == XSLT_RVT_LOCAL) {
558 xsltReleaseRVT(elem->context, cur);
559 } else if (cur->psvi == XSLT_RVT_FUNC_RESULT) {
560 xsltRegisterLocalRVT(elem->context, cur);
562 } else {
564 "xsltFreeStackElem: Unexpected RVT flag %p\n",
565 cur->psvi);
566 }
567 }
568 }
569 /*
570 * Cache or free the variable structure.
571 */
572 if (elem->context && (elem->context->cache->nbStackItems < 50)) {
573 /*
574 * Store the item in the cache.
575 */
576 xsltTransformContextPtr ctxt = elem->context;
577 memset(elem, 0, sizeof(xsltStackElem));
578 elem->context = ctxt;
579 elem->next = ctxt->cache->stackItems;
580 ctxt->cache->stackItems = elem;
581 ctxt->cache->nbStackItems++;
582#ifdef XSLT_DEBUG_PROFILE_CACHE
583 ctxt->cache->dbgCachedVars++;
584#endif
585 return;
586 }
587 xmlFree(elem);
588}
589
590static void
593}
594
595
602void
605
606 while (elem != NULL) {
607 next = elem->next;
609 elem = next;
610 }
611}
612
621#if 0 /* TODO: Those seem to have been used for debugging. */
622static int stack_addr = 0;
623static int stack_cmp = 0;
624#endif
625
626static xsltStackElemPtr
628 const xmlChar *nameURI) {
629 int i;
631
632 if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))
633 return(NULL);
634
635 /*
636 * Do the lookup from the top of the stack, but
637 * don't use params being computed in a call-param
638 * First lookup expects the variable name and URI to
639 * come from the disctionnary and hence pointer comparison.
640 */
641 for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
642 cur = ctxt->varsTab[i-1];
643 while (cur != NULL) {
644 if ((cur->name == name) && (cur->nameURI == nameURI)) {
645#if 0
646 stack_addr++;
647#endif
648 return(cur);
649 }
650 cur = cur->next;
651 }
652 }
653
654 /*
655 * Redo the lookup with interned string compares
656 * to avoid string compares.
657 */
658 name = xmlDictLookup(ctxt->dict, name, -1);
659 if (nameURI != NULL)
660 nameURI = xmlDictLookup(ctxt->dict, nameURI, -1);
661
662 for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
663 cur = ctxt->varsTab[i-1];
664 while (cur != NULL) {
665 if ((cur->name == name) && (cur->nameURI == nameURI)) {
666#if 0
667 stack_cmp++;
668#endif
669 return(cur);
670 }
671 cur = cur->next;
672 }
673 }
674
675 return(NULL);
676}
677
678#ifdef XSLT_REFACTORED
679#else
680
695static int
697 const xmlChar *nameURI) {
699
700 if ((ctxt == NULL) || (name == NULL))
701 return(-1);
702
703 cur = xsltStackLookup(ctxt, name, nameURI);
704 if (cur == NULL)
705 return(0);
706 if (cur->comp != NULL) {
707 if (cur->comp->type == XSLT_FUNC_WITHPARAM)
708 return(3);
709 else if (cur->comp->type == XSLT_FUNC_PARAM)
710 return(2);
711 }
712
713 return(1);
714}
715
716#endif /* XSLT_REFACTORED */
717
730static int
732{
733 if ((ctxt == NULL) || (elem == NULL))
734 return(-1);
735
736 do {
737 if (ctxt->varsMax == 0) {
738 ctxt->varsMax = 10;
739 ctxt->varsTab =
741 sizeof(ctxt->varsTab[0]));
742 if (ctxt->varsTab == NULL) {
743 xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
744 return (-1);
745 }
746 }
747 if (ctxt->varsNr >= ctxt->varsMax) {
748 ctxt->varsMax *= 2;
749 ctxt->varsTab =
751 ctxt->varsMax *
752 sizeof(ctxt->varsTab[0]));
753 if (ctxt->varsTab == NULL) {
754 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
755 return (-1);
756 }
757 }
758 ctxt->varsTab[ctxt->varsNr++] = elem;
759 ctxt->vars = elem;
760
761 elem = elem->next;
762 } while (elem != NULL);
763
764 return(0);
765}
766
776int
778{
779 return(xsltAddStackElem(ctxt, elems));
780}
781
782/************************************************************************
783 * *
784 * Module interfaces *
785 * *
786 ************************************************************************/
787
798static xmlXPathObjectPtr
800 xsltStylePreCompPtr castedComp)
801{
802#ifdef XSLT_REFACTORED
803 xsltStyleItemVariablePtr comp =
804 (xsltStyleItemVariablePtr) castedComp;
805#else
806 xsltStylePreCompPtr comp = castedComp;
807#endif
808 xmlXPathObjectPtr result = NULL;
809 xmlNodePtr oldInst;
810
811 if ((ctxt == NULL) || (variable == NULL))
812 return(NULL);
813
814 /*
815 * A variable or parameter are evaluated on demand; thus the
816 * context (of XSLT and XPath) need to be temporarily adjusted and
817 * restored on exit.
818 */
819 oldInst = ctxt->inst;
820
821#ifdef WITH_XSLT_DEBUG_VARIABLE
823 "Evaluating variable '%s'\n", variable->name));
824#endif
825 if (variable->select != NULL) {
826 xmlXPathCompExprPtr xpExpr = NULL;
827 xmlDocPtr oldXPDoc;
828 xmlNodePtr oldXPContextNode;
829 int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
830 xmlNsPtr *oldXPNamespaces;
831 xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
832 xsltStackElemPtr oldVar = ctxt->contextVariable;
833
834 if ((comp != NULL) && (comp->comp != NULL)) {
835 xpExpr = comp->comp;
836 } else {
837 xpExpr = xmlXPathCtxtCompile(ctxt->xpathCtxt, variable->select);
838 }
839 if (xpExpr == NULL)
840 return(NULL);
841 /*
842 * Save context states.
843 */
844 oldXPDoc = xpctxt->doc;
845 oldXPContextNode = xpctxt->node;
846 oldXPProximityPosition = xpctxt->proximityPosition;
847 oldXPContextSize = xpctxt->contextSize;
848 oldXPNamespaces = xpctxt->namespaces;
849 oldXPNsNr = xpctxt->nsNr;
850
851 xpctxt->node = ctxt->node;
852 /*
853 * OPTIMIZE TODO: Lame try to set the context doc.
854 * Get rid of this somehow in xpath.c.
855 */
856 if ((ctxt->node->type != XML_NAMESPACE_DECL) &&
857 ctxt->node->doc)
858 xpctxt->doc = ctxt->node->doc;
859 /*
860 * BUG TODO: The proximity position and the context size will
861 * potentially be wrong.
862 * Example:
863 * <xsl:template select="foo">
864 * <xsl:variable name="pos" select="position()"/>
865 * <xsl:for-each select="bar">
866 * <xsl:value-of select="$pos"/>
867 * </xsl:for-each>
868 * </xsl:template>
869 * Here the proximity position and context size are changed
870 * to the context of <xsl:for-each select="bar">, but
871 * the variable needs to be evaluated in the context of
872 * <xsl:template select="foo">.
873 */
874 if (comp != NULL) {
875
876#ifdef XSLT_REFACTORED
877 if (comp->inScopeNs != NULL) {
878 xpctxt->namespaces = comp->inScopeNs->list;
879 xpctxt->nsNr = comp->inScopeNs->xpathNumber;
880 } else {
881 xpctxt->namespaces = NULL;
882 xpctxt->nsNr = 0;
883 }
884#else
885 xpctxt->namespaces = comp->nsList;
886 xpctxt->nsNr = comp->nsNr;
887#endif
888 } else {
889 xpctxt->namespaces = NULL;
890 xpctxt->nsNr = 0;
891 }
892
893 /*
894 * We need to mark that we are "selecting" a var's value;
895 * if any tree fragments are created inside the expression,
896 * then those need to be stored inside the variable; otherwise
897 * we'll eventually free still referenced fragments, before
898 * we leave the scope of the variable.
899 */
902
903 result = xmlXPathCompiledEval(xpExpr, xpctxt);
904
906 /*
907 * Restore Context states.
908 */
909 ctxt->contextVariable = oldVar;
910
911 xpctxt->doc = oldXPDoc;
912 xpctxt->node = oldXPContextNode;
913 xpctxt->contextSize = oldXPContextSize;
914 xpctxt->proximityPosition = oldXPProximityPosition;
915 xpctxt->namespaces = oldXPNamespaces;
916 xpctxt->nsNr = oldXPNsNr;
917
918 if ((comp == NULL) || (comp->comp == NULL))
919 xmlXPathFreeCompExpr(xpExpr);
920 if (result == NULL) {
922 (comp != NULL) ? comp->inst : NULL,
923 "Failed to evaluate the expression of variable '%s'.\n",
924 variable->name);
926
927#ifdef WITH_XSLT_DEBUG_VARIABLE
928#ifdef LIBXML_DEBUG_ENABLED
929 } else {
932 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
933 result, 0);
934#endif
935#endif
936 }
937 } else {
938 if (variable->tree == NULL) {
939 result = xmlXPathNewCString("");
940 } else {
941 if (variable->tree) {
943 xmlNodePtr oldInsert;
944 xmlDocPtr oldOutput;
945 const xmlChar *oldLastText;
946 int oldLastTextSize, oldLastTextUse;
947 xsltStackElemPtr oldVar = ctxt->contextVariable;
948
949 /*
950 * Generate a result tree fragment.
951 */
952 container = xsltCreateRVT(ctxt);
953 if (container == NULL)
954 goto error;
955 /*
956 * NOTE: Local Result Tree Fragments of params/variables
957 * are not registered globally anymore; the life-time
958 * is not directly dependant of the param/variable itself.
959 *
960 * OLD: xsltRegisterTmpRVT(ctxt, container);
961 */
962 /*
963 * Attach the Result Tree Fragment to the variable;
964 * when the variable is freed, it will also free
965 * the Result Tree Fragment.
966 */
967 variable->fragment = container;
969
970 oldOutput = ctxt->output;
971 oldInsert = ctxt->insert;
972 oldLastText = ctxt->lasttext;
973 oldLastTextSize = ctxt->lasttsize;
974 oldLastTextUse = ctxt->lasttuse;
975
976 ctxt->output = container;
977 ctxt->insert = (xmlNodePtr) container;
979 /*
980 * Process the sequence constructor (variable->tree).
981 * The resulting tree will be held by @container.
982 */
983 xsltApplyOneTemplate(ctxt, ctxt->node, variable->tree,
984 NULL, NULL);
985
986 ctxt->contextVariable = oldVar;
987 ctxt->insert = oldInsert;
988 ctxt->output = oldOutput;
989 ctxt->lasttext = oldLastText;
990 ctxt->lasttsize = oldLastTextSize;
991 ctxt->lasttuse = oldLastTextUse;
992
993 result = xmlXPathNewValueTree((xmlNodePtr) container);
994 }
995 if (result == NULL) {
996 result = xmlXPathNewCString("");
997 } else {
998 /*
999 * Freeing is not handled there anymore.
1000 * QUESTION TODO: What does the above comment mean?
1001 */
1002 result->boolval = 0;
1003 }
1004#ifdef WITH_XSLT_DEBUG_VARIABLE
1005#ifdef LIBXML_DEBUG_ENABLED
1006
1009 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
1010 result, 0);
1011#endif
1012#endif
1013 }
1014 }
1015
1016error:
1017 ctxt->inst = oldInst;
1018 return(result);
1019}
1020
1031static xmlXPathObjectPtr
1033{
1034 xmlXPathObjectPtr result = NULL;
1035 xmlNodePtr oldInst;
1036 const xmlChar* oldVarName;
1037
1038#ifdef XSLT_REFACTORED
1039 xsltStyleBasicItemVariablePtr comp;
1040#else
1042#endif
1043
1044 if ((ctxt == NULL) || (elem == NULL))
1045 return(NULL);
1046 if (elem->computed)
1047 return(elem->value);
1048
1049
1050#ifdef WITH_XSLT_DEBUG_VARIABLE
1052 "Evaluating global variable %s\n", elem->name));
1053#endif
1054
1055#ifdef WITH_DEBUGGER
1056 if ((ctxt->debugStatus != XSLT_DEBUG_NONE) &&
1057 elem->comp && elem->comp->inst)
1058 xslHandleDebugger(elem->comp->inst, NULL, NULL, ctxt);
1059#endif
1060
1061 oldInst = ctxt->inst;
1062#ifdef XSLT_REFACTORED
1063 comp = (xsltStyleBasicItemVariablePtr) elem->comp;
1064#else
1065 comp = elem->comp;
1066#endif
1067 oldVarName = elem->name;
1069 /*
1070 * OPTIMIZE TODO: We should consider instantiating global vars/params
1071 * on-demand. The vars/params don't need to be evaluated if never
1072 * called; and in the case of global params, if values for such params
1073 * are provided by the user.
1074 */
1075 if (elem->select != NULL) {
1076 xmlXPathCompExprPtr xpExpr = NULL;
1077 xmlDocPtr oldXPDoc;
1078 xmlNodePtr oldXPContextNode;
1079 int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
1080 xmlNsPtr *oldXPNamespaces;
1081 xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
1082
1083 if ((comp != NULL) && (comp->comp != NULL)) {
1084 xpExpr = comp->comp;
1085 } else {
1086 xpExpr = xmlXPathCtxtCompile(ctxt->xpathCtxt, elem->select);
1087 }
1088 if (xpExpr == NULL)
1089 goto error;
1090
1091
1092 if (comp != NULL)
1093 ctxt->inst = comp->inst;
1094 else
1095 ctxt->inst = NULL;
1096 /*
1097 * SPEC XSLT 1.0:
1098 * "At top-level, the expression or template specifying the
1099 * variable value is evaluated with the same context as that used
1100 * to process the root node of the source document: the current
1101 * node is the root node of the source document and the current
1102 * node list is a list containing just the root node of the source
1103 * document."
1104 */
1105 /*
1106 * Save context states.
1107 */
1108 oldXPDoc = xpctxt->doc;
1109 oldXPContextNode = xpctxt->node;
1110 oldXPProximityPosition = xpctxt->proximityPosition;
1111 oldXPContextSize = xpctxt->contextSize;
1112 oldXPNamespaces = xpctxt->namespaces;
1113 oldXPNsNr = xpctxt->nsNr;
1114
1115 xpctxt->node = ctxt->initialContextNode;
1116 xpctxt->doc = ctxt->initialContextDoc;
1117 xpctxt->contextSize = 1;
1118 xpctxt->proximityPosition = 1;
1119
1120 if (comp != NULL) {
1121
1122#ifdef XSLT_REFACTORED
1123 if (comp->inScopeNs != NULL) {
1124 xpctxt->namespaces = comp->inScopeNs->list;
1125 xpctxt->nsNr = comp->inScopeNs->xpathNumber;
1126 } else {
1127 xpctxt->namespaces = NULL;
1128 xpctxt->nsNr = 0;
1129 }
1130#else
1131 xpctxt->namespaces = comp->nsList;
1132 xpctxt->nsNr = comp->nsNr;
1133#endif
1134 } else {
1135 xpctxt->namespaces = NULL;
1136 xpctxt->nsNr = 0;
1137 }
1138
1139 result = xmlXPathCompiledEval(xpExpr, xpctxt);
1140
1141 /*
1142 * Restore Context states.
1143 */
1144 xpctxt->doc = oldXPDoc;
1145 xpctxt->node = oldXPContextNode;
1146 xpctxt->contextSize = oldXPContextSize;
1147 xpctxt->proximityPosition = oldXPProximityPosition;
1148 xpctxt->namespaces = oldXPNamespaces;
1149 xpctxt->nsNr = oldXPNsNr;
1150
1151 if ((comp == NULL) || (comp->comp == NULL))
1152 xmlXPathFreeCompExpr(xpExpr);
1153 if (result == NULL) {
1154 if (comp == NULL)
1156 "Evaluating global variable %s failed\n", elem->name);
1157 else
1158 xsltTransformError(ctxt, NULL, comp->inst,
1159 "Evaluating global variable %s failed\n", elem->name);
1160 ctxt->state = XSLT_STATE_STOPPED;
1161 goto error;
1162 }
1163
1164 /*
1165 * Mark all RVTs that are referenced from result as part
1166 * of this variable so they won't be freed too early.
1167 */
1169
1170#ifdef WITH_XSLT_DEBUG_VARIABLE
1171#ifdef LIBXML_DEBUG_ENABLED
1174 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
1175 result, 0);
1176#endif
1177#endif
1178 } else {
1179 if (elem->tree == NULL) {
1180 result = xmlXPathNewCString("");
1181 } else {
1183 xmlNodePtr oldInsert;
1184 xmlDocPtr oldOutput, oldXPDoc;
1185 /*
1186 * Generate a result tree fragment.
1187 */
1188 container = xsltCreateRVT(ctxt);
1189 if (container == NULL)
1190 goto error;
1191 /*
1192 * Let the lifetime of the tree fragment be handled by
1193 * the Libxslt's garbage collector.
1194 */
1196
1197 oldOutput = ctxt->output;
1198 oldInsert = ctxt->insert;
1199
1200 oldXPDoc = ctxt->xpathCtxt->doc;
1201
1202 ctxt->output = container;
1203 ctxt->insert = (xmlNodePtr) container;
1204
1205 ctxt->xpathCtxt->doc = ctxt->initialContextDoc;
1206 /*
1207 * Process the sequence constructor.
1208 */
1209 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
1210
1211 ctxt->xpathCtxt->doc = oldXPDoc;
1212
1213 ctxt->insert = oldInsert;
1214 ctxt->output = oldOutput;
1215
1216 result = xmlXPathNewValueTree((xmlNodePtr) container);
1217 if (result == NULL) {
1218 result = xmlXPathNewCString("");
1219 } else {
1220 result->boolval = 0; /* Freeing is not handled there anymore */
1221 }
1222#ifdef WITH_XSLT_DEBUG_VARIABLE
1223#ifdef LIBXML_DEBUG_ENABLED
1226 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
1227 result, 0);
1228#endif
1229#endif
1230 }
1231 }
1232
1233error:
1234 elem->name = oldVarName;
1235 ctxt->inst = oldInst;
1236 if (result != NULL) {
1237 elem->value = result;
1238 elem->computed = 1;
1239 }
1240 return(result);
1241}
1242
1243static void
1245 const xmlChar *name ATTRIBUTE_UNUSED) {
1248}
1249
1259int
1263
1264 if ((ctxt == NULL) || (ctxt->document == NULL))
1265 return(-1);
1266
1267#ifdef WITH_XSLT_DEBUG_VARIABLE
1269 "Registering global variables\n"));
1270#endif
1271 /*
1272 * Walk the list from the stylesheets and populate the hash table
1273 */
1274 style = ctxt->style;
1275 while (style != NULL) {
1276 elem = style->variables;
1277
1278#ifdef WITH_XSLT_DEBUG_VARIABLE
1279 if ((style->doc != NULL) && (style->doc->URL != NULL)) {
1281 "Registering global variables from %s\n",
1282 style->doc->URL));
1283 }
1284#endif
1285
1286 while (elem != NULL) {
1287 xsltStackElemPtr def;
1288
1289 /*
1290 * Global variables are stored in the variables pool.
1291 */
1292 def = (xsltStackElemPtr)
1294 elem->name, elem->nameURI);
1295 if (def == NULL) {
1296
1297 def = xsltCopyStackElem(elem);
1299 elem->name, elem->nameURI, def);
1300 } else if ((elem->comp != NULL) &&
1301 (elem->comp->type == XSLT_FUNC_VARIABLE)) {
1302 /*
1303 * Redefinition of variables from a different stylesheet
1304 * should not generate a message.
1305 */
1306 if ((elem->comp->inst != NULL) &&
1307 (def->comp != NULL) && (def->comp->inst != NULL) &&
1308 (elem->comp->inst->doc == def->comp->inst->doc))
1309 {
1310 xsltTransformError(ctxt, style, elem->comp->inst,
1311 "Global variable %s already defined\n", elem->name);
1312 if (style != NULL) style->errors++;
1313 }
1314 }
1315 elem = elem->next;
1316 }
1317
1319 }
1320
1321 /*
1322 * This part does the actual evaluation
1323 */
1325
1326 return(0);
1327}
1328
1344static int
1346 const xmlChar *ns_uri, const xmlChar *sel,
1348 const xmlChar *value) {
1350 if (style == NULL)
1351 return(-1);
1352 if (name == NULL)
1353 return(-1);
1354 if (comp == NULL)
1355 return(-1);
1356
1357#ifdef WITH_XSLT_DEBUG_VARIABLE
1358 if (comp->type == XSLT_FUNC_PARAM)
1360 "Defining global param %s\n", name);
1361 else
1363 "Defining global variable %s\n", name);
1364#endif
1365
1367 if (elem == NULL)
1368 return(-1);
1369 elem->comp = comp;
1370 elem->name = xmlDictLookup(style->dict, name, -1);
1371 elem->select = xmlDictLookup(style->dict, sel, -1);
1372 if (ns_uri)
1373 elem->nameURI = xmlDictLookup(style->dict, ns_uri, -1);
1374 elem->tree = tree;
1375 tmp = style->variables;
1376 if (tmp == NULL) {
1377 elem->next = NULL;
1378 style->variables = elem;
1379 } else {
1380 while (tmp != NULL) {
1381 if ((elem->comp->type == XSLT_FUNC_VARIABLE) &&
1382 (tmp->comp->type == XSLT_FUNC_VARIABLE) &&
1383 (xmlStrEqual(elem->name, tmp->name)) &&
1384 ((elem->nameURI == tmp->nameURI) ||
1385 (xmlStrEqual(elem->nameURI, tmp->nameURI))))
1386 {
1388 "redefinition of global variable %s\n", elem->name);
1389 style->errors++;
1390 }
1391 if (tmp->next == NULL)
1392 break;
1393 tmp = tmp->next;
1394 }
1395 elem->next = NULL;
1396 tmp->next = elem;
1397 }
1398 if (value != NULL) {
1399 elem->computed = 1;
1400 elem->value = xmlXPathNewString(value);
1401 }
1402 return(0);
1403}
1404
1436static
1437int
1439 const xmlChar * name,
1440 const xmlChar * value,
1441 int eval) {
1442
1444 const xmlChar *prefix;
1445 const xmlChar *href;
1446 xmlXPathCompExprPtr xpExpr;
1447 xmlXPathObjectPtr result;
1448
1450 int res;
1451 void *res_ptr;
1452
1453 if (ctxt == NULL)
1454 return(-1);
1455 if (name == NULL)
1456 return(0);
1457 if (value == NULL)
1458 return(0);
1459
1460 style = ctxt->style;
1461
1462#ifdef WITH_XSLT_DEBUG_VARIABLE
1464 "Evaluating user parameter %s=%s\n", name, value));
1465#endif
1466
1467 /*
1468 * Name lookup
1469 */
1470 href = NULL;
1471
1472 if (name[0] == '{') {
1473 int len = 0;
1474
1475 while ((name[len] != 0) && (name[len] != '}')) len++;
1476 if (name[len] == 0) {
1478 "user param : malformed parameter name : %s\n", name);
1479 } else {
1480 href = xmlDictLookup(ctxt->dict, &name[1], len-1);
1481 name = xmlDictLookup(ctxt->dict, &name[len + 1], -1);
1482 }
1483 }
1484 else {
1485 name = xsltSplitQName(ctxt->dict, name, &prefix);
1486 if (prefix != NULL) {
1487 xmlNsPtr ns;
1488
1490 prefix);
1491 if (ns == NULL) {
1493 "user param : no namespace bound to prefix %s\n", prefix);
1494 href = NULL;
1495 } else {
1496 href = ns->href;
1497 }
1498 }
1499 }
1500
1501 if (name == NULL)
1502 return (-1);
1503
1504 res_ptr = xmlHashLookup2(ctxt->globalVars, name, href);
1505 if (res_ptr != 0) {
1507 "Global parameter %s already defined\n", name);
1508 }
1509 if (ctxt->globalVars == NULL)
1510 ctxt->globalVars = xmlHashCreate(20);
1511
1512 /*
1513 * do not overwrite variables with parameters from the command line
1514 */
1515 while (style != NULL) {
1516 elem = ctxt->style->variables;
1517 while (elem != NULL) {
1518 if ((elem->comp != NULL) &&
1519 (elem->comp->type == XSLT_FUNC_VARIABLE) &&
1520 (xmlStrEqual(elem->name, name)) &&
1521 (xmlStrEqual(elem->nameURI, href))) {
1522 return(0);
1523 }
1524 elem = elem->next;
1525 }
1527 }
1528 style = ctxt->style;
1529 elem = NULL;
1530
1531 /*
1532 * Do the evaluation if @eval is non-zero.
1533 */
1534
1535 result = NULL;
1536 if (eval != 0) {
1537 xpExpr = xmlXPathCtxtCompile(ctxt->xpathCtxt, value);
1538 if (xpExpr != NULL) {
1539 xmlDocPtr oldXPDoc;
1540 xmlNodePtr oldXPContextNode;
1541 int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
1542 xmlNsPtr *oldXPNamespaces;
1543 xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
1544
1545 /*
1546 * Save context states.
1547 */
1548 oldXPDoc = xpctxt->doc;
1549 oldXPContextNode = xpctxt->node;
1550 oldXPProximityPosition = xpctxt->proximityPosition;
1551 oldXPContextSize = xpctxt->contextSize;
1552 oldXPNamespaces = xpctxt->namespaces;
1553 oldXPNsNr = xpctxt->nsNr;
1554
1555 /*
1556 * SPEC XSLT 1.0:
1557 * "At top-level, the expression or template specifying the
1558 * variable value is evaluated with the same context as that used
1559 * to process the root node of the source document: the current
1560 * node is the root node of the source document and the current
1561 * node list is a list containing just the root node of the source
1562 * document."
1563 */
1564 xpctxt->doc = ctxt->initialContextDoc;
1565 xpctxt->node = ctxt->initialContextNode;
1566 xpctxt->contextSize = 1;
1567 xpctxt->proximityPosition = 1;
1568 /*
1569 * There is really no in scope namespace for parameters on the
1570 * command line.
1571 */
1572 xpctxt->namespaces = NULL;
1573 xpctxt->nsNr = 0;
1574
1575 result = xmlXPathCompiledEval(xpExpr, xpctxt);
1576
1577 /*
1578 * Restore Context states.
1579 */
1580 xpctxt->doc = oldXPDoc;
1581 xpctxt->node = oldXPContextNode;
1582 xpctxt->contextSize = oldXPContextSize;
1583 xpctxt->proximityPosition = oldXPProximityPosition;
1584 xpctxt->namespaces = oldXPNamespaces;
1585 xpctxt->nsNr = oldXPNsNr;
1586
1587 xmlXPathFreeCompExpr(xpExpr);
1588 }
1589 if (result == NULL) {
1591 "Evaluating user parameter %s failed\n", name);
1592 ctxt->state = XSLT_STATE_STOPPED;
1593 return(-1);
1594 }
1595 }
1596
1597 /*
1598 * If @eval is 0 then @value is to be taken literally and result is NULL
1599 *
1600 * If @eval is not 0, then @value is an XPath expression and has been
1601 * successfully evaluated and result contains the resulting value and
1602 * is not NULL.
1603 *
1604 * Now create an xsltStackElemPtr for insertion into the context's
1605 * global variable/parameter hash table.
1606 */
1607
1608#ifdef WITH_XSLT_DEBUG_VARIABLE
1609#ifdef LIBXML_DEBUG_ENABLED
1612 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
1613 result, 0);
1614#endif
1615#endif
1616
1618 if (elem != NULL) {
1619 elem->name = name;
1620 elem->select = xmlDictLookup(ctxt->dict, value, -1);
1621 if (href != NULL)
1622 elem->nameURI = xmlDictLookup(ctxt->dict, href, -1);
1623 elem->tree = NULL;
1624 elem->computed = 1;
1625 if (eval == 0) {
1626 elem->value = xmlXPathNewString(value);
1627 }
1628 else {
1629 elem->value = result;
1630 }
1631 }
1632
1633 /*
1634 * Global parameters are stored in the XPath context variables pool.
1635 */
1636
1637 res = xmlHashAddEntry2(ctxt->globalVars, name, href, elem);
1638 if (res != 0) {
1641 "Global parameter %s already defined\n", name);
1642 }
1643 return(0);
1644}
1645
1661int
1663 int indx = 0;
1664 const xmlChar *name;
1665 const xmlChar *value;
1666
1667 if (params == NULL)
1668 return(0);
1669 while (params[indx] != NULL) {
1670 name = (const xmlChar *) params[indx++];
1671 value = (const xmlChar *) params[indx++];
1672 if (xsltEvalOneUserParam(ctxt, name, value) != 0)
1673 return(-1);
1674 }
1675 return 0;
1676}
1677
1691int
1693 int indx = 0;
1694 const xmlChar *name;
1695 const xmlChar *value;
1696
1697 if (params == NULL)
1698 return(0);
1699 while (params[indx] != NULL) {
1700 name = (const xmlChar *) params[indx++];
1701 value = (const xmlChar *) params[indx++];
1702 if (xsltQuoteOneUserParam(ctxt, name, value) != 0)
1703 return(-1);
1704 }
1705 return 0;
1706}
1707
1726int
1728 const xmlChar * name,
1729 const xmlChar * value) {
1731 1 /* xpath eval ? */);
1732}
1733
1747int
1749 const xmlChar * name,
1750 const xmlChar * value) {
1752 0 /* xpath eval ? */);
1753}
1754
1765static xsltStackElemPtr
1767 xsltStylePreCompPtr castedComp,
1769{
1770#ifdef XSLT_REFACTORED
1771 xsltStyleBasicItemVariablePtr comp =
1772 (xsltStyleBasicItemVariablePtr) castedComp;
1773#else
1774 xsltStylePreCompPtr comp = castedComp;
1775#endif
1777
1778#ifdef WITH_XSLT_DEBUG_VARIABLE
1780 "Building variable %s", comp->name));
1781 if (comp->select != NULL)
1783 " select %s", comp->select));
1785#endif
1786
1787 elem = xsltNewStackElem(ctxt);
1788 if (elem == NULL)
1789 return(NULL);
1790 elem->comp = (xsltStylePreCompPtr) comp;
1791 elem->name = comp->name;
1792 elem->select = comp->select;
1793 elem->nameURI = comp->ns;
1794 elem->tree = tree;
1795 elem->value = xsltEvalVariable(ctxt, elem,
1796 (xsltStylePreCompPtr) comp);
1797 elem->computed = 1;
1798 return(elem);
1799}
1800
1812static int
1814 xsltStylePreCompPtr castedComp,
1815 xmlNodePtr tree, int isParam)
1816{
1817#ifdef XSLT_REFACTORED
1818 xsltStyleBasicItemVariablePtr comp =
1819 (xsltStyleBasicItemVariablePtr) castedComp;
1820#else
1821 xsltStylePreCompPtr comp = castedComp;
1822 int present;
1823#endif
1825
1826#ifdef XSLT_REFACTORED
1827 /*
1828 * REFACTORED NOTE: Redefinitions of vars/params are checked
1829 * at compilation time in the refactored code.
1830 * xsl:with-param parameters are checked in xsltApplyXSLTTemplate().
1831 */
1832#else
1833 present = xsltCheckStackElem(ctxt, comp->name, comp->ns);
1834 if (isParam == 0) {
1835 if ((present != 0) && (present != 3)) {
1836 /* TODO: report QName. */
1837 xsltTransformError(ctxt, NULL, comp->inst,
1838 "XSLT-variable: Redefinition of variable '%s'.\n", comp->name);
1839 return(0);
1840 }
1841 } else if (present != 0) {
1842 if ((present == 1) || (present == 2)) {
1843 /* TODO: report QName. */
1844 xsltTransformError(ctxt, NULL, comp->inst,
1845 "XSLT-param: Redefinition of parameter '%s'.\n", comp->name);
1846 return(0);
1847 }
1848#ifdef WITH_XSLT_DEBUG_VARIABLE
1850 "param %s defined by caller\n", comp->name));
1851#endif
1852 return(0);
1853 }
1854#endif /* else of XSLT_REFACTORED */
1855
1858 return(0);
1859}
1860
1872static xmlXPathObjectPtr
1874 const xmlChar *ns_uri) {
1876 xmlXPathObjectPtr ret = NULL;
1877
1878 /*
1879 * Lookup the global variables in XPath global variable hash table
1880 */
1881 if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))
1882 return(NULL);
1884 xmlHashLookup2(ctxt->globalVars, name, ns_uri);
1885 if (elem == NULL) {
1886#ifdef WITH_XSLT_DEBUG_VARIABLE
1888 "global variable not found %s\n", name));
1889#endif
1890 return(NULL);
1891 }
1892 /*
1893 * URGENT TODO: Move the detection of recursive definitions
1894 * to compile-time.
1895 */
1896 if (elem->computed == 0) {
1897 if (elem->name == xsltComputingGlobalVarMarker) {
1898 xsltTransformError(ctxt, NULL, elem->comp->inst,
1899 "Recursive definition of %s\n", name);
1900 return(NULL);
1901 }
1903 } else
1904 ret = elem->value;
1905 return(xmlXPathObjectCopy(ret));
1906}
1907
1919xmlXPathObjectPtr
1921 const xmlChar *ns_uri) {
1923
1924 if (ctxt == NULL)
1925 return(NULL);
1926
1927 elem = xsltStackLookup(ctxt, name, ns_uri);
1928 if (elem == NULL) {
1929 return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
1930 }
1931 if (elem->computed == 0) {
1932#ifdef WITH_XSLT_DEBUG_VARIABLE
1934 "uncomputed variable %s\n", name));
1935#endif
1936 elem->value = xsltEvalVariable(ctxt, elem, NULL);
1937 elem->computed = 1;
1938 }
1939 if (elem->value != NULL)
1940 return(xmlXPathObjectCopy(elem->value));
1941#ifdef WITH_XSLT_DEBUG_VARIABLE
1943 "variable not found %s\n", name));
1944#endif
1945 return(NULL);
1946}
1947
1963{
1964#ifdef XSLT_REFACTORED
1965 xsltStyleBasicItemVariablePtr comp;
1966#else
1968#endif
1969 xmlNodePtr tree = NULL; /* The first child node of the instruction or
1970 the instruction itself. */
1972
1973 if ((ctxt == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
1974 return(NULL);
1975
1976#ifdef XSLT_REFACTORED
1977 comp = (xsltStyleBasicItemVariablePtr) inst->psvi;
1978#else
1979 comp = (xsltStylePreCompPtr) inst->psvi;
1980#endif
1981
1982 if (comp == NULL) {
1983 xsltTransformError(ctxt, NULL, inst,
1984 "Internal error in xsltParseStylesheetCallerParam(): "
1985 "The XSLT 'with-param' instruction was not compiled.\n");
1986 return(NULL);
1987 }
1988 if (comp->name == NULL) {
1989 xsltTransformError(ctxt, NULL, inst,
1990 "Internal error in xsltParseStylesheetCallerParam(): "
1991 "XSLT 'with-param': The attribute 'name' was not compiled.\n");
1992 return(NULL);
1993 }
1994
1995#ifdef WITH_XSLT_DEBUG_VARIABLE
1997 "Handling xsl:with-param %s\n", comp->name));
1998#endif
1999
2000 if (comp->select == NULL) {
2001 tree = inst->children;
2002 } else {
2003#ifdef WITH_XSLT_DEBUG_VARIABLE
2005 " select %s\n", comp->select));
2006#endif
2007 tree = inst;
2008 }
2009
2011
2012 return(param);
2013}
2014
2023void
2025{
2026#ifdef XSLT_REFACTORED
2027 xsltStyleItemVariablePtr comp;
2028#else
2030#endif
2031
2032 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
2033 return;
2034
2035#ifdef XSLT_REFACTORED
2036 /*
2037 * Note that xsltStylePreCompute() will be called from
2038 * xslt.c only.
2039 */
2040 comp = (xsltStyleItemVariablePtr) cur->psvi;
2041#else
2043 comp = (xsltStylePreCompPtr) cur->psvi;
2044#endif
2045 if (comp == NULL) {
2047 "xsl:variable : compilation failed\n");
2048 return;
2049 }
2050
2051 if (comp->name == NULL) {
2053 "xsl:variable : missing name attribute\n");
2054 return;
2055 }
2056
2057 /*
2058 * Parse the content (a sequence constructor) of xsl:variable.
2059 */
2060 if (cur->children != NULL) {
2061#ifdef XSLT_REFACTORED
2062 xsltParseSequenceConstructor(XSLT_CCTXT(style), cur->children);
2063#else
2065#endif
2066 }
2067#ifdef WITH_XSLT_DEBUG_VARIABLE
2069 "Registering global variable %s\n", comp->name);
2070#endif
2071
2072 xsltRegisterGlobalVariable(style, comp->name, comp->ns,
2073 comp->select, cur->children, (xsltStylePreCompPtr) comp,
2074 NULL);
2075}
2076
2086void
2088#ifdef XSLT_REFACTORED
2089 xsltStyleItemParamPtr comp;
2090#else
2092#endif
2093
2094 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
2095 return;
2096
2097#ifdef XSLT_REFACTORED
2098 /*
2099 * Note that xsltStylePreCompute() will be called from
2100 * xslt.c only.
2101 */
2102 comp = (xsltStyleItemParamPtr) cur->psvi;
2103#else
2105 comp = (xsltStylePreCompPtr) cur->psvi;
2106#endif
2107 if (comp == NULL) {
2109 "xsl:param : compilation failed\n");
2110 return;
2111 }
2112
2113 if (comp->name == NULL) {
2115 "xsl:param : missing name attribute\n");
2116 return;
2117 }
2118
2119 /*
2120 * Parse the content (a sequence constructor) of xsl:param.
2121 */
2122 if (cur->children != NULL) {
2123#ifdef XSLT_REFACTORED
2124 xsltParseSequenceConstructor(XSLT_CCTXT(style), cur->children);
2125#else
2127#endif
2128 }
2129
2130#ifdef WITH_XSLT_DEBUG_VARIABLE
2132 "Registering global param %s\n", comp->name);
2133#endif
2134
2135 xsltRegisterGlobalVariable(style, comp->name, comp->ns,
2136 comp->select, cur->children, (xsltStylePreCompPtr) comp,
2137 NULL);
2138}
2139
2148void
2150{
2151#ifdef XSLT_REFACTORED
2152 xsltStyleItemVariablePtr comp;
2153#else
2155#endif
2156
2157 if ((inst == NULL) || (ctxt == NULL) || (inst->type != XML_ELEMENT_NODE))
2158 return;
2159
2160 comp = inst->psvi;
2161 if (comp == NULL) {
2162 xsltTransformError(ctxt, NULL, inst,
2163 "Internal error in xsltParseStylesheetVariable(): "
2164 "The XSLT 'variable' instruction was not compiled.\n");
2165 return;
2166 }
2167 if (comp->name == NULL) {
2168 xsltTransformError(ctxt, NULL, inst,
2169 "Internal error in xsltParseStylesheetVariable(): "
2170 "The attribute 'name' was not compiled.\n");
2171 return;
2172 }
2173
2174#ifdef WITH_XSLT_DEBUG_VARIABLE
2176 "Registering variable '%s'\n", comp->name));
2177#endif
2178
2179 xsltRegisterVariable(ctxt, (xsltStylePreCompPtr) comp, inst->children, 0);
2180}
2181
2190void
2192{
2193#ifdef XSLT_REFACTORED
2194 xsltStyleItemParamPtr comp;
2195#else
2197#endif
2198
2199 if ((cur == NULL) || (ctxt == NULL) || (cur->type != XML_ELEMENT_NODE))
2200 return;
2201
2202 comp = cur->psvi;
2203 if ((comp == NULL) || (comp->name == NULL)) {
2205 "Internal error in xsltParseStylesheetParam(): "
2206 "The XSLT 'param' declaration was not compiled correctly.\n");
2207 return;
2208 }
2209
2210#ifdef WITH_XSLT_DEBUG_VARIABLE
2212 "Registering param %s\n", comp->name));
2213#endif
2214
2215 xsltRegisterVariable(ctxt, (xsltStylePreCompPtr) comp, cur->children, 1);
2216}
2217
2226void
2229}
2230
2242xmlXPathObjectPtr
2244 const xmlChar *ns_uri) {
2246 xmlXPathObjectPtr valueObj = NULL;
2247
2248 if ((ctxt == NULL) || (name == NULL))
2249 return(NULL);
2250
2251#ifdef WITH_XSLT_DEBUG_VARIABLE
2253 "Lookup variable '%s'\n", name));
2254#endif
2255
2256 tctxt = (xsltTransformContextPtr) ctxt;
2257 /*
2258 * Local variables/params ---------------------------------------------
2259 *
2260 * Do the lookup from the top of the stack, but
2261 * don't use params being computed in a call-param
2262 * First lookup expects the variable name and URI to
2263 * come from the disctionnary and hence pointer comparison.
2264 */
2265 if (tctxt->varsNr != 0) {
2266 int i;
2268
2269 for (i = tctxt->varsNr; i > tctxt->varsBase; i--) {
2270 cur = tctxt->varsTab[i-1];
2271 if ((cur->name == name) && (cur->nameURI == ns_uri)) {
2272#if 0
2273 stack_addr++;
2274#endif
2275 variable = cur;
2276 goto local_variable_found;
2277 }
2278 cur = cur->next;
2279 }
2280 /*
2281 * Redo the lookup with interned strings to avoid string comparison.
2282 *
2283 * OPTIMIZE TODO: The problem here is, that if we request a
2284 * global variable, then this will be also executed.
2285 */
2286 {
2287 const xmlChar *tmpName = name, *tmpNsName = ns_uri;
2288
2289 name = xmlDictLookup(tctxt->dict, name, -1);
2290 if (ns_uri)
2291 ns_uri = xmlDictLookup(tctxt->dict, ns_uri, -1);
2292 if ((tmpName != name) || (tmpNsName != ns_uri)) {
2293 for (i = tctxt->varsNr; i > tctxt->varsBase; i--) {
2294 cur = tctxt->varsTab[i-1];
2295 if ((cur->name == name) && (cur->nameURI == ns_uri)) {
2296#if 0
2297 stack_cmp++;
2298#endif
2299 variable = cur;
2300 goto local_variable_found;
2301 }
2302 }
2303 }
2304 }
2305
2306local_variable_found:
2307
2308 if (variable) {
2309 if (variable->computed == 0) {
2310
2311#ifdef WITH_XSLT_DEBUG_VARIABLE
2313 "uncomputed variable '%s'\n", name));
2314#endif
2315 variable->value = xsltEvalVariable(tctxt, variable, NULL);
2316 variable->computed = 1;
2317 }
2318 if (variable->value != NULL) {
2319 valueObj = xmlXPathObjectCopy(variable->value);
2320 }
2321 return(valueObj);
2322 }
2323 }
2324 /*
2325 * Global variables/params --------------------------------------------
2326 */
2327 if (tctxt->globalVars) {
2328 valueObj = xsltGlobalVariableLookup(tctxt, name, ns_uri);
2329 }
2330
2331 if (valueObj == NULL) {
2332
2333#ifdef WITH_XSLT_DEBUG_VARIABLE
2335 "variable not found '%s'\n", name));
2336#endif
2337
2338 if (ns_uri) {
2339 xsltTransformError(tctxt, NULL, tctxt->inst,
2340 "Variable '{%s}%s' has not been declared.\n", ns_uri, name);
2341 } else {
2342 xsltTransformError(tctxt, NULL, tctxt->inst,
2343 "Variable '%s' has not been declared.\n", name);
2344 }
2345 } else {
2346
2347#ifdef WITH_XSLT_DEBUG_VARIABLE
2349 "found variable '%s'\n", name));
2350#endif
2351 }
2352
2353 return(valueObj);
2354}
2355
2356
Arabic default style
Definition: afstyles.h:94
struct _tree tree
#define NULL
Definition: types.h:112
void xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst)
Definition: preproc.c:2177
void xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr list, xsltTemplatePtr templ ATTRIBUTE_UNUSED, xsltStackElemPtr params)
Definition: transform.c:3273
FxCollectionEntry * cur
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint res
Definition: glext.h:9613
GLenum const GLfloat * params
Definition: glext.h:5645
GLbitfield flags
Definition: glext.h:7161
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLenum variable
Definition: glext.h:9031
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
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
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:251
#define stdout
Definition: stdio.h:99
#define stderr
Definition: stdio.h:100
void xsltFreeDocumentKeys(xsltDocumentPtr idoc)
Definition: keys.c:925
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static size_t elem
Definition: string.c:68
static unsigned __int64 next
Definition: rand_nt.c:6
XMLPUBFUN const xmlChar *XMLCALL xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:867
XMLPUBFUN int XMLCALL xmlDictReference(xmlDictPtr dict)
Definition: dict.c:647
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
XMLPUBVAR void * xmlGenericErrorContext
Definition: globals.h:353
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:250
XMLPUBVAR xmlGenericErrorFunc xmlGenericError
Definition: globals.h:337
XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata)
Definition: hash.c:406
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:322
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:176
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:476
XMLPUBFUN void XMLCALL xmlHashScan(xmlHashTablePtr table, xmlHashScanner f, void *data)
Definition: hash.c:859
XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement(const xmlDoc *doc)
XMLPUBFUN void XMLCALL xmlFreeDoc(xmlDocPtr cur)
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
xmlNode * xmlNodePtr
Definition: tree.h:488
XMLPUBFUN xmlDocPtr XMLCALL xmlNewDoc(const xmlChar *version)
xmlDoc * xmlDocPtr
Definition: tree.h:550
@ XML_NAMESPACE_DECL
Definition: tree.h:177
@ XML_ELEMENT_NODE
Definition: tree.h:160
XMLPUBFUN void XMLCALL xmlFreeNodeList(xmlNodePtr cur)
#define memset(x, y, z)
Definition: compat.h:39
Definition: tree.h:551
struct _xmlNode * next
Definition: tree.h:558
char * name
Definition: tree.h:554
void * _private
Definition: tree.h:552
void * ids
Definition: tree.h:575
struct _xmlNode * last
Definition: tree.h:556
struct _xmlNode * prev
Definition: tree.h:559
struct _xmlNode * children
Definition: tree.h:555
void * psvi
Definition: tree.h:581
struct _xmlDoc * doc
Definition: tree.h:560
Definition: tree.h:489
struct _xmlNode * children
Definition: tree.h:493
void * psvi
Definition: tree.h:505
struct _xmlDoc * doc
Definition: tree.h:498
xmlElementType type
Definition: tree.h:491
Definition: tree.h:389
xsltStylePreCompPtr comp
struct _xsltStackElem * next
const xmlChar * nameURI
const xmlChar * name
xsltStyleType type
xsltStackElemPtr variables
xsltStackElemPtr stackItems
xsltTransformState state
xsltStackElemPtr vars
xsltDocumentPtr document
xmlHashTablePtr globalVars
xsltTransformCachePtr cache
xmlNodePtr initialContextNode
xsltStylesheetPtr style
xsltStackElemPtr * varsTab
xmlXPathContextPtr xpathCtxt
const xmlChar * lasttext
char * name
Definition: compiler.c:66
Definition: name.c:39
Definition: mxnamespace.c:45
XSLTPUBFUN void XSLTCALL xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ, xsltTransformContextPtr ctxt)
Definition: pdh_main.c:94
XMLPUBFUN void XMLCALL xmlFreeIDTable(xmlIDTablePtr table)
Definition: valid.c:2756
void xsltFreeRVTs(xsltTransformContextPtr ctxt)
Definition: variables.c:416
static int xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns_uri, const xmlChar *sel, xmlNodePtr tree, xsltStylePreCompPtr comp, const xmlChar *value)
Definition: variables.c:1345
xmlXPathObjectPtr xsltXPathVariableLookup(void *ctxt, const xmlChar *name, const xmlChar *ns_uri)
Definition: variables.c:2243
xmlDocPtr xsltCreateRVT(xsltTransformContextPtr ctxt)
Definition: variables.c:44
int xsltEvalGlobalVariables(xsltTransformContextPtr ctxt)
Definition: variables.c:1260
static xmlXPathObjectPtr xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable, xsltStylePreCompPtr castedComp)
Definition: variables.c:799
static xmlXPathObjectPtr xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt)
Definition: variables.c:1032
static xmlXPathObjectPtr xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri)
Definition: variables.c:1873
int xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:99
void xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: variables.c:2024
int xsltRegisterLocalRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:138
void xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: variables.c:2087
static xsltStackElemPtr xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr castedComp, xmlNodePtr tree)
Definition: variables.c:1766
int xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED)
Definition: variables.c:187
int xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:394
void xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur)
Definition: variables.c:2191
void xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:328
static int xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI)
Definition: variables.c:696
static xsltStackElemPtr xsltCopyStackElem(xsltStackElemPtr elem)
Definition: variables.c:516
static xsltStackElemPtr xsltNewStackElem(xsltTransformContextPtr ctxt)
Definition: variables.c:480
void xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr inst)
Definition: variables.c:2149
void xsltFreeGlobalVariables(xsltTransformContextPtr ctxt)
Definition: variables.c:2227
xsltStackElemPtr xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr inst)
Definition: variables.c:1962
static xsltStackElemPtr xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI)
Definition: variables.c:627
void xsltFreeStackElemList(xsltStackElemPtr elem)
Definition: variables.c:603
int xsltQuoteOneUserParam(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *value)
Definition: variables.c:1748
static void xsltEvalGlobalVariableWrapper(void *payload, void *data, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: variables.c:1244
xmlXPathObjectPtr xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri)
Definition: variables.c:1920
static const xmlChar * xsltComputingGlobalVarMarker
Definition: variables.c:22
int xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, xmlXPathObjectPtr obj ATTRIBUTE_UNUSED)
Definition: variables.c:213
static int xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem)
Definition: variables.c:731
static int xsltRegisterVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr castedComp, xmlNodePtr tree, int isParam)
Definition: variables.c:1813
int xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val)
Definition: variables.c:237
int xsltEvalOneUserParam(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *value)
Definition: variables.c:1727
int xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params)
Definition: variables.c:1692
#define XSLT_VAR_IN_SELECT
Definition: variables.c:26
static int xsltProcessUserParamInternal(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *value, int eval)
Definition: variables.c:1438
int xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems)
Definition: variables.c:777
#define XSLT_TCTXT_VARIABLE(c)
Definition: variables.c:27
static void xsltFreeStackElemEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: variables.c:591
static void xsltFreeStackElem(xsltStackElemPtr elem)
Definition: variables.c:542
int xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params)
Definition: variables.c:1662
#define XSLT_RVT_GLOBAL
Definition: variables.h:62
#define XSLT_RVT_FUNC_RESULT
Definition: variables.h:55
#define XSLT_RVT_LOCAL
Definition: variables.h:46
int ret
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
unsigned char xmlChar
Definition: xmlstring.h:28
xsltTransformContext * xsltTransformContextPtr
@ XSLT_FUNC_VARIABLE
@ XSLT_FUNC_WITHPARAM
@ XSLT_FUNC_PARAM
#define XSLT_MARK_RES_TREE_FRAG(n)
Definition: xsltInternals.h:48
@ XSLT_STATE_STOPPED
xsltStackElem * xsltStackElemPtr
xsltStylePreComp * xsltStylePreCompPtr
void xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ)
Definition: xslt.c:4878
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:548
void * xsltGenericDebugContext
Definition: xsltutils.c:549
const xmlChar * xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix)
Definition: xsltutils.c:720
@ XSLT_DEBUG_NONE
Definition: xsltutils.h:273
@ XSLT_TRACE_VARIABLES
Definition: xsltutils.h:117
#define XSLT_TRACE(ctxt, code, call)
Definition: xsltutils.h:125