ReactOS 0.4.16-dev-2206-gc56950d
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#define IN_LIBXSLT
13#include "libxslt.h"
14
15#include <string.h>
16
17#include <libxml/xmlmemory.h>
18#include <libxml/tree.h>
19#include <libxml/valid.h>
20#include <libxml/hash.h>
21#include <libxml/xmlerror.h>
22#include <libxml/xpath.h>
25#include <libxml/dict.h>
26#include "xslt.h"
27#include "xsltInternals.h"
28#include "xsltutils.h"
29#include "variables.h"
30#include "transform.h"
31#include "imports.h"
32#include "preproc.h"
33#include "keys.h"
34
35#ifdef WITH_XSLT_DEBUG
36 #define WITH_XSLT_DEBUG_VARIABLE
37#endif
38
39#ifdef XSLT_REFACTORED
40const xmlChar *xsltDocFragFake = (const xmlChar *) " fake node libxslt";
41#endif
42
44 (const xmlChar *) " var/param being computed";
45
46#define XSLT_VAR_GLOBAL (1<<0)
47#define XSLT_VAR_IN_SELECT (1<<1)
48#define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable)
49
50/************************************************************************
51 * *
52 * Result Value Tree (Result Tree Fragment) interfaces *
53 * *
54 ************************************************************************/
64xmlDocPtr
66{
67 xmlDocPtr container;
68
69 /*
70 * Question: Why is this function public?
71 * Answer: It is called by the EXSLT module.
72 */
73 if (ctxt == NULL)
74 return(NULL);
75
76 /*
77 * Reuse a RTF from the cache if available.
78 */
79 if (ctxt->cache->RVT) {
80 container = ctxt->cache->RVT;
81 ctxt->cache->RVT = (xmlDocPtr) container->next;
82 /* clear the internal pointers */
83 container->next = NULL;
84 container->prev = NULL;
85 if (ctxt->cache->nbRVT > 0)
86 ctxt->cache->nbRVT--;
87#ifdef XSLT_DEBUG_PROFILE_CACHE
88 ctxt->cache->dbgReusedRVTs++;
89#endif
90 return(container);
91 }
92
93 container = xmlNewDoc(NULL);
94 if (container == NULL)
95 return(NULL);
96 container->dict = ctxt->dict;
99 container->doc = container;
100 container->parent = NULL;
101 return(container);
102}
103
119int
121{
122 if ((ctxt == NULL) || (RVT == NULL))
123 return(-1);
124
125 RVT->prev = NULL;
126 RVT->compression = XSLT_RVT_LOCAL;
127
128 /*
129 * We'll restrict the lifetime of user-created fragments
130 * insinde an xsl:variable and xsl:param to the lifetime of the
131 * var/param itself.
132 */
133 if (ctxt->contextVariable != NULL) {
134 RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
135 XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
136 return(0);
137 }
138
139 RVT->next = (xmlNodePtr) ctxt->tmpRVT;
140 if (ctxt->tmpRVT != NULL)
141 ctxt->tmpRVT->prev = (xmlNodePtr) RVT;
142 ctxt->tmpRVT = RVT;
143 return(0);
144}
145
158int
160 xmlDocPtr RVT)
161{
162 if ((ctxt == NULL) || (RVT == NULL))
163 return(-1);
164
165 RVT->prev = NULL;
166 RVT->compression = XSLT_RVT_LOCAL;
167
168 /*
169 * When evaluating "select" expressions of xsl:variable
170 * and xsl:param, we need to bind newly created tree fragments
171 * to the variable itself; otherwise the fragment will be
172 * freed before we leave the scope of a var.
173 */
174 if ((ctxt->contextVariable != NULL) &&
176 {
177 RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
178 XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
179 return(0);
180 }
181 /*
182 * Store the fragment in the scope of the current instruction.
183 * If not reference by a returning instruction (like EXSLT's function),
184 * then this fragment will be freed, when the instruction exits.
185 */
186 RVT->next = (xmlNodePtr) ctxt->localRVT;
187 if (ctxt->localRVT != NULL)
188 ctxt->localRVT->prev = (xmlNodePtr) RVT;
189 ctxt->localRVT = RVT;
190 return(0);
191}
192
207int
210{
212 "xsltExtensionInstructionResultFinalize is unsupported "
213 "in this release of libxslt.\n");
214 return(-1);
215}
216
233int
236 xmlXPathObjectPtr obj ATTRIBUTE_UNUSED)
237{
238 return(0);
239}
240
257int
258xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, int val) {
259 int i;
260 xmlNodePtr cur;
261 xmlDocPtr doc;
262
263 if ((ctxt == NULL) || (obj == NULL))
264 return(-1);
265
266 /*
267 * OPTIMIZE TODO: If no local variables/params and no local tree
268 * fragments were created, then we don't need to analyse the XPath
269 * objects for tree fragments.
270 */
271
272 if ((obj->type != XPATH_NODESET) && (obj->type != XPATH_XSLT_TREE))
273 return(0);
274 if ((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0))
275 return(0);
276
277 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
278 cur = obj->nodesetval->nodeTab[i];
279 if (cur->type == XML_NAMESPACE_DECL) {
280 /*
281 * The XPath module sets the owner element of a ns-node on
282 * the ns->next field.
283 */
284 if ((((xmlNsPtr) cur)->next != NULL) &&
285 (((xmlNsPtr) cur)->next->type == XML_ELEMENT_NODE))
286 {
287 cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
288 doc = cur->doc;
289 } else {
290 xsltTransformError(ctxt, NULL, ctxt->inst,
291 "Internal error in xsltFlagRVTs(): "
292 "Cannot retrieve the doc of a namespace node.\n");
293 return(-1);
294 }
295 } else {
296 doc = cur->doc;
297 }
298 if (doc == NULL) {
299 xsltTransformError(ctxt, NULL, ctxt->inst,
300 "Internal error in xsltFlagRVTs(): "
301 "Cannot retrieve the doc of a node.\n");
302 return(-1);
303 }
304 if (doc->name && (doc->name[0] == ' ') &&
305 doc->compression != XSLT_RVT_GLOBAL) {
306 /*
307 * This is a result tree fragment.
308 * We store ownership information in the @compression field.
309 * TODO: How do we know if this is a doc acquired via the
310 * document() function?
311 */
312#ifdef WITH_XSLT_DEBUG_VARIABLE
315 "Flagging RVT %p: %d -> %d\n",
316 (void *) doc, doc->compression, val));
317#endif
318
319 if (val == XSLT_RVT_LOCAL) {
320 if (doc->compression == XSLT_RVT_FUNC_RESULT)
321 doc->compression = XSLT_RVT_LOCAL;
322 } else if (val == XSLT_RVT_GLOBAL) {
323 if (doc->compression != XSLT_RVT_LOCAL) {
325 "xsltFlagRVTs: Invalid transition %d => GLOBAL\n",
326 doc->compression);
327 doc->compression = XSLT_RVT_GLOBAL;
328 return(-1);
329 }
330
331 /* Will be registered as persistant in xsltReleaseLocalRVTs. */
332 doc->compression = XSLT_RVT_GLOBAL;
333 } else if (val == XSLT_RVT_FUNC_RESULT) {
334 doc->compression = val;
335 }
336 }
337 }
338
339 return(0);
340}
341
350void
352{
353 if (RVT == NULL)
354 return;
355
356 if (ctxt && (ctxt->cache->nbRVT < 40)) {
357 /*
358 * Store the Result Tree Fragment.
359 * Free the document info.
360 */
361 if (RVT->_private != NULL) {
362 xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);
363 xmlFree(RVT->_private);
364 RVT->_private = NULL;
365 }
366 /*
367 * Clear the document tree.
368 */
369 if (RVT->children != NULL) {
370 xmlFreeNodeList(RVT->children);
371 RVT->children = NULL;
372 RVT->last = NULL;
373 }
374 if (RVT->ids != NULL) {
375 xmlFreeIDTable((xmlIDTablePtr) RVT->ids);
376 RVT->ids = NULL;
377 }
378
379 /*
380 * Reset the ownership information.
381 */
382 RVT->compression = 0;
383
384 RVT->next = (xmlNodePtr) ctxt->cache->RVT;
385 ctxt->cache->RVT = RVT;
386
387 ctxt->cache->nbRVT++;
388
389#ifdef XSLT_DEBUG_PROFILE_CACHE
390 ctxt->cache->dbgCachedRVTs++;
391#endif
392 return;
393 }
394 /*
395 * Free it.
396 */
397 if (RVT->_private != NULL) {
398 xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);
399 xmlFree(RVT->_private);
400 }
401 xmlFreeDoc(RVT);
402}
403
416int
418{
419 if ((ctxt == NULL) || (RVT == NULL)) return(-1);
420
421 RVT->compression = XSLT_RVT_GLOBAL;
422 RVT->prev = NULL;
423 RVT->next = (xmlNodePtr) ctxt->persistRVT;
424 if (ctxt->persistRVT != NULL)
425 ctxt->persistRVT->prev = (xmlNodePtr) RVT;
426 ctxt->persistRVT = RVT;
427 return(0);
428}
429
438void
440{
441 xmlDocPtr cur, next;
442
443 if (ctxt == NULL)
444 return;
445 /*
446 * Local fragments.
447 */
448 cur = ctxt->localRVT;
449 while (cur != NULL) {
450 next = (xmlDocPtr) cur->next;
451 if (cur->_private != NULL) {
452 xsltFreeDocumentKeys(cur->_private);
453 xmlFree(cur->_private);
454 }
455 xmlFreeDoc(cur);
456 cur = next;
457 }
458 ctxt->localRVT = NULL;
459 /*
460 * User-created per-template fragments.
461 */
462 cur = ctxt->tmpRVT;
463 while (cur != NULL) {
464 next = (xmlDocPtr) cur->next;
465 if (cur->_private != NULL) {
466 xsltFreeDocumentKeys(cur->_private);
467 xmlFree(cur->_private);
468 }
469 xmlFreeDoc(cur);
470 cur = next;
471 }
472 ctxt->tmpRVT = NULL;
473 /*
474 * Global fragments.
475 */
476 cur = ctxt->persistRVT;
477 while (cur != NULL) {
478 next = (xmlDocPtr) cur->next;
479 if (cur->_private != NULL) {
480 xsltFreeDocumentKeys(cur->_private);
481 xmlFree(cur->_private);
482 }
483 xmlFreeDoc(cur);
484 cur = next;
485 }
486 ctxt->persistRVT = NULL;
487}
488
489/************************************************************************
490 * *
491 * Module interfaces *
492 * *
493 ************************************************************************/
494
502static xsltStackElemPtr
504{
506 /*
507 * Reuse a stack item from the cache if available.
508 */
509 if (ctxt && ctxt->cache->stackItems) {
510 ret = ctxt->cache->stackItems;
511 ctxt->cache->stackItems = ret->next;
512 ret->next = NULL;
513 ctxt->cache->nbStackItems--;
514#ifdef XSLT_DEBUG_PROFILE_CACHE
515 ctxt->cache->dbgReusedVars++;
516#endif
517 return(ret);
518 }
520 if (ret == NULL) {
522 "xsltNewStackElem : malloc failed\n");
523 return(NULL);
524 }
525 memset(ret, 0, sizeof(xsltStackElem));
526 ret->context = ctxt;
527 return(ret);
528}
529
538static xsltStackElemPtr
541
543 if (cur == NULL) {
545 "xsltCopyStackElem : malloc failed\n");
546 return(NULL);
547 }
548 memset(cur, 0, sizeof(xsltStackElem));
549 cur->context = elem->context;
550 cur->name = elem->name;
551 cur->nameURI = elem->nameURI;
552 cur->select = elem->select;
553 cur->tree = elem->tree;
554 cur->comp = elem->comp;
555 return(cur);
556}
557
564static void
566 if (elem == NULL)
567 return;
568 if (elem->value != NULL)
569 xmlXPathFreeObject(elem->value);
570 /*
571 * Release the list of temporary Result Tree Fragments.
572 */
573 if (elem->context) {
574 xmlDocPtr cur;
575
576 while (elem->fragment != NULL) {
577 cur = elem->fragment;
578 elem->fragment = (xmlDocPtr) cur->next;
579
580 if (cur->compression == XSLT_RVT_LOCAL) {
581 xsltReleaseRVT(elem->context, cur);
582 } else if (cur->compression == XSLT_RVT_FUNC_RESULT) {
583 xsltRegisterLocalRVT(elem->context, cur);
584 cur->compression = XSLT_RVT_FUNC_RESULT;
585 } else {
587 "xsltFreeStackElem: Unexpected RVT flag %d\n",
588 cur->compression);
589 }
590 }
591 }
592 /*
593 * Cache or free the variable structure.
594 */
595 if (elem->context && (elem->context->cache->nbStackItems < 50)) {
596 /*
597 * Store the item in the cache.
598 */
599 xsltTransformContextPtr ctxt = elem->context;
600 memset(elem, 0, sizeof(xsltStackElem));
601 elem->context = ctxt;
602 elem->next = ctxt->cache->stackItems;
603 ctxt->cache->stackItems = elem;
604 ctxt->cache->nbStackItems++;
605#ifdef XSLT_DEBUG_PROFILE_CACHE
606 ctxt->cache->dbgCachedVars++;
607#endif
608 return;
609 }
610 xmlFree(elem);
611}
612
613static void
616}
617
618
625void
628
629 while (elem != NULL) {
630 next = elem->next;
632 elem = next;
633 }
634}
635
644#if 0 /* TODO: Those seem to have been used for debugging. */
645static int stack_addr = 0;
646static int stack_cmp = 0;
647#endif
648
649static xsltStackElemPtr
651 const xmlChar *nameURI) {
652 int i;
654
655 if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))
656 return(NULL);
657
658 /*
659 * Do the lookup from the top of the stack, but
660 * don't use params being computed in a call-param
661 * First lookup expects the variable name and URI to
662 * come from the disctionnary and hence pointer comparison.
663 */
664 for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
665 cur = ctxt->varsTab[i-1];
666 while (cur != NULL) {
667 if ((cur->name == name) && (cur->nameURI == nameURI)) {
668#if 0
669 stack_addr++;
670#endif
671 return(cur);
672 }
673 cur = cur->next;
674 }
675 }
676
677 /*
678 * Redo the lookup with interned string compares
679 * to avoid string compares.
680 */
681 name = xmlDictLookup(ctxt->dict, name, -1);
682 if (nameURI != NULL)
683 nameURI = xmlDictLookup(ctxt->dict, nameURI, -1);
684
685 for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
686 cur = ctxt->varsTab[i-1];
687 while (cur != NULL) {
688 if ((cur->name == name) && (cur->nameURI == nameURI)) {
689#if 0
690 stack_cmp++;
691#endif
692 return(cur);
693 }
694 cur = cur->next;
695 }
696 }
697
698 return(NULL);
699}
700
701#ifdef XSLT_REFACTORED
702#else
703
718static int
720 const xmlChar *nameURI) {
722
723 if ((ctxt == NULL) || (name == NULL))
724 return(-1);
725
726 cur = xsltStackLookup(ctxt, name, nameURI);
727 if (cur == NULL)
728 return(0);
729 if (cur->comp != NULL) {
730 if (cur->comp->type == XSLT_FUNC_WITHPARAM)
731 return(3);
732 else if (cur->comp->type == XSLT_FUNC_PARAM)
733 return(2);
734 }
735
736 return(1);
737}
738
739#endif /* XSLT_REFACTORED */
740
753static int
755{
756 if ((ctxt == NULL) || (elem == NULL))
757 return(-1);
758
759 do {
760 if (ctxt->varsNr >= ctxt->varsMax) {
761 xsltStackElemPtr *tmp;
762 int newMax = ctxt->varsMax == 0 ? 10 : 2 * ctxt->varsMax;
763
764 tmp = (xsltStackElemPtr *) xmlRealloc(ctxt->varsTab,
765 newMax * sizeof(*tmp));
766 if (tmp == NULL) {
767 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
768 return (-1);
769 }
770 ctxt->varsTab = tmp;
771 ctxt->varsMax = newMax;
772 }
773 ctxt->varsTab[ctxt->varsNr++] = elem;
774 ctxt->vars = elem;
775
776 elem = elem->next;
777 } while (elem != NULL);
778
779 return(0);
780}
781
791int
793{
794 return(xsltAddStackElem(ctxt, elems));
795}
796
797/************************************************************************
798 * *
799 * Module interfaces *
800 * *
801 ************************************************************************/
802
813static xmlXPathObjectPtr
815 xsltStylePreCompPtr castedComp)
816{
817#ifdef XSLT_REFACTORED
818 xsltStyleItemVariablePtr comp =
819 (xsltStyleItemVariablePtr) castedComp;
820#else
821 xsltStylePreCompPtr comp = castedComp;
822#endif
823 xmlXPathObjectPtr result = NULL;
824 xmlNodePtr oldInst;
825
826 if ((ctxt == NULL) || (variable == NULL))
827 return(NULL);
828
829 /*
830 * A variable or parameter are evaluated on demand; thus the
831 * context (of XSLT and XPath) need to be temporarily adjusted and
832 * restored on exit.
833 */
834 oldInst = ctxt->inst;
835
836#ifdef WITH_XSLT_DEBUG_VARIABLE
838 "Evaluating variable '%s'\n", variable->name));
839#endif
840 if (variable->select != NULL) {
841 xmlXPathCompExprPtr xpExpr = NULL;
842 xmlDocPtr oldXPDoc;
843 xmlNodePtr oldXPContextNode;
844 int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
845 xmlNsPtr *oldXPNamespaces;
846 xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
847 xsltStackElemPtr oldVar = ctxt->contextVariable;
848
849 if ((comp != NULL) && (comp->comp != NULL)) {
850 xpExpr = comp->comp;
851 } else {
852 xpExpr = xmlXPathCtxtCompile(ctxt->xpathCtxt, variable->select);
853 }
854 if (xpExpr == NULL)
855 return(NULL);
856 /*
857 * Save context states.
858 */
859 oldXPDoc = xpctxt->doc;
860 oldXPContextNode = xpctxt->node;
861 oldXPProximityPosition = xpctxt->proximityPosition;
862 oldXPContextSize = xpctxt->contextSize;
863 oldXPNamespaces = xpctxt->namespaces;
864 oldXPNsNr = xpctxt->nsNr;
865
866 xpctxt->node = ctxt->node;
867 /*
868 * OPTIMIZE TODO: Lame try to set the context doc.
869 * Get rid of this somehow in xpath.c.
870 */
871 if ((ctxt->node->type != XML_NAMESPACE_DECL) &&
872 ctxt->node->doc)
873 xpctxt->doc = ctxt->node->doc;
874 /*
875 * BUG TODO: The proximity position and the context size will
876 * potentially be wrong.
877 * Example:
878 * <xsl:template select="foo">
879 * <xsl:variable name="pos" select="position()"/>
880 * <xsl:for-each select="bar">
881 * <xsl:value-of select="$pos"/>
882 * </xsl:for-each>
883 * </xsl:template>
884 * Here the proximity position and context size are changed
885 * to the context of <xsl:for-each select="bar">, but
886 * the variable needs to be evaluated in the context of
887 * <xsl:template select="foo">.
888 */
889 if (comp != NULL) {
890
891#ifdef XSLT_REFACTORED
892 if (comp->inScopeNs != NULL) {
893 xpctxt->namespaces = comp->inScopeNs->list;
894 xpctxt->nsNr = comp->inScopeNs->xpathNumber;
895 } else {
896 xpctxt->namespaces = NULL;
897 xpctxt->nsNr = 0;
898 }
899#else
900 xpctxt->namespaces = comp->nsList;
901 xpctxt->nsNr = comp->nsNr;
902#endif
903 } else {
904 xpctxt->namespaces = NULL;
905 xpctxt->nsNr = 0;
906 }
907
908 /*
909 * We need to mark that we are "selecting" a var's value;
910 * if any tree fragments are created inside the expression,
911 * then those need to be stored inside the variable; otherwise
912 * we'll eventually free still referenced fragments, before
913 * we leave the scope of the variable.
914 */
917
918 result = xmlXPathCompiledEval(xpExpr, xpctxt);
919
921 /*
922 * Restore Context states.
923 */
924 ctxt->contextVariable = oldVar;
925
926 xpctxt->doc = oldXPDoc;
927 xpctxt->node = oldXPContextNode;
928 xpctxt->contextSize = oldXPContextSize;
929 xpctxt->proximityPosition = oldXPProximityPosition;
930 xpctxt->namespaces = oldXPNamespaces;
931 xpctxt->nsNr = oldXPNsNr;
932
933 if ((comp == NULL) || (comp->comp == NULL))
934 xmlXPathFreeCompExpr(xpExpr);
935 if (result == NULL) {
937 (comp != NULL) ? comp->inst : NULL,
938 "Failed to evaluate the expression of variable '%s'.\n",
939 variable->name);
941
942#ifdef WITH_XSLT_DEBUG_VARIABLE
943#ifdef LIBXML_DEBUG_ENABLED
944 } else {
947 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
948 result, 0);
949#endif
950#endif
951 }
952 } else {
953 if (variable->tree == NULL) {
954 result = xmlXPathNewCString("");
955 } else {
956 if (variable->tree) {
957 xmlDocPtr container;
958 xmlNodePtr oldInsert;
959 xmlDocPtr oldOutput;
960 const xmlChar *oldLastText;
961 int oldLastTextSize, oldLastTextUse;
962 xsltStackElemPtr oldVar = ctxt->contextVariable;
963
964 /*
965 * Generate a result tree fragment.
966 */
967 container = xsltCreateRVT(ctxt);
968 if (container == NULL)
969 goto error;
970 /*
971 * NOTE: Local Result Tree Fragments of params/variables
972 * are not registered globally anymore; the life-time
973 * is not directly dependant of the param/variable itself.
974 *
975 * OLD: xsltRegisterTmpRVT(ctxt, container);
976 */
977 /*
978 * Attach the Result Tree Fragment to the variable;
979 * when the variable is freed, it will also free
980 * the Result Tree Fragment.
981 */
982 variable->fragment = container;
983 container->compression = XSLT_RVT_LOCAL;
984
985 oldOutput = ctxt->output;
986 oldInsert = ctxt->insert;
987 oldLastText = ctxt->lasttext;
988 oldLastTextSize = ctxt->lasttsize;
989 oldLastTextUse = ctxt->lasttuse;
990
991 ctxt->output = container;
992 ctxt->insert = (xmlNodePtr) container;
994 /*
995 * Process the sequence constructor (variable->tree).
996 * The resulting tree will be held by @container.
997 */
998 xsltApplyOneTemplate(ctxt, ctxt->node, variable->tree,
999 NULL, NULL);
1000
1001 ctxt->contextVariable = oldVar;
1002 ctxt->insert = oldInsert;
1003 ctxt->output = oldOutput;
1004 ctxt->lasttext = oldLastText;
1005 ctxt->lasttsize = oldLastTextSize;
1006 ctxt->lasttuse = oldLastTextUse;
1007
1008 result = xmlXPathNewValueTree((xmlNodePtr) container);
1009 }
1010 if (result == NULL) {
1011 result = xmlXPathNewCString("");
1012 } else {
1013 /*
1014 * This stops older libxml2 versions from freeing the nodes
1015 * in the tree.
1016 */
1017 result->boolval = 0;
1018 }
1019#ifdef WITH_XSLT_DEBUG_VARIABLE
1020#ifdef LIBXML_DEBUG_ENABLED
1021
1024 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
1025 result, 0);
1026#endif
1027#endif
1028 }
1029 }
1030
1031error:
1032 ctxt->inst = oldInst;
1033 return(result);
1034}
1035
1046static xmlXPathObjectPtr
1048{
1049 xmlXPathObjectPtr result = NULL;
1050 xmlNodePtr oldInst;
1051 const xmlChar* oldVarName;
1052
1053#ifdef XSLT_REFACTORED
1054 xsltStyleBasicItemVariablePtr comp;
1055#else
1057#endif
1058
1059 if ((ctxt == NULL) || (elem == NULL))
1060 return(NULL);
1061 if (elem->computed)
1062 return(elem->value);
1063
1064
1065#ifdef WITH_XSLT_DEBUG_VARIABLE
1067 "Evaluating global variable %s\n", elem->name));
1068#endif
1069
1070#ifdef WITH_DEBUGGER
1071 if ((ctxt->debugStatus != XSLT_DEBUG_NONE) &&
1072 elem->comp && elem->comp->inst)
1073 xslHandleDebugger(elem->comp->inst, NULL, NULL, ctxt);
1074#endif
1075
1076 oldInst = ctxt->inst;
1077#ifdef XSLT_REFACTORED
1078 comp = (xsltStyleBasicItemVariablePtr) elem->comp;
1079#else
1080 comp = elem->comp;
1081#endif
1082 oldVarName = elem->name;
1084 /*
1085 * OPTIMIZE TODO: We should consider instantiating global vars/params
1086 * on-demand. The vars/params don't need to be evaluated if never
1087 * called; and in the case of global params, if values for such params
1088 * are provided by the user.
1089 */
1090 if (elem->select != NULL) {
1091 xmlXPathCompExprPtr xpExpr = NULL;
1092 xmlDocPtr oldXPDoc;
1093 xmlNodePtr oldXPContextNode;
1094 int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
1095 xmlNsPtr *oldXPNamespaces;
1096 xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
1097
1098 if ((comp != NULL) && (comp->comp != NULL)) {
1099 xpExpr = comp->comp;
1100 } else {
1101 xpExpr = xmlXPathCtxtCompile(ctxt->xpathCtxt, elem->select);
1102 }
1103 if (xpExpr == NULL)
1104 goto error;
1105
1106
1107 if (comp != NULL)
1108 ctxt->inst = comp->inst;
1109 else
1110 ctxt->inst = NULL;
1111 /*
1112 * SPEC XSLT 1.0:
1113 * "At top-level, the expression or template specifying the
1114 * variable value is evaluated with the same context as that used
1115 * to process the root node of the source document: the current
1116 * node is the root node of the source document and the current
1117 * node list is a list containing just the root node of the source
1118 * document."
1119 */
1120 /*
1121 * Save context states.
1122 */
1123 oldXPDoc = xpctxt->doc;
1124 oldXPContextNode = xpctxt->node;
1125 oldXPProximityPosition = xpctxt->proximityPosition;
1126 oldXPContextSize = xpctxt->contextSize;
1127 oldXPNamespaces = xpctxt->namespaces;
1128 oldXPNsNr = xpctxt->nsNr;
1129
1130 xpctxt->node = ctxt->initialContextNode;
1131 xpctxt->doc = ctxt->initialContextDoc;
1132 xpctxt->contextSize = 1;
1133 xpctxt->proximityPosition = 1;
1134
1135 if (comp != NULL) {
1136
1137#ifdef XSLT_REFACTORED
1138 if (comp->inScopeNs != NULL) {
1139 xpctxt->namespaces = comp->inScopeNs->list;
1140 xpctxt->nsNr = comp->inScopeNs->xpathNumber;
1141 } else {
1142 xpctxt->namespaces = NULL;
1143 xpctxt->nsNr = 0;
1144 }
1145#else
1146 xpctxt->namespaces = comp->nsList;
1147 xpctxt->nsNr = comp->nsNr;
1148#endif
1149 } else {
1150 xpctxt->namespaces = NULL;
1151 xpctxt->nsNr = 0;
1152 }
1153
1154 result = xmlXPathCompiledEval(xpExpr, xpctxt);
1155
1156 /*
1157 * Restore Context states.
1158 */
1159 xpctxt->doc = oldXPDoc;
1160 xpctxt->node = oldXPContextNode;
1161 xpctxt->contextSize = oldXPContextSize;
1162 xpctxt->proximityPosition = oldXPProximityPosition;
1163 xpctxt->namespaces = oldXPNamespaces;
1164 xpctxt->nsNr = oldXPNsNr;
1165
1166 if ((comp == NULL) || (comp->comp == NULL))
1167 xmlXPathFreeCompExpr(xpExpr);
1168 if (result == NULL) {
1169 if (comp == NULL)
1171 "Evaluating global variable %s failed\n", elem->name);
1172 else
1173 xsltTransformError(ctxt, NULL, comp->inst,
1174 "Evaluating global variable %s failed\n", elem->name);
1175 ctxt->state = XSLT_STATE_STOPPED;
1176 goto error;
1177 }
1178
1179 /*
1180 * Mark all RVTs that are referenced from result as part
1181 * of this variable so they won't be freed too early.
1182 */
1184
1185#ifdef WITH_XSLT_DEBUG_VARIABLE
1186#ifdef LIBXML_DEBUG_ENABLED
1189 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
1190 result, 0);
1191#endif
1192#endif
1193 } else {
1194 if (elem->tree == NULL) {
1195 result = xmlXPathNewCString("");
1196 } else {
1197 xmlDocPtr container;
1198 xmlNodePtr oldInsert;
1199 xmlDocPtr oldOutput, oldXPDoc;
1200 /*
1201 * Generate a result tree fragment.
1202 */
1203 container = xsltCreateRVT(ctxt);
1204 if (container == NULL)
1205 goto error;
1206 /*
1207 * Let the lifetime of the tree fragment be handled by
1208 * the Libxslt's garbage collector.
1209 */
1211
1212 oldOutput = ctxt->output;
1213 oldInsert = ctxt->insert;
1214
1215 oldXPDoc = ctxt->xpathCtxt->doc;
1216
1217 ctxt->output = container;
1218 ctxt->insert = (xmlNodePtr) container;
1219
1220 ctxt->xpathCtxt->doc = ctxt->initialContextDoc;
1221 /*
1222 * Process the sequence constructor.
1223 */
1224 xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
1225
1226 ctxt->xpathCtxt->doc = oldXPDoc;
1227
1228 ctxt->insert = oldInsert;
1229 ctxt->output = oldOutput;
1230
1231 result = xmlXPathNewValueTree((xmlNodePtr) container);
1232 if (result == NULL) {
1233 result = xmlXPathNewCString("");
1234 } else {
1235 /*
1236 * This stops older libxml2 versions from freeing the nodes
1237 * in the tree.
1238 */
1239 result->boolval = 0;
1240 }
1241#ifdef WITH_XSLT_DEBUG_VARIABLE
1242#ifdef LIBXML_DEBUG_ENABLED
1245 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
1246 result, 0);
1247#endif
1248#endif
1249 }
1250 }
1251
1252error:
1253 elem->name = oldVarName;
1254 ctxt->inst = oldInst;
1255 if (result != NULL) {
1256 elem->value = result;
1257 elem->computed = 1;
1258 }
1259 return(result);
1260}
1261
1262static void
1264 const xmlChar *name ATTRIBUTE_UNUSED) {
1267}
1268
1278int
1282
1283 if ((ctxt == NULL) || (ctxt->document == NULL))
1284 return(-1);
1285
1286#ifdef WITH_XSLT_DEBUG_VARIABLE
1288 "Registering global variables\n"));
1289#endif
1290 /*
1291 * Walk the list from the stylesheets and populate the hash table
1292 */
1293 style = ctxt->style;
1294 while (style != NULL) {
1295 elem = style->variables;
1296
1297#ifdef WITH_XSLT_DEBUG_VARIABLE
1298 if ((style->doc != NULL) && (style->doc->URL != NULL)) {
1300 "Registering global variables from %s\n",
1301 style->doc->URL));
1302 }
1303#endif
1304
1305 while (elem != NULL) {
1306 xsltStackElemPtr def;
1307
1308 /*
1309 * Global variables are stored in the variables pool.
1310 */
1311 def = (xsltStackElemPtr)
1313 elem->name, elem->nameURI);
1314 if (def == NULL) {
1315
1316 def = xsltCopyStackElem(elem);
1317 if (xmlHashAddEntry2(ctxt->globalVars,
1318 elem->name, elem->nameURI, def) < 0) {
1320 "hash update failed\n");
1321 xsltFreeStackElem(def);
1322 return(-1);
1323 }
1324 } else if ((elem->comp != NULL) &&
1325 (elem->comp->type == XSLT_FUNC_VARIABLE)) {
1326 /*
1327 * Redefinition of variables from a different stylesheet
1328 * should not generate a message.
1329 */
1330 if ((elem->comp->inst != NULL) &&
1331 (def->comp != NULL) && (def->comp->inst != NULL) &&
1332 (elem->comp->inst->doc == def->comp->inst->doc))
1333 {
1334 xsltTransformError(ctxt, style, elem->comp->inst,
1335 "Global variable %s already defined\n", elem->name);
1336 if (style != NULL) style->errors++;
1337 }
1338 }
1339 elem = elem->next;
1340 }
1341
1343 }
1344
1345 /*
1346 * This part does the actual evaluation
1347 */
1349
1350 return(0);
1351}
1352
1368static int
1370 const xmlChar *ns_uri, const xmlChar *sel,
1371 xmlNodePtr tree, xsltStylePreCompPtr comp,
1372 const xmlChar *value) {
1374 if (style == NULL)
1375 return(-1);
1376 if (name == NULL)
1377 return(-1);
1378 if (comp == NULL)
1379 return(-1);
1380
1381#ifdef WITH_XSLT_DEBUG_VARIABLE
1382 if (comp->type == XSLT_FUNC_PARAM)
1384 "Defining global param %s\n", name);
1385 else
1387 "Defining global variable %s\n", name);
1388#endif
1389
1391 if (elem == NULL)
1392 return(-1);
1393 elem->comp = comp;
1394 elem->name = xmlDictLookup(style->dict, name, -1);
1395 elem->select = xmlDictLookup(style->dict, sel, -1);
1396 if (ns_uri)
1397 elem->nameURI = xmlDictLookup(style->dict, ns_uri, -1);
1398 elem->tree = tree;
1399 tmp = style->variables;
1400 if (tmp == NULL) {
1401 elem->next = NULL;
1402 style->variables = elem;
1403 } else {
1404 while (tmp != NULL) {
1405 if ((elem->comp->type == XSLT_FUNC_VARIABLE) &&
1406 (tmp->comp->type == XSLT_FUNC_VARIABLE) &&
1407 (xmlStrEqual(elem->name, tmp->name)) &&
1408 ((elem->nameURI == tmp->nameURI) ||
1409 (xmlStrEqual(elem->nameURI, tmp->nameURI))))
1410 {
1412 "redefinition of global variable %s\n", elem->name);
1413 style->errors++;
1414 }
1415 if (tmp->next == NULL)
1416 break;
1417 tmp = tmp->next;
1418 }
1419 elem->next = NULL;
1420 tmp->next = elem;
1421 }
1422 if (value != NULL) {
1423 elem->computed = 1;
1424 elem->value = xmlXPathNewString(value);
1425 }
1426 return(0);
1427}
1428
1460static
1461int
1463 const xmlChar * name,
1464 const xmlChar * value,
1465 int eval) {
1466
1468 const xmlChar *prefix;
1469 const xmlChar *href;
1470 xmlXPathCompExprPtr xpExpr;
1471 xmlXPathObjectPtr result;
1472
1474 int res;
1475 void *res_ptr;
1476
1477 if (ctxt == NULL)
1478 return(-1);
1479 if (name == NULL)
1480 return(0);
1481 if (value == NULL)
1482 return(0);
1483
1484 style = ctxt->style;
1485
1486#ifdef WITH_XSLT_DEBUG_VARIABLE
1488 "Evaluating user parameter %s=%s\n", name, value));
1489#endif
1490
1491 /*
1492 * Name lookup
1493 */
1494 href = NULL;
1495
1496 if (name[0] == '{') {
1497 int len = 0;
1498
1499 while ((name[len] != 0) && (name[len] != '}')) len++;
1500 if (name[len] == 0) {
1502 "user param : malformed parameter name : %s\n", name);
1503 } else {
1504 href = xmlDictLookup(ctxt->dict, &name[1], len-1);
1505 name = xmlDictLookup(ctxt->dict, &name[len + 1], -1);
1506 }
1507 }
1508 else {
1509 name = xsltSplitQName(ctxt->dict, name, &prefix);
1510 if (prefix != NULL) {
1511 xmlNsPtr ns;
1512
1513 ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
1514 prefix);
1515 if (ns == NULL) {
1517 "user param : no namespace bound to prefix %s\n", prefix);
1518 href = NULL;
1519 } else {
1520 href = ns->href;
1521 }
1522 }
1523 }
1524
1525 if (name == NULL)
1526 return (-1);
1527
1528 res_ptr = xmlHashLookup2(ctxt->globalVars, name, href);
1529 if (res_ptr != 0) {
1531 "Global parameter %s already defined\n", name);
1532 }
1533 if (ctxt->globalVars == NULL)
1534 ctxt->globalVars = xmlHashCreate(20);
1535
1536 /*
1537 * do not overwrite variables with parameters from the command line
1538 */
1539 while (style != NULL) {
1540 elem = ctxt->style->variables;
1541 while (elem != NULL) {
1542 if ((elem->comp != NULL) &&
1543 (elem->comp->type == XSLT_FUNC_VARIABLE) &&
1544 (xmlStrEqual(elem->name, name)) &&
1545 (xmlStrEqual(elem->nameURI, href))) {
1546 return(0);
1547 }
1548 elem = elem->next;
1549 }
1551 }
1552 style = ctxt->style;
1553 elem = NULL;
1554
1555 /*
1556 * Do the evaluation if @eval is non-zero.
1557 */
1558
1559 result = NULL;
1560 if (eval != 0) {
1561 xpExpr = xmlXPathCtxtCompile(ctxt->xpathCtxt, value);
1562 if (xpExpr != NULL) {
1563 xmlDocPtr oldXPDoc;
1564 xmlNodePtr oldXPContextNode;
1565 int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
1566 xmlNsPtr *oldXPNamespaces;
1567 xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
1568
1569 /*
1570 * Save context states.
1571 */
1572 oldXPDoc = xpctxt->doc;
1573 oldXPContextNode = xpctxt->node;
1574 oldXPProximityPosition = xpctxt->proximityPosition;
1575 oldXPContextSize = xpctxt->contextSize;
1576 oldXPNamespaces = xpctxt->namespaces;
1577 oldXPNsNr = xpctxt->nsNr;
1578
1579 /*
1580 * SPEC XSLT 1.0:
1581 * "At top-level, the expression or template specifying the
1582 * variable value is evaluated with the same context as that used
1583 * to process the root node of the source document: the current
1584 * node is the root node of the source document and the current
1585 * node list is a list containing just the root node of the source
1586 * document."
1587 */
1588 xpctxt->doc = ctxt->initialContextDoc;
1589 xpctxt->node = ctxt->initialContextNode;
1590 xpctxt->contextSize = 1;
1591 xpctxt->proximityPosition = 1;
1592 /*
1593 * There is really no in scope namespace for parameters on the
1594 * command line.
1595 */
1596 xpctxt->namespaces = NULL;
1597 xpctxt->nsNr = 0;
1598
1599 result = xmlXPathCompiledEval(xpExpr, xpctxt);
1600
1601 /*
1602 * Restore Context states.
1603 */
1604 xpctxt->doc = oldXPDoc;
1605 xpctxt->node = oldXPContextNode;
1606 xpctxt->contextSize = oldXPContextSize;
1607 xpctxt->proximityPosition = oldXPProximityPosition;
1608 xpctxt->namespaces = oldXPNamespaces;
1609 xpctxt->nsNr = oldXPNsNr;
1610
1611 xmlXPathFreeCompExpr(xpExpr);
1612 }
1613 if (result == NULL) {
1615 "Evaluating user parameter %s failed\n", name);
1616 ctxt->state = XSLT_STATE_STOPPED;
1617 return(-1);
1618 }
1619 }
1620
1621 /*
1622 * If @eval is 0 then @value is to be taken literally and result is NULL
1623 *
1624 * If @eval is not 0, then @value is an XPath expression and has been
1625 * successfully evaluated and result contains the resulting value and
1626 * is not NULL.
1627 *
1628 * Now create an xsltStackElemPtr for insertion into the context's
1629 * global variable/parameter hash table.
1630 */
1631
1632#ifdef WITH_XSLT_DEBUG_VARIABLE
1633#ifdef LIBXML_DEBUG_ENABLED
1636 xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
1637 result, 0);
1638#endif
1639#endif
1640
1642 if (elem != NULL) {
1643 elem->name = name;
1644 elem->select = xmlDictLookup(ctxt->dict, value, -1);
1645 if (href != NULL)
1646 elem->nameURI = xmlDictLookup(ctxt->dict, href, -1);
1647 elem->tree = NULL;
1648 elem->computed = 1;
1649 if (eval == 0) {
1650 elem->value = xmlXPathNewString(value);
1651 }
1652 else {
1653 elem->value = result;
1654 }
1655 }
1656
1657 /*
1658 * Global parameters are stored in the XPath context variables pool.
1659 */
1660
1661 res = xmlHashAddEntry2(ctxt->globalVars, name, href, elem);
1662 if (res != 0) {
1665 "Global parameter %s already defined\n", name);
1666 }
1667 return(0);
1668}
1669
1685int
1687 size_t indx = 0;
1688 const xmlChar *name;
1689 const xmlChar *value;
1690
1691 if (params == NULL)
1692 return(0);
1693 while (params[indx] != NULL) {
1694 name = (const xmlChar *) params[indx++];
1695 value = (const xmlChar *) params[indx++];
1696 if (xsltEvalOneUserParam(ctxt, name, value) != 0)
1697 return(-1);
1698 }
1699 return 0;
1700}
1701
1715int
1717 size_t indx = 0;
1718 const xmlChar *name;
1719 const xmlChar *value;
1720
1721 if (params == NULL)
1722 return(0);
1723 while (params[indx] != NULL) {
1724 name = (const xmlChar *) params[indx++];
1725 value = (const xmlChar *) params[indx++];
1726 if (xsltQuoteOneUserParam(ctxt, name, value) != 0)
1727 return(-1);
1728 }
1729 return 0;
1730}
1731
1750int
1752 const xmlChar * name,
1753 const xmlChar * value) {
1755 1 /* xpath eval ? */);
1756}
1757
1771int
1773 const xmlChar * name,
1774 const xmlChar * value) {
1776 0 /* xpath eval ? */);
1777}
1778
1789static xsltStackElemPtr
1791 xsltStylePreCompPtr castedComp,
1792 xmlNodePtr tree)
1793{
1794#ifdef XSLT_REFACTORED
1795 xsltStyleBasicItemVariablePtr comp =
1796 (xsltStyleBasicItemVariablePtr) castedComp;
1797#else
1798 xsltStylePreCompPtr comp = castedComp;
1799#endif
1801
1802#ifdef WITH_XSLT_DEBUG_VARIABLE
1804 "Building variable %s", comp->name));
1805 if (comp->select != NULL)
1807 " select %s", comp->select));
1809#endif
1810
1811 elem = xsltNewStackElem(ctxt);
1812 if (elem == NULL)
1813 return(NULL);
1814 elem->comp = (xsltStylePreCompPtr) comp;
1815 elem->name = comp->name;
1816 elem->select = comp->select;
1817 elem->nameURI = comp->ns;
1818 elem->tree = tree;
1819 elem->value = xsltEvalVariable(ctxt, elem,
1820 (xsltStylePreCompPtr) comp);
1821 elem->computed = 1;
1822 return(elem);
1823}
1824
1836static int
1838 xsltStylePreCompPtr castedComp,
1839 xmlNodePtr tree, int isParam)
1840{
1841#ifdef XSLT_REFACTORED
1842 xsltStyleBasicItemVariablePtr comp =
1843 (xsltStyleBasicItemVariablePtr) castedComp;
1844#else
1845 xsltStylePreCompPtr comp = castedComp;
1846 int present;
1847#endif
1849
1850#ifdef XSLT_REFACTORED
1851 /*
1852 * REFACTORED NOTE: Redefinitions of vars/params are checked
1853 * at compilation time in the refactored code.
1854 * xsl:with-param parameters are checked in xsltApplyXSLTTemplate().
1855 */
1856#else
1857 present = xsltCheckStackElem(ctxt, comp->name, comp->ns);
1858 if (isParam == 0) {
1859 if ((present != 0) && (present != 3)) {
1860 /* TODO: report QName. */
1861 xsltTransformError(ctxt, NULL, comp->inst,
1862 "XSLT-variable: Redefinition of variable '%s'.\n", comp->name);
1863 return(0);
1864 }
1865 } else if (present != 0) {
1866 if ((present == 1) || (present == 2)) {
1867 /* TODO: report QName. */
1868 xsltTransformError(ctxt, NULL, comp->inst,
1869 "XSLT-param: Redefinition of parameter '%s'.\n", comp->name);
1870 return(0);
1871 }
1872#ifdef WITH_XSLT_DEBUG_VARIABLE
1874 "param %s defined by caller\n", comp->name));
1875#endif
1876 return(0);
1877 }
1878#endif /* else of XSLT_REFACTORED */
1879
1881 if (xsltAddStackElem(ctxt, variable) < 0) {
1883 return(-1);
1884 }
1885 return(0);
1886}
1887
1899static xmlXPathObjectPtr
1901 const xmlChar *ns_uri) {
1903 xmlXPathObjectPtr ret = NULL;
1904
1905 /*
1906 * Lookup the global variables in XPath global variable hash table
1907 */
1908 if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))
1909 return(NULL);
1911 xmlHashLookup2(ctxt->globalVars, name, ns_uri);
1912 if (elem == NULL) {
1913#ifdef WITH_XSLT_DEBUG_VARIABLE
1915 "global variable not found %s\n", name));
1916#endif
1917 return(NULL);
1918 }
1919 /*
1920 * URGENT TODO: Move the detection of recursive definitions
1921 * to compile-time.
1922 */
1923 if (elem->computed == 0) {
1924 if (elem->name == xsltComputingGlobalVarMarker) {
1925 xsltTransformError(ctxt, NULL, elem->comp->inst,
1926 "Recursive definition of %s\n", name);
1927 return(NULL);
1928 }
1930 } else
1931 ret = elem->value;
1932 return(xmlXPathObjectCopy(ret));
1933}
1934
1946xmlXPathObjectPtr
1948 const xmlChar *ns_uri) {
1950
1951 if (ctxt == NULL)
1952 return(NULL);
1953
1954 elem = xsltStackLookup(ctxt, name, ns_uri);
1955 if (elem == NULL) {
1956 return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
1957 }
1958 if (elem->computed == 0) {
1959#ifdef WITH_XSLT_DEBUG_VARIABLE
1961 "uncomputed variable %s\n", name));
1962#endif
1963 elem->value = xsltEvalVariable(ctxt, elem, NULL);
1964 elem->computed = 1;
1965 }
1966 if (elem->value != NULL)
1967 return(xmlXPathObjectCopy(elem->value));
1968#ifdef WITH_XSLT_DEBUG_VARIABLE
1970 "variable not found %s\n", name));
1971#endif
1972 return(NULL);
1973}
1974
1990{
1991#ifdef XSLT_REFACTORED
1992 xsltStyleBasicItemVariablePtr comp;
1993#else
1995#endif
1996 xmlNodePtr tree = NULL; /* The first child node of the instruction or
1997 the instruction itself. */
1999
2000 if ((ctxt == NULL) || (inst == NULL) || (inst->type != XML_ELEMENT_NODE))
2001 return(NULL);
2002
2003#ifdef XSLT_REFACTORED
2004 comp = (xsltStyleBasicItemVariablePtr) inst->psvi;
2005#else
2006 comp = (xsltStylePreCompPtr) inst->psvi;
2007#endif
2008
2009 if (comp == NULL) {
2010 xsltTransformError(ctxt, NULL, inst,
2011 "Internal error in xsltParseStylesheetCallerParam(): "
2012 "The XSLT 'with-param' instruction was not compiled.\n");
2013 return(NULL);
2014 }
2015 if (comp->name == NULL) {
2016 xsltTransformError(ctxt, NULL, inst,
2017 "Internal error in xsltParseStylesheetCallerParam(): "
2018 "XSLT 'with-param': The attribute 'name' was not compiled.\n");
2019 return(NULL);
2020 }
2021
2022#ifdef WITH_XSLT_DEBUG_VARIABLE
2024 "Handling xsl:with-param %s\n", comp->name));
2025#endif
2026
2027 if (comp->select == NULL) {
2028 tree = inst->children;
2029 } else {
2030#ifdef WITH_XSLT_DEBUG_VARIABLE
2032 " select %s\n", comp->select));
2033#endif
2034 tree = inst;
2035 }
2036
2038
2039 return(param);
2040}
2041
2050void
2052{
2053#ifdef XSLT_REFACTORED
2054 xsltStyleItemVariablePtr comp;
2055#else
2057#endif
2058
2059 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
2060 return;
2061
2062#ifdef XSLT_REFACTORED
2063 /*
2064 * Note that xsltStylePreCompute() will be called from
2065 * xslt.c only.
2066 */
2067 comp = (xsltStyleItemVariablePtr) cur->psvi;
2068#else
2070 comp = (xsltStylePreCompPtr) cur->psvi;
2071#endif
2072 if (comp == NULL) {
2074 "xsl:variable : compilation failed\n");
2075 return;
2076 }
2077
2078 if (comp->name == NULL) {
2080 "xsl:variable : missing name attribute\n");
2081 return;
2082 }
2083
2084 /*
2085 * Parse the content (a sequence constructor) of xsl:variable.
2086 */
2087 if (cur->children != NULL) {
2088#ifdef XSLT_REFACTORED
2089 xsltParseSequenceConstructor(XSLT_CCTXT(style), cur->children);
2090#else
2092#endif
2093 }
2094#ifdef WITH_XSLT_DEBUG_VARIABLE
2096 "Registering global variable %s\n", comp->name);
2097#endif
2098
2099 xsltRegisterGlobalVariable(style, comp->name, comp->ns,
2100 comp->select, cur->children, (xsltStylePreCompPtr) comp,
2101 NULL);
2102}
2103
2113void
2115#ifdef XSLT_REFACTORED
2116 xsltStyleItemParamPtr comp;
2117#else
2119#endif
2120
2121 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
2122 return;
2123
2124#ifdef XSLT_REFACTORED
2125 /*
2126 * Note that xsltStylePreCompute() will be called from
2127 * xslt.c only.
2128 */
2129 comp = (xsltStyleItemParamPtr) cur->psvi;
2130#else
2132 comp = (xsltStylePreCompPtr) cur->psvi;
2133#endif
2134 if (comp == NULL) {
2136 "xsl:param : compilation failed\n");
2137 return;
2138 }
2139
2140 if (comp->name == NULL) {
2142 "xsl:param : missing name attribute\n");
2143 return;
2144 }
2145
2146 /*
2147 * Parse the content (a sequence constructor) of xsl:param.
2148 */
2149 if (cur->children != NULL) {
2150#ifdef XSLT_REFACTORED
2151 xsltParseSequenceConstructor(XSLT_CCTXT(style), cur->children);
2152#else
2154#endif
2155 }
2156
2157#ifdef WITH_XSLT_DEBUG_VARIABLE
2159 "Registering global param %s\n", comp->name);
2160#endif
2161
2162 xsltRegisterGlobalVariable(style, comp->name, comp->ns,
2163 comp->select, cur->children, (xsltStylePreCompPtr) comp,
2164 NULL);
2165}
2166
2175void
2177{
2178#ifdef XSLT_REFACTORED
2179 xsltStyleItemVariablePtr comp;
2180#else
2182#endif
2183
2184 if ((inst == NULL) || (ctxt == NULL) || (inst->type != XML_ELEMENT_NODE))
2185 return;
2186
2187 comp = inst->psvi;
2188 if (comp == NULL) {
2189 xsltTransformError(ctxt, NULL, inst,
2190 "Internal error in xsltParseStylesheetVariable(): "
2191 "The XSLT 'variable' instruction was not compiled.\n");
2192 return;
2193 }
2194 if (comp->name == NULL) {
2195 xsltTransformError(ctxt, NULL, inst,
2196 "Internal error in xsltParseStylesheetVariable(): "
2197 "The attribute 'name' was not compiled.\n");
2198 return;
2199 }
2200
2201#ifdef WITH_XSLT_DEBUG_VARIABLE
2203 "Registering variable '%s'\n", comp->name));
2204#endif
2205
2206 xsltRegisterVariable(ctxt, (xsltStylePreCompPtr) comp, inst->children, 0);
2207}
2208
2217void
2219{
2220#ifdef XSLT_REFACTORED
2221 xsltStyleItemParamPtr comp;
2222#else
2224#endif
2225
2226 if ((cur == NULL) || (ctxt == NULL) || (cur->type != XML_ELEMENT_NODE))
2227 return;
2228
2229 comp = cur->psvi;
2230 if ((comp == NULL) || (comp->name == NULL)) {
2232 "Internal error in xsltParseStylesheetParam(): "
2233 "The XSLT 'param' declaration was not compiled correctly.\n");
2234 return;
2235 }
2236
2237#ifdef WITH_XSLT_DEBUG_VARIABLE
2239 "Registering param %s\n", comp->name));
2240#endif
2241
2242 xsltRegisterVariable(ctxt, (xsltStylePreCompPtr) comp, cur->children, 1);
2243}
2244
2253void
2256}
2257
2269xmlXPathObjectPtr
2271 const xmlChar *ns_uri) {
2273 xmlXPathObjectPtr valueObj = NULL;
2274
2275 if ((ctxt == NULL) || (name == NULL))
2276 return(NULL);
2277
2278#ifdef WITH_XSLT_DEBUG_VARIABLE
2280 "Lookup variable '%s'\n", name));
2281#endif
2282
2283 tctxt = (xsltTransformContextPtr) ctxt;
2284 /*
2285 * Local variables/params ---------------------------------------------
2286 *
2287 * Do the lookup from the top of the stack, but
2288 * don't use params being computed in a call-param
2289 * First lookup expects the variable name and URI to
2290 * come from the disctionnary and hence pointer comparison.
2291 */
2292 if (tctxt->varsNr != 0) {
2293 int i;
2295
2296 for (i = tctxt->varsNr; i > tctxt->varsBase; i--) {
2297 cur = tctxt->varsTab[i-1];
2298 if ((cur->name == name) && (cur->nameURI == ns_uri)) {
2299#if 0
2300 stack_addr++;
2301#endif
2302 variable = cur;
2303 goto local_variable_found;
2304 }
2305 cur = cur->next;
2306 }
2307 /*
2308 * Redo the lookup with interned strings to avoid string comparison.
2309 *
2310 * OPTIMIZE TODO: The problem here is, that if we request a
2311 * global variable, then this will be also executed.
2312 */
2313 {
2314 const xmlChar *tmpName = name, *tmpNsName = ns_uri;
2315
2316 name = xmlDictLookup(tctxt->dict, name, -1);
2317 if (ns_uri)
2318 ns_uri = xmlDictLookup(tctxt->dict, ns_uri, -1);
2319 if ((tmpName != name) || (tmpNsName != ns_uri)) {
2320 for (i = tctxt->varsNr; i > tctxt->varsBase; i--) {
2321 cur = tctxt->varsTab[i-1];
2322 if ((cur->name == name) && (cur->nameURI == ns_uri)) {
2323#if 0
2324 stack_cmp++;
2325#endif
2326 variable = cur;
2327 goto local_variable_found;
2328 }
2329 }
2330 }
2331 }
2332
2333local_variable_found:
2334
2335 if (variable) {
2336 if (variable->computed == 0) {
2337
2338#ifdef WITH_XSLT_DEBUG_VARIABLE
2340 "uncomputed variable '%s'\n", name));
2341#endif
2342 variable->value = xsltEvalVariable(tctxt, variable, NULL);
2343 variable->computed = 1;
2344 }
2345 if (variable->value != NULL) {
2346 valueObj = xmlXPathObjectCopy(variable->value);
2347 }
2348 return(valueObj);
2349 }
2350 }
2351 /*
2352 * Global variables/params --------------------------------------------
2353 */
2354 if (tctxt->globalVars) {
2355 valueObj = xsltGlobalVariableLookup(tctxt, name, ns_uri);
2356 }
2357
2358 if (valueObj == NULL) {
2359
2360#ifdef WITH_XSLT_DEBUG_VARIABLE
2362 "variable not found '%s'\n", name));
2363#endif
2364
2365 if (ns_uri) {
2366 xsltTransformError(tctxt, NULL, tctxt->inst,
2367 "Variable '{%s}%s' has not been declared.\n", ns_uri, name);
2368 } else {
2369 xsltTransformError(tctxt, NULL, tctxt->inst,
2370 "Variable '%s' has not been declared.\n", name);
2371 }
2372 } else {
2373
2374#ifdef WITH_XSLT_DEBUG_VARIABLE
2376 "found variable '%s'\n", name));
2377#endif
2378 }
2379
2380 return(valueObj);
2381}
void xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst)
Definition: preproc.c:2191
Arabic default style
Definition: afstyles.h:94
struct _tree tree
#define NULL
Definition: types.h:112
void xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr list, xsltTemplatePtr templ ATTRIBUTE_UNUSED, xsltStackElemPtr params)
Definition: transform.c:3313
#define stdout
#define stderr
return ret
Definition: mutex.c:146
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
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLenum variable
Definition: glext.h:9031
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
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:297
void xsltFreeDocumentKeys(xsltDocumentPtr idoc)
Definition: keys.c:931
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static size_t elem
Definition: string.c:71
static unsigned __int64 next
Definition: rand_nt.c:6
int xmlDictReference(xmlDictPtr dict)
Definition: dict.c:317
const xmlChar * xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:824
void * xmlGenericErrorContext
Definition: globals.c:410
xmlReallocFunc xmlRealloc
Definition: globals.c:214
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlGenericErrorFunc xmlGenericError
Definition: globals.c:396
xmlMallocFunc xmlMalloc
Definition: globals.c:193
void xmlHashScan(xmlHashTablePtr hash, xmlHashScanner scan, void *data)
Definition: hash.c:898
void xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc)
Definition: hash.c:229
void * xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2)
Definition: hash.c:754
xmlHashTablePtr xmlHashCreate(int size)
Definition: hash.c:160
int xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, void *payload)
Definition: hash.c:639
#define memset(x, y, z)
Definition: compat.h:39
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
struct define * next
Definition: compiler.c:65
Definition: name.c:39
Definition: mxnamespace.c:38
Character const *const prefix
Definition: tempnam.cpp:195
XSLTPUBFUN void XSLTCALL xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ, xsltTransformContextPtr ctxt)
Definition: pdh_main.c:96
XMLPUBFUN void xmlFreeIDTable(xmlIDTablePtr table)
Definition: valid.c:2601
void xsltFreeRVTs(xsltTransformContextPtr ctxt)
Definition: variables.c:439
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:1369
xmlXPathObjectPtr xsltXPathVariableLookup(void *ctxt, const xmlChar *name, const xmlChar *ns_uri)
Definition: variables.c:2270
xmlDocPtr xsltCreateRVT(xsltTransformContextPtr ctxt)
Definition: variables.c:65
int xsltEvalGlobalVariables(xsltTransformContextPtr ctxt)
Definition: variables.c:1279
static xmlXPathObjectPtr xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable, xsltStylePreCompPtr castedComp)
Definition: variables.c:814
static xmlXPathObjectPtr xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt)
Definition: variables.c:1047
static xmlXPathObjectPtr xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri)
Definition: variables.c:1900
int xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:120
void xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: variables.c:2051
int xsltRegisterLocalRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:159
void xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: variables.c:2114
static xsltStackElemPtr xsltBuildVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr castedComp, xmlNodePtr tree)
Definition: variables.c:1790
int xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED)
Definition: variables.c:208
int xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:417
void xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur)
Definition: variables.c:2218
void xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:351
int xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, int val)
Definition: variables.c:258
static int xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI)
Definition: variables.c:719
static xsltStackElemPtr xsltCopyStackElem(xsltStackElemPtr elem)
Definition: variables.c:539
static xsltStackElemPtr xsltNewStackElem(xsltTransformContextPtr ctxt)
Definition: variables.c:503
void xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr inst)
Definition: variables.c:2176
void xsltFreeGlobalVariables(xsltTransformContextPtr ctxt)
Definition: variables.c:2254
xsltStackElemPtr xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr inst)
Definition: variables.c:1989
static xsltStackElemPtr xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI)
Definition: variables.c:650
void xsltFreeStackElemList(xsltStackElemPtr elem)
Definition: variables.c:626
int xsltQuoteOneUserParam(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *value)
Definition: variables.c:1772
static void xsltEvalGlobalVariableWrapper(void *payload, void *data, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: variables.c:1263
xmlXPathObjectPtr xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri)
Definition: variables.c:1947
static const xmlChar * xsltComputingGlobalVarMarker
Definition: variables.c:43
int xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, xmlXPathObjectPtr obj ATTRIBUTE_UNUSED)
Definition: variables.c:234
static int xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem)
Definition: variables.c:754
static int xsltRegisterVariable(xsltTransformContextPtr ctxt, xsltStylePreCompPtr castedComp, xmlNodePtr tree, int isParam)
Definition: variables.c:1837
int xsltEvalOneUserParam(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *value)
Definition: variables.c:1751
int xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params)
Definition: variables.c:1716
#define XSLT_VAR_IN_SELECT
Definition: variables.c:47
static int xsltProcessUserParamInternal(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *value, int eval)
Definition: variables.c:1462
int xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems)
Definition: variables.c:792
#define XSLT_TCTXT_VARIABLE(c)
Definition: variables.c:48
static void xsltFreeStackElemEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: variables.c:614
static void xsltFreeStackElem(xsltStackElemPtr elem)
Definition: variables.c:565
int xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params)
Definition: variables.c:1686
#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
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
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:47
@ XSLT_STATE_STOPPED
xsltStackElem * xsltStackElemPtr
xsltStylePreComp * xsltStylePreCompPtr
void xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ)
Definition: xslt.c:4894
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:762
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:632
void * xsltGenericDebugContext
Definition: xsltutils.c:633
const xmlChar * xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix)
Definition: xsltutils.c:804
@ XSLT_DEBUG_NONE
Definition: xsltutils.h:304
@ XSLT_TRACE_VARIABLES
Definition: xsltutils.h:124
#define XSLT_TRACE(ctxt, code, call)
Definition: xsltutils.h:132