[LIBXSLT] Update to version 1.1.32. CORE-14291
authorThomas Faber <thomas.faber@reactos.org>
Sun, 4 Feb 2018 14:52:31 +0000 (15:52 +0100)
committerThomas Faber <thomas.faber@reactos.org>
Mon, 5 Feb 2018 13:37:37 +0000 (14:37 +0100)
24 files changed:
dll/3rdparty/libxslt/Makefile.am
dll/3rdparty/libxslt/attributes.c
dll/3rdparty/libxslt/extensions.c
dll/3rdparty/libxslt/extra.c
dll/3rdparty/libxslt/extra.h
dll/3rdparty/libxslt/functions.c
dll/3rdparty/libxslt/keys.c
dll/3rdparty/libxslt/numbers.c
dll/3rdparty/libxslt/pattern.c
dll/3rdparty/libxslt/preproc.c
dll/3rdparty/libxslt/security.c
dll/3rdparty/libxslt/templates.c
dll/3rdparty/libxslt/transform.c
dll/3rdparty/libxslt/variables.c
dll/3rdparty/libxslt/xslt.c
dll/3rdparty/libxslt/xsltconfig.h.in
dll/3rdparty/libxslt/xsltlocale.c
dll/3rdparty/libxslt/xsltutils.c
dll/3rdparty/libxslt/xsltwin32config.h
sdk/include/reactos/libs/libxslt/libxslt.h
sdk/include/reactos/libs/libxslt/variables.h
sdk/include/reactos/libs/libxslt/xsltInternals.h
sdk/include/reactos/libs/libxslt/xsltconfig.h
sdk/include/reactos/libs/libxslt/xsltlocale.h

index d9fed68..ef2de24 100644 (file)
@@ -62,7 +62,7 @@ else
 LIBXSLT_VERSION_SCRIPT =
 endif
 
-libxslt_la_LIBADD = $(LIBXML_LIBS) $(EXTRA_LIBS)
+libxslt_la_LIBADD = $(LIBXML_LIBS) $(EXTRA_LIBS) $(M_LIBS)
 libxslt_la_LDFLAGS =                                   \
                $(WIN32_EXTRA_LDFLAGS)                  \
                $(LIBXSLT_VERSION_SCRIPT)               \
index c038a3c..8191f44 100644 (file)
 #define WITH_XSLT_DEBUG_ATTRIBUTES
 #endif
 
-/*
- * TODO: merge attribute sets from different import precedence.
- *       all this should be precomputed just before the transformation
- *       starts or at first hit with a cache in the context.
- *       The simple way for now would be to not allow redefinition of
- *       attributes once generated in the output tree, possibly costlier.
- */
-
 /*
  * Useful macros
  */
 #define IS_BLANK_NODE(n)                                               \
     (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
 
+#define ATTRSET_UNRESOLVED 0
+#define ATTRSET_RESOLVING  1
+#define ATTRSET_RESOLVED   2
+
 
 /*
  * The in-memory structure corresponding to an XSLT Attribute in
@@ -49,10 +45,36 @@ typedef xsltAttrElem *xsltAttrElemPtr;
 struct _xsltAttrElem {
     struct _xsltAttrElem *next;/* chained list */
     xmlNodePtr attr;   /* the xsl:attribute definition */
-    const xmlChar *set; /* or the attribute set */
-    const xmlChar *ns;  /* and its namespace */
 };
 
+typedef struct _xsltUseAttrSet xsltUseAttrSet;
+typedef xsltUseAttrSet *xsltUseAttrSetPtr;
+struct _xsltUseAttrSet {
+    struct _xsltUseAttrSet *next; /* chained list */
+    const xmlChar *ncname;
+    const xmlChar *ns;
+};
+
+typedef struct _xsltAttrSet xsltAttrSet;
+typedef xsltAttrSet *xsltAttrSetPtr;
+struct _xsltAttrSet {
+    int state;
+    xsltAttrElemPtr attrs; /* list head */
+    xsltUseAttrSetPtr useAttrSets; /* list head */
+};
+
+typedef struct _xsltAttrSetContext xsltAttrSetContext;
+typedef xsltAttrSetContext *xsltAttrSetContextPtr;
+struct _xsltAttrSetContext {
+    xsltStylesheetPtr topStyle;
+    xsltStylesheetPtr style;
+};
+
+static void
+xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle,
+                   xsltStylesheetPtr style, const xmlChar *name,
+                   const xmlChar *ns, int depth);
+
 /************************************************************************
  *                                                                     *
  *                     XSLT Attribute handling                         *
@@ -110,11 +132,6 @@ xsltFreeAttrElemList(xsltAttrElemPtr list) {
     }
 }
 
-#ifdef XSLT_REFACTORED
-    /*
-    * This was moved to xsltParseStylesheetAttributeSet().
-    */
-#else
 /**
  * xsltAddAttrElemList:
  * @list:  an XSLT AttrElem list
@@ -135,9 +152,7 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
     cur = list;
     while (cur != NULL) {
        next = cur->next;
-       if (cur->attr == attr)
-           return(cur);
-       if (cur->next == NULL) {
+       if (next == NULL) {
            cur->next = xsltNewAttrElem(attr);
            return(list);
        }
@@ -145,92 +160,174 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
     }
     return(list);
 }
-#endif /* XSLT_REFACTORED */
 
 /**
- * xsltMergeAttrElemList:
- * @list:  an XSLT AttrElem list
- * @old:  another XSLT AttrElem list
+ * xsltNewUseAttrSet:
+ * @ncname:  local name
+ * @ns:  namespace URI
  *
- * Add all the attributes from list @old to list @list,
- * but drop redefinition of existing values.
+ * Create a new XSLT UseAttrSet
  *
- * Returns the new list pointer
+ * Returns the newly allocated xsltUseAttrSetPtr or NULL in case of error.
  */
-static xsltAttrElemPtr
-xsltMergeAttrElemList(xsltStylesheetPtr style,
-                     xsltAttrElemPtr list, xsltAttrElemPtr old) {
+static xsltUseAttrSetPtr
+xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns) {
+    xsltUseAttrSetPtr cur;
+
+    cur = (xsltUseAttrSetPtr) xmlMalloc(sizeof(xsltUseAttrSet));
+    if (cur == NULL) {
+        xsltGenericError(xsltGenericErrorContext,
+               "xsltNewUseAttrSet : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltUseAttrSet));
+    cur->ncname = ncname;
+    cur->ns = ns;
+    return(cur);
+}
+
+/**
+ * xsltFreeUseAttrSet:
+ * @use:  an XSLT UseAttrSet
+ *
+ * Free up the memory allocated by @use
+ */
+static void
+xsltFreeUseAttrSet(xsltUseAttrSetPtr use) {
+    xmlFree(use);
+}
+
+/**
+ * xsltFreeUseAttrSetList:
+ * @list:  an XSLT UseAttrSet list
+ *
+ * Free up the memory allocated by @list
+ */
+static void
+xsltFreeUseAttrSetList(xsltUseAttrSetPtr list) {
+    xsltUseAttrSetPtr next;
+
+    while (list != NULL) {
+       next = list->next;
+       xsltFreeUseAttrSet(list);
+       list = next;
+    }
+}
+
+/**
+ * xsltAddUseAttrSetList:
+ * @list:  a xsltUseAttrSet list
+ * @ncname:  local name
+ * @ns:  namespace URI
+ *
+ * Add the use-attribute-set name to the list.
+ *
+ * Returns the new list pointer.
+ */
+static xsltUseAttrSetPtr
+xsltAddUseAttrSetList(xsltUseAttrSetPtr list, const xmlChar *ncname,
+                      const xmlChar *ns) {
+    xsltUseAttrSetPtr next, cur;
+
+    if (ncname == NULL)
+        return(list);
+    if (list == NULL)
+       return(xsltNewUseAttrSet(ncname, ns));
+    cur = list;
+    while (cur != NULL) {
+        if ((cur->ncname == ncname) && (cur->ns == ns))
+            return(list);
+       next = cur->next;
+       if (next == NULL) {
+           cur->next = xsltNewUseAttrSet(ncname, ns);
+           return(list);
+       }
+       cur = next;
+    }
+    return(list);
+}
+
+/**
+ * xsltNewAttrSet:
+ *
+ * Create a new attribute set.
+ *
+ * Returns the newly allocated xsltAttrSetPtr or NULL in case of error.
+ */
+static xsltAttrSetPtr
+xsltNewAttrSet() {
+    xsltAttrSetPtr cur;
+
+    cur = (xsltAttrSetPtr) xmlMalloc(sizeof(xsltAttrSet));
+    if (cur == NULL) {
+        xsltGenericError(xsltGenericErrorContext,
+               "xsltNewAttrSet : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltAttrSet));
+    return(cur);
+}
+
+/**
+ * xsltFreeAttrSet:
+ * @set:  an attribute set
+ *
+ * Free memory allocated by @set
+ */
+static void
+xsltFreeAttrSet(xsltAttrSetPtr set) {
+    if (set == NULL)
+        return;
+
+    xsltFreeAttrElemList(set->attrs);
+    xsltFreeUseAttrSetList(set->useAttrSets);
+    xmlFree(set);
+}
+
+/**
+ * xsltMergeAttrSets:
+ * @set:  an attribute set
+ * @other:  another attribute set
+ *
+ * Add all the attributes from @other to @set,
+ * but drop redefinition of existing values.
+ */
+static void
+xsltMergeAttrSets(xsltAttrSetPtr set, xsltAttrSetPtr other) {
     xsltAttrElemPtr cur;
+    xsltAttrElemPtr old = other->attrs;
     int add;
 
     while (old != NULL) {
-       if ((old->attr == NULL) && (old->set == NULL)) {
-           old = old->next;
-           continue;
-       }
        /*
         * Check that the attribute is not yet in the list
         */
-       cur = list;
+       cur = set->attrs;
        add = 1;
        while (cur != NULL) {
-           if ((cur->attr == NULL) && (cur->set == NULL)) {
-               if (cur->next == NULL)
-                   break;
-               cur = cur->next;
-               continue;
-           }
-           if ((cur->set != NULL) && (cur->set == old->set)) {
-               add = 0;
-               break;
-           }
-           if (cur->set != NULL) {
-               if (cur->next == NULL)
-                   break;
-               cur = cur->next;
-               continue;
-           }
-           if (old->set != NULL) {
-               if (cur->next == NULL)
-                   break;
-               cur = cur->next;
-               continue;
-           }
-           if (cur->attr == old->attr) {
-               xsltGenericError(xsltGenericErrorContext,
-            "xsl:attribute-set : use-attribute-sets recursion detected\n");
-               return(list);
-           }
+            xsltStylePreCompPtr curComp = cur->attr->psvi;
+            xsltStylePreCompPtr oldComp = old->attr->psvi;
+
+            if ((curComp->name == oldComp->name) &&
+                (curComp->ns == oldComp->ns)) {
+                add = 0;
+                break;
+            }
            if (cur->next == NULL)
                break;
             cur = cur->next;
        }
 
        if (add == 1) {
-           /*
-           * Changed to use the string-dict, rather than duplicating
-           * @set and @ns; this fixes bug #340400.
-           */
            if (cur == NULL) {
-               list = xsltNewAttrElem(old->attr);
-               if (old->set != NULL) {
-                   list->set = xmlDictLookup(style->dict, old->set, -1);
-                   if (old->ns != NULL)
-                       list->ns = xmlDictLookup(style->dict, old->ns, -1);
-               }
+               set->attrs = xsltNewAttrElem(old->attr);
            } else if (add) {
                cur->next = xsltNewAttrElem(old->attr);
-               if (old->set != NULL) {
-                   cur->next->set = xmlDictLookup(style->dict, old->set, -1);
-                   if (old->ns != NULL)
-                       cur->next->ns = xmlDictLookup(style->dict, old->ns, -1);
-               }
            }
        }
 
        old = old->next;
     }
-    return(list);
 }
 
 /************************************************************************
@@ -251,9 +348,10 @@ void
 xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
     const xmlChar *ncname;
     const xmlChar *prefix;
+    const xmlChar *nsUri = NULL;
     xmlChar *value;
     xmlNodePtr child;
-    xsltAttrElemPtr attrItems;
+    xsltAttrSetPtr set;
 
     if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
        return;
@@ -267,9 +365,29 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
        return;
     }
 
+    if (xmlValidateQName(value, 0)) {
+        xsltTransformError(NULL, style, cur,
+            "xsl:attribute-set : The name '%s' is not a valid QName.\n",
+            value);
+        style->errors++;
+        xmlFree(value);
+        return;
+    }
+
     ncname = xsltSplitQName(style->dict, value, &prefix);
     xmlFree(value);
     value = NULL;
+    if (prefix != NULL) {
+        xmlNsPtr ns = xmlSearchNs(style->doc, cur, prefix);
+        if (ns == NULL) {
+            xsltTransformError(NULL, style, cur,
+                "xsl:attribute-set : No namespace found for QName '%s:%s'\n",
+                prefix, ncname);
+            style->errors++;
+            return;
+        }
+        nsUri = ns->href;
+    }
 
     if (style->attributeSets == NULL) {
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
@@ -281,7 +399,13 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
     if (style->attributeSets == NULL)
        return;
 
-    attrItems = xmlHashLookup2(style->attributeSets, ncname, prefix);
+    set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
+    if (set == NULL) {
+        set = xsltNewAttrSet();
+        if (set == NULL)
+            return;
+        xmlHashAddEntry2(style->attributeSets, ncname, nsUri, set);
+    }
 
     /*
     * Parse the content. Only xsl:attribute elements are allowed.
@@ -307,71 +431,36 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
                "xsl:attribute-set : unexpected child xsl:%s\n",
                child->name);
        } else {
-#ifdef XSLT_REFACTORED
-           xsltAttrElemPtr nextAttr, curAttr;
-
-           /*
-           * Process xsl:attribute
-           * ---------------------
-           */
-
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
            xsltGenericDebug(xsltGenericDebugContext,
                "add attribute to list %s\n", ncname);
 #endif
-           /*
-           * The following was taken over from
-           * xsltAddAttrElemList().
-           */
-           if (attrItems == NULL) {
-               attrItems = xsltNewAttrElem(child);
-           } else {
-               curAttr = attrItems;
-               while (curAttr != NULL) {
-                   nextAttr = curAttr->next;
-                   if (curAttr->attr == child) {
-                       /*
-                       * URGENT TODO: Can somebody explain
-                       *  why attrItems is set to curAttr
-                       *  here? Is this somehow related to
-                       *  avoidance of recursions?
-                       */
-                       attrItems = curAttr;
-                       goto next_child;
-                   }
-                   if (curAttr->next == NULL)
-                       curAttr->next = xsltNewAttrElem(child);
-                   curAttr = nextAttr;
-               }
-           }
-           /*
-           * Parse the xsl:attribute and its content.
-           */
-           xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
+            xsltStylePreCompute(style, child);
+            if (child->children != NULL) {
+#ifdef XSLT_REFACTORED
+                xsltParseSequenceConstructor(XSLT_CCTXT(style),
+                                             child->children);
 #else
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
-           xsltGenericDebug(xsltGenericDebugContext,
-               "add attribute to list %s\n", ncname);
-#endif
-           /*
-           * OLD behaviour:
-           */
-           attrItems = xsltAddAttrElemList(attrItems, child);
+                xsltParseTemplateContent(style, child);
 #endif
+            }
+            if (child->psvi == NULL) {
+                xsltTransformError(NULL, style, child,
+                    "xsl:attribute-set : internal error, attribute %s not "
+                    "compiled\n", child->name);
+            }
+            else {
+               set->attrs = xsltAddAttrElemList(set->attrs, child);
+            }
        }
 
-#ifdef XSLT_REFACTORED
-next_child:
-#endif
        child = child->next;
     }
 
     /*
-    * Process attribue "use-attribute-sets".
+    * Process attribute "use-attribute-sets".
     */
-    /* TODO check recursion */
-    value = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets",
-       NULL);
+    value = xmlGetNsProp(cur, BAD_CAST "use-attribute-sets", NULL);
     if (value != NULL) {
        const xmlChar *curval, *endval;
        curval = value;
@@ -385,21 +474,38 @@ next_child:
            if (curval) {
                const xmlChar *ncname2 = NULL;
                const xmlChar *prefix2 = NULL;
-               xsltAttrElemPtr refAttrItems;
+                const xmlChar *nsUri2 = NULL;
 
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
                xsltGenericDebug(xsltGenericDebugContext,
                    "xsl:attribute-set : %s adds use %s\n", ncname, curval);
 #endif
+
+                if (xmlValidateQName(curval, 0)) {
+                    xsltTransformError(NULL, style, cur,
+                        "xsl:attribute-set : The name '%s' in "
+                        "use-attribute-sets is not a valid QName.\n", curval);
+                    style->errors++;
+                    xmlFree(value);
+                    return;
+                }
+
                ncname2 = xsltSplitQName(style->dict, curval, &prefix2);
-               refAttrItems = xsltNewAttrElem(NULL);
-               if (refAttrItems != NULL) {
-                   refAttrItems->set = ncname2;
-                   refAttrItems->ns = prefix2;
-                   attrItems = xsltMergeAttrElemList(style,
-                       attrItems, refAttrItems);
-                   xsltFreeAttrElem(refAttrItems);
-               }
+                if (prefix2 != NULL) {
+                    xmlNsPtr ns2 = xmlSearchNs(style->doc, cur, prefix2);
+                    if (ns2 == NULL) {
+                        xsltTransformError(NULL, style, cur,
+                            "xsl:attribute-set : No namespace found for QName "
+                            "'%s:%s' in use-attribute-sets\n",
+                            prefix2, ncname2);
+                        style->errors++;
+                        xmlFree(value);
+                        return;
+                    }
+                    nsUri2 = ns2->href;
+                }
+                set->useAttrSets = xsltAddUseAttrSetList(set->useAttrSets,
+                                                         ncname2, nsUri2);
            }
            curval = endval;
        }
@@ -407,15 +513,6 @@ next_child:
        value = NULL;
     }
 
-    /*
-     * Update the value
-     */
-    /*
-    * TODO: Why is this dummy entry needed.?
-    */
-    if (attrItems == NULL)
-       attrItems = xsltNewAttrElem(NULL);
-    xmlHashUpdateEntry2(style->attributeSets, ncname, prefix, attrItems, NULL);
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
     xsltGenericDebug(xsltGenericDebugContext,
        "updated attribute list %s\n", ncname);
@@ -423,143 +520,141 @@ next_child:
 }
 
 /**
- * xsltGetSAS:
- * @style:  the XSLT stylesheet
- * @name:  the attribute list name
- * @ns:  the attribute list namespace
+ * xsltResolveUseAttrSets:
+ * @set: the attribute set
+ * @asctx:  the context for attribute set resolution
+ * @depth: recursion depth
  *
- * lookup an attribute set based on the style cascade
- *
- * Returns the attribute set or NULL
+ * Process "use-attribute-sets".
  */
-static xsltAttrElemPtr
-xsltGetSAS(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns) {
-    xsltAttrElemPtr values;
-
-    while (style != NULL) {
-       values = xmlHashLookup2(style->attributeSets, name, ns);
-       if (values != NULL)
-           return(values);
-       style = xsltNextImport(style);
+static void
+xsltResolveUseAttrSets(xsltAttrSetPtr set, xsltStylesheetPtr topStyle,
+                      int depth) {
+    xsltStylesheetPtr cur;
+    xsltAttrSetPtr other;
+    xsltUseAttrSetPtr use = set->useAttrSets;
+    xsltUseAttrSetPtr next;
+
+    while (use != NULL) {
+        /*
+         * Iterate top stylesheet and all imports.
+         */
+        cur = topStyle;
+        while (cur != NULL) {
+            if (cur->attributeSets) {
+                other = xmlHashLookup2(cur->attributeSets, use->ncname,
+                                       use->ns);
+                if (other != NULL) {
+                    xsltResolveAttrSet(other, topStyle, cur, use->ncname,
+                                       use->ns, depth + 1);
+                    xsltMergeAttrSets(set, other);
+                    break;
+                }
+            }
+            cur = xsltNextImport(cur);
+        }
+
+        next = use->next;
+        /* Free useAttrSets early. */
+        xsltFreeUseAttrSet(use);
+        use = next;
     }
-    return(NULL);
+
+    set->useAttrSets = NULL;
 }
 
 /**
- * xsltResolveSASCallbackInt:
- * @style:  the XSLT stylesheet
+ * xsltResolveAttrSet:
+ * @set: the attribute set
+ * @asctx:  the context for attribute set resolution
+ * @name: the local name of the attirbute set
+ * @ns: the namespace of the attribute set
+ * @depth: recursion depth
  *
  * resolve the references in an attribute set.
  */
 static void
-xsltResolveSASCallbackInt(xsltAttrElemPtr values, xsltStylesheetPtr style,
-                      const xmlChar *name, const xmlChar *ns,
-                      int depth) {
-    xsltAttrElemPtr tmp;
-    xsltAttrElemPtr refs;
+xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle,
+                   xsltStylesheetPtr style, const xmlChar *name,
+                   const xmlChar *ns, int depth) {
+    xsltStylesheetPtr cur;
+    xsltAttrSetPtr other;
 
-    tmp = values;
-    if ((name == NULL) || (name[0] == 0))
+    if (set->state == ATTRSET_RESOLVED)
+        return;
+    if (set->state == ATTRSET_RESOLVING) {
+       xsltTransformError(NULL, topStyle, NULL,
+            "xsl:attribute-set : use-attribute-sets recursion detected"
+            " on %s\n", name);
+        topStyle->errors++;
+        set->state = ATTRSET_RESOLVED;
         return;
+    }
     if (depth > 100) {
-       xsltGenericError(xsltGenericErrorContext,
-       "xsl:attribute-set : use-attribute-sets recursion detected on %s\n",
-                        name);
+       xsltTransformError(NULL, topStyle, NULL,
+               "xsl:attribute-set : use-attribute-sets maximum recursion "
+               "depth exceeded on %s\n", name);
+        topStyle->errors++;
        return;
     }
-    while (tmp != NULL) {
-       if (tmp->set != NULL) {
-           /*
-            * Check against cycles !
-            */
-           if ((xmlStrEqual(name, tmp->set)) && (xmlStrEqual(ns, tmp->ns))) {
-               xsltGenericError(xsltGenericErrorContext,
-     "xsl:attribute-set : use-attribute-sets recursion detected on %s\n",
-                                 name);
-           } else {
+
+    set->state = ATTRSET_RESOLVING;
+
+    xsltResolveUseAttrSets(set, topStyle, depth);
+
+    /* Merge imported sets. */
+    cur = xsltNextImport(style);
+    while (cur != NULL) {
+        if (cur->attributeSets != NULL) {
+            other = xmlHashLookup2(cur->attributeSets, name, ns);
+
+            if (other != NULL) {
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
-               xsltGenericDebug(xsltGenericDebugContext,
-                       "Importing attribute list %s\n", tmp->set);
+                xsltGenericDebug(xsltGenericDebugContext,
+                    "xsl:attribute-set : merging import for %s\n", name);
 #endif
+                xsltResolveUseAttrSets(other, topStyle, depth);
+                xsltMergeAttrSets(set, other);
+                xmlHashRemoveEntry2(cur->attributeSets, name, ns, NULL);
+                xsltFreeAttrSet(other);
+            }
+        }
 
-               refs = xsltGetSAS(style, tmp->set, tmp->ns);
-               if (refs == NULL) {
-                   xsltGenericError(xsltGenericErrorContext,
-     "xsl:attribute-set : use-attribute-sets %s reference missing %s\n",
-                                    name, tmp->set);
-               } else {
-                   /*
-                    * recurse first for cleanup
-                    */
-                   xsltResolveSASCallbackInt(refs, style, name, ns, depth + 1);
-                   /*
-                    * Then merge
-                    */
-                   xsltMergeAttrElemList(style, values, refs);
-                   /*
-                    * Then suppress the reference
-                    */
-                   tmp->set = NULL;
-                   tmp->ns = NULL;
-               }
-           }
-       }
-       tmp = tmp->next;
+        cur = xsltNextImport(cur);
     }
+
+    set->state = ATTRSET_RESOLVED;
 }
 
 /**
- * xsltResolveSASCallback,:
- * @style:  the XSLT stylesheet
+ * xsltResolveSASCallback:
+ * @set: the attribute set
+ * @asctx:  the context for attribute set resolution
+ * @name: the local name of the attirbute set
+ * @ns: the namespace of the attribute set
  *
  * resolve the references in an attribute set.
  */
 static void
-xsltResolveSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
+xsltResolveSASCallback(xsltAttrSetPtr set, xsltAttrSetContextPtr asctx,
                       const xmlChar *name, const xmlChar *ns,
                       ATTRIBUTE_UNUSED const xmlChar *ignored) {
-    xsltResolveSASCallbackInt(values, style, name, ns, 1);
-}
+    xsltStylesheetPtr topStyle = asctx->topStyle;
+    xsltStylesheetPtr style = asctx->style;
 
-/**
- * xsltMergeSASCallback,:
- * @style:  the XSLT stylesheet
- *
- * Merge an attribute set from an imported stylesheet.
- */
-static void
-xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
-                      const xmlChar *name, const xmlChar *ns,
-                      ATTRIBUTE_UNUSED const xmlChar *ignored) {
-    int ret;
-    xsltAttrElemPtr topSet;
+    xsltResolveAttrSet(set, topStyle, style, name, ns, 1);
 
-    ret = xmlHashAddEntry2(style->attributeSets, name, ns, values);
-    if (ret < 0) {
-       /*
-        * Add failed, this attribute set can be removed.
-        */
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
-       xsltGenericDebug(xsltGenericDebugContext,
-               "attribute set %s present already in top stylesheet"
-               " - merging\n", name);
-#endif
-       topSet = xmlHashLookup2(style->attributeSets, name, ns);
-       if (topSet==NULL) {
+    /* Move attribute sets to top stylesheet. */
+    if (style != topStyle) {
+        /*
+         * This imported stylesheet won't be visited anymore. Don't bother
+         * removing the hash entry.
+         */
+        if (xmlHashAddEntry2(topStyle->attributeSets, name, ns, set) < 0) {
            xsltGenericError(xsltGenericErrorContext,
-               "xsl:attribute-set : logic error merging from imports for"
-               " attribute-set %s\n", name);
-       } else {
-           topSet = xsltMergeAttrElemList(style, topSet, values);
-           xmlHashUpdateEntry2(style->attributeSets, name, ns, topSet, NULL);
-       }
-       xsltFreeAttrElemList(values);
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
-    } else {
-       xsltGenericDebug(xsltGenericDebugContext,
-               "attribute set %s moved to top stylesheet\n",
-                        name);
-#endif
+                "xsl:attribute-set : internal error, can't move imported "
+                " attribute set %s\n", name);
+        }
     }
 }
 
@@ -572,15 +667,14 @@ xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
 void
 xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) {
     xsltStylesheetPtr cur;
+    xsltAttrSetContext asctx;
 
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
     xsltGenericDebug(xsltGenericDebugContext,
            "Resolving attribute sets references\n");
 #endif
-    /*
-     * First aggregate all the attribute sets definitions from the imports
-     */
-    cur = xsltNextImport(style);
+    asctx.topStyle = style;
+    cur = style;
     while (cur != NULL) {
        if (cur->attributeSets != NULL) {
            if (style->attributeSets == NULL) {
@@ -590,43 +684,37 @@ xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) {
 #endif
                style->attributeSets = xmlHashCreate(10);
            }
+            asctx.style = cur;
            xmlHashScanFull(cur->attributeSets,
-               (xmlHashScannerFull) xsltMergeSASCallback, style);
-           /*
-            * the attribute lists have either been migrated to style
-            * or freed directly in xsltMergeSASCallback()
-            */
-           xmlHashFree(cur->attributeSets, NULL);
-           cur->attributeSets = NULL;
+               (xmlHashScannerFull) xsltResolveSASCallback, &asctx);
+
+            if (cur != style) {
+                /*
+                 * the attribute lists have either been migrated to style
+                 * or freed directly in xsltResolveSASCallback()
+                 */
+                xmlHashFree(cur->attributeSets, NULL);
+                cur->attributeSets = NULL;
+            }
        }
        cur = xsltNextImport(cur);
     }
-
-    /*
-     * Then resolve all the references and computes the resulting sets
-     */
-    if (style->attributeSets != NULL) {
-       xmlHashScanFull(style->attributeSets,
-               (xmlHashScannerFull) xsltResolveSASCallback, style);
-    }
 }
 
 /**
- * xsltAttributeInternal:
+ * xsltAttribute:
  * @ctxt:  a XSLT process context
- * @node:  the current node in the source tree
+ * @contextNode:  the current node in the source tree
  * @inst:  the xsl:attribute element
- * @comp:  precomputed information
- * @fromAttributeSet:  the attribute comes from an attribute-set
+ * @castedComp:  precomputed information
  *
  * Process the xslt attribute node on the source node
  */
-static void
-xsltAttributeInternal(xsltTransformContextPtr ctxt,
-                     xmlNodePtr contextNode,
-                      xmlNodePtr inst,
-                     xsltStylePreCompPtr castedComp,
-                      int fromAttributeSet)
+void
+xsltAttribute(xsltTransformContextPtr ctxt,
+             xmlNodePtr contextNode,
+              xmlNodePtr inst,
+             xsltStylePreCompPtr castedComp)
 {
 #ifdef XSLT_REFACTORED
     xsltStyleItemAttributePtr comp =
@@ -666,7 +754,7 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
 
     if (comp == NULL) {
         xsltTransformError(ctxt, NULL, inst,
-           "Internal error in xsltAttributeInternal(): "
+           "Internal error in xsltAttribute(): "
            "The XSLT 'attribute' instruction was not compiled.\n");
         return;
     }
@@ -831,19 +919,6 @@ xsltAttributeInternal(xsltTransformContextPtr ctxt,
            nsName = ns->href;
     }
 
-    if (fromAttributeSet) {
-       /*
-       * This tries to ensure that xsl:attribute(s) coming
-       * from an xsl:attribute-set won't override attribute of
-       * literal result elements or of explicit xsl:attribute(s).
-       * URGENT TODO: This might be buggy, since it will miss to
-       *  overwrite two equal attributes both from attribute sets.
-       */
-       attr = xmlHasNsProp(targetElem, name, nsName);
-       if (attr != NULL)
-           return;
-    }
-
     /*
     * Find/create a matching ns-decl in the result tree.
     */
@@ -993,21 +1068,6 @@ error:
     return;
 }
 
-/**
- * xsltAttribute:
- * @ctxt:  a XSLT process context
- * @node:  the node in the source tree.
- * @inst:  the xslt attribute node
- * @comp:  precomputed information
- *
- * Process the xslt attribute node on the source node
- */
-void
-xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
-             xmlNodePtr inst, xsltStylePreCompPtr comp) {
-    xsltAttributeInternal(ctxt, node, inst, comp, 0);
-}
-
 /**
  * xsltApplyAttributeSet:
  * @ctxt:  the XSLT stylesheet
@@ -1028,7 +1088,7 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
     const xmlChar *ncname = NULL;
     const xmlChar *prefix = NULL;
     const xmlChar *curstr, *endstr;
-    xsltAttrElemPtr attrs;
+    xsltAttrSetPtr set;
     xsltStylesheetPtr style;
 
     if (attrSets == NULL) {
@@ -1065,15 +1125,32 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
             endstr++;
         curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr);
         if (curstr) {
-           /*
-           * TODO: Validate the QName.
-           */
+            xmlNsPtr ns;
+            const xmlChar *nsUri = NULL;
 
-#ifdef WITH_XSLT_DEBUG_curstrUTES
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
             xsltGenericDebug(xsltGenericDebugContext,
-                             "apply curstrute set %s\n", curstr);
+                             "apply attribute set %s\n", curstr);
 #endif
+
+            if (xmlValidateQName(curstr, 0)) {
+                xsltTransformError(ctxt, NULL, inst,
+                    "The name '%s' in use-attribute-sets is not a valid "
+                    "QName.\n", curstr);
+                return;
+            }
+
             ncname = xsltSplitQName(ctxt->dict, curstr, &prefix);
+            if (prefix != NULL) {
+               ns = xmlSearchNs(inst->doc, inst, prefix);
+                if (ns == NULL) {
+                    xsltTransformError(ctxt, NULL, inst,
+                        "use-attribute-set : No namespace found for QName "
+                        "'%s:%s'\n", prefix, ncname);
+                    return;
+                }
+                nsUri = ns->href;
+            }
 
             style = ctxt->style;
 
@@ -1082,27 +1159,28 @@ xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
                (style->attributeSets != NULL) &&
                (ctxt->debugStatus != XSLT_DEBUG_NONE))
            {
-                attrs =
-                    xmlHashLookup2(style->attributeSets, ncname, prefix);
-                if ((attrs != NULL) && (attrs->attr != NULL))
-                    xslHandleDebugger(attrs->attr->parent, node, NULL,
+                set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
+                if ((set != NULL) && (set->attrs != NULL) &&
+                    (set->attrs->attr != NULL))
+                    xslHandleDebugger(set->attrs->attr->parent, node, NULL,
                        ctxt);
             }
 #endif
            /*
-           * Lookup the referenced curstrute-set.
+           * Lookup the referenced attribute-set. All attribute sets were
+            * moved to the top stylesheet so there's no need to iterate
+            * imported stylesheets
            */
-            while (style != NULL) {
-                attrs =
-                    xmlHashLookup2(style->attributeSets, ncname, prefix);
-                while (attrs != NULL) {
-                    if (attrs->attr != NULL) {
-                        xsltAttributeInternal(ctxt, node, attrs->attr,
-                           attrs->attr->psvi, 1);
+            set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
+            if (set != NULL) {
+                xsltAttrElemPtr cur = set->attrs;
+                while (cur != NULL) {
+                    if (cur->attr != NULL) {
+                        xsltAttribute(ctxt, node, cur->attr,
+                            cur->attr->psvi);
                     }
-                    attrs = attrs->next;
+                    cur = cur->next;
                 }
-                style = xsltNextImport(style);
             }
         }
         curstr = endstr;
@@ -1119,6 +1197,6 @@ void
 xsltFreeAttributeSetsHashes(xsltStylesheetPtr style) {
     if (style->attributeSets != NULL)
        xmlHashFree((xmlHashTablePtr) style->attributeSets,
-                   (xmlHashDeallocator) xsltFreeAttrElemList);
+                   (xmlHashDeallocator) xsltFreeAttrSet);
     style->attributeSets = NULL;
 }
index 4c0763f..58c9913 100644 (file)
@@ -372,8 +372,7 @@ xsltExtModuleRegisterDynamic(const xmlChar * URI)
 
     /* build the module filename, and confirm the module exists */
     xmlStrPrintf((xmlChar *) module_filename, sizeof(module_filename),
-                 BAD_CAST "%s/%s%s",
-                 ext_directory, ext_name, LIBXML_MODULE_EXTENSION);
+                 "%s/%s%s", ext_directory, ext_name, LIBXML_MODULE_EXTENSION);
 
 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
     xsltGenericDebug(xsltGenericDebugContext,
index bfcd953..71fe28a 100644 (file)
@@ -76,7 +76,10 @@ xsltDebug(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,
                 xsltGenericError(xsltGenericErrorContext, "noname !!!!");
 #ifdef LIBXML_DEBUG_ENABLED
             if (cur->value != NULL) {
-                xmlXPathDebugDumpObject(stdout, cur->value, 1);
+                if ((xsltGenericDebugContext == stdout) ||
+                    (xsltGenericDebugContext == stderr))
+                    xmlXPathDebugDumpObject((FILE*)xsltGenericDebugContext,
+                                            cur->value, 1);
             } else {
                 xsltGenericError(xsltGenericErrorContext, "NULL !!!!");
             }
@@ -125,134 +128,6 @@ xsltFunctionNodeSet(xmlXPathParserContextPtr ctxt, int nargs){
     }
 }
 
-
-/*
- * Okay the following really seems unportable and since it's not
- * part of any standard I'm not too ashamed to do this
- */
-#if defined(linux) || defined(__sun)
-#if defined(HAVE_MKTIME) && defined(HAVE_LOCALTIME) && defined(HAVE_ASCTIME)
-#define WITH_LOCALTIME
-
-/**
- * xsltFunctionLocalTime:
- * @ctxt:  the XPath Parser context
- * @nargs:  the number of arguments
- *
- * Implement the localTime XSLT function used by NORM
- *   string localTime(???)
- *
- * This function is available in Norm's extension namespace
- * Code (and comments) contributed by Norm
- */
-static void
-xsltFunctionLocalTime(xmlXPathParserContextPtr ctxt, int nargs) {
-    xmlXPathObjectPtr obj;
-    char *str;
-    char digits[5];
-    char result[29];
-    long int field;
-    time_t gmt, lmt;
-    struct tm gmt_tm;
-    struct tm *local_tm;
-
-    if (nargs != 1) {
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
-                      "localTime() : invalid number of args %d\n", nargs);
-       ctxt->error = XPATH_INVALID_ARITY;
-       return;
-    }
-
-    obj = valuePop(ctxt);
-
-    if (obj->type != XPATH_STRING) {
-       obj = xmlXPathConvertString(obj);
-    }
-    if (obj == NULL) {
-       valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
-       return;
-    }
-
-    str = (char *) obj->stringval;
-
-    /* str = "$Date$" */
-    memset(digits, 0, sizeof(digits));
-    strncpy(digits, str+7, 4);
-    field = strtol(digits, NULL, 10);
-    gmt_tm.tm_year = field - 1900;
-
-    memset(digits, 0, sizeof(digits));
-    strncpy(digits, str+12, 2);
-    field = strtol(digits, NULL, 10);
-    gmt_tm.tm_mon = field - 1;
-
-    memset(digits, 0, sizeof(digits));
-    strncpy(digits, str+15, 2);
-    field = strtol(digits, NULL, 10);
-    gmt_tm.tm_mday = field;
-
-    memset(digits, 0, sizeof(digits));
-    strncpy(digits, str+18, 2);
-    field = strtol(digits, NULL, 10);
-    gmt_tm.tm_hour = field;
-
-    memset(digits, 0, sizeof(digits));
-    strncpy(digits, str+21, 2);
-    field = strtol(digits, NULL, 10);
-    gmt_tm.tm_min = field;
-
-    memset(digits, 0, sizeof(digits));
-    strncpy(digits, str+24, 2);
-    field = strtol(digits, NULL, 10);
-    gmt_tm.tm_sec = field;
-
-    /* Now turn gmt_tm into a time. */
-    gmt = mktime(&gmt_tm);
-
-
-    /*
-     * FIXME: it's been too long since I did manual memory management.
-     * (I swore never to do it again.) Does this introduce a memory leak?
-     */
-    local_tm = localtime(&gmt);
-
-    /*
-     * Calling localtime() has the side-effect of setting timezone.
-     * After we know the timezone, we can adjust for it
-     */
-#if !defined(__FreeBSD__)
-    lmt = gmt - timezone;
-#else  /* FreeBSD DOESN'T have such side-ffect */
-    lmt = gmt - local_tm->tm_gmtoff;
-#endif
-    /*
-     * FIXME: it's been too long since I did manual memory management.
-     * (I swore never to do it again.) Does this introduce a memory leak?
-     */
-    local_tm = localtime(&lmt);
-
-    /*
-     * Now convert local_tm back into a string. This doesn't introduce
-     * a memory leak, so says asctime(3).
-     */
-
-    str = asctime(local_tm);           /* "Tue Jun 26 05:02:16 2001" */
-                                       /*  0123456789 123456789 123 */
-
-    memset(result, 0, sizeof(result)); /* "Thu, 26 Jun 2001" */
-                                       /*  0123456789 12345 */
-
-    strncpy(result, str, 20);
-    strcpy(result+20, "???");          /* tzname doesn't work, fake it */
-    strncpy(result+23, str+19, 5);
-
-    /* Ok, now result contains the string I want to send back. */
-    valuePush(ctxt, xmlXPathNewString((xmlChar *)result));
-}
-#endif
-#endif /* linux or sun */
-
-
 /**
  * xsltRegisterExtras:
  * @ctxt:  a XSLT process context
@@ -281,11 +156,6 @@ xsltRegisterAllExtras (void) {
     xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
                                  XSLT_XT_NAMESPACE,
                                  xsltFunctionNodeSet);
-#ifdef WITH_LOCALTIME
-    xsltRegisterExtModuleFunction((const xmlChar *) "localTime",
-                                 XSLT_NORM_SAXON_NAMESPACE,
-                                 xsltFunctionLocalTime);
-#endif
     xsltRegisterExtModuleElement((const xmlChar *) "debug",
                                 XSLT_LIBXSLT_NAMESPACE,
                                 NULL,
index 6929e3c..1b36d56 100644 (file)
@@ -48,14 +48,6 @@ extern "C" {
 #define XSLT_XALAN_NAMESPACE ((xmlChar *)      \
                                "org.apache.xalan.xslt.extensions.Redirect")
 
-/**
- * XSLT_NORM_SAXON_NAMESPACE:
- *
- * This is Norm's namespace for SAXON extensions.
- */
-#define XSLT_NORM_SAXON_NAMESPACE ((xmlChar *) \
-       "http://nwalsh.com/xslt/ext/com.nwalsh.saxon.CVS")
-
 
 XSLTPUBFUN void XSLTCALL
                xsltFunctionNodeSet     (xmlXPathParserContextPtr ctxt,
index 41a58d3..decb3d9 100644 (file)
@@ -575,12 +575,15 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
     xmlXPathObjectPtr formatObj = NULL;
     xmlXPathObjectPtr decimalObj = NULL;
     xsltStylesheetPtr sheet;
-    xsltDecimalFormatPtr formatValues;
+    xsltDecimalFormatPtr formatValues = NULL;
     xmlChar *result;
+    const xmlChar *ncname;
+    const xmlChar *prefix = NULL;
+    const xmlChar *nsUri = NULL;
     xsltTransformContextPtr tctxt;
 
     tctxt = xsltXPathGetTransformContext(ctxt);
-    if (tctxt == NULL)
+    if ((tctxt == NULL) || (tctxt->inst == NULL))
        return;
     sheet = tctxt->style;
     if (sheet == NULL)
@@ -591,7 +594,23 @@ xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
     case 3:
        CAST_TO_STRING;
        decimalObj = valuePop(ctxt);
-       formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval);
+        ncname = xsltSplitQName(sheet->dict, decimalObj->stringval, &prefix);
+        if (prefix != NULL) {
+            xmlNsPtr ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, prefix);
+            if (ns == NULL) {
+                xsltTransformError(tctxt, NULL, NULL,
+                    "format-number : No namespace found for QName '%s:%s'\n",
+                    prefix, ncname);
+                sheet->errors++;
+                ncname = NULL;
+            }
+            else {
+                nsUri = ns->href;
+            }
+        }
+        if (ncname != NULL) {
+           formatValues = xsltDecimalFormatGetByQName(sheet, nsUri, ncname);
+        }
        if (formatValues == NULL) {
            xsltTransformError(tctxt, NULL, NULL,
                    "format-number() : undeclared decimal format '%s'\n",
@@ -807,7 +826,7 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
     }
     obj = valuePop(ctxt);
     tctxt = xsltXPathGetTransformContext(ctxt);
-    if (tctxt == NULL) {
+    if ((tctxt == NULL) || (tctxt->inst == NULL)) {
        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
                "element-available() : internal error tctxt == NULL\n");
        xmlXPathFreeObject(obj);
@@ -822,7 +841,7 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
 
        name = xmlStrdup(obj->stringval);
        ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
-       if (ns != NULL) nsURI = xmlStrdup(ns->href);
+       if (ns != NULL) nsURI = ns->href;
     } else {
        nsURI = xmlXPathNsLookup(ctxt->context, prefix);
        if (nsURI == NULL) {
index e3a929c..9170538 100644 (file)
@@ -384,10 +384,13 @@ xsltAddKey(xsltStylesheetPtr style, const xmlChar *name,
        prev->next = key;
     }
     key->next = NULL;
+    key = NULL;
 
 error:
     if (pattern != NULL)
        xmlFree(pattern);
+    if (key != NULL)
+        xsltFreeKeyDef(key);
     return(0);
 }
 
index 790300d..470ee32 100644 (file)
@@ -48,39 +48,11 @@ static xsltFormatToken default_token;
 /*
  * **** Start temp insert ****
  *
- * The following two routines (xsltUTF8Size and xsltUTF8Charcmp)
- * will be replaced with calls to the corresponding libxml routines
- * at a later date (when other inter-library dependencies require it)
+ * The following routine xsltUTF8Charcmp will be replaced with calls to
+ * the corresponding libxml routine at a later date (when other
+ * inter-library dependencies require it).
  */
 
-/**
- * xsltUTF8Size:
- * @utf: pointer to the UTF8 character
- *
- * returns the numbers of bytes in the character, -1 on format error
- */
-static int
-xsltUTF8Size(xmlChar *utf) {
-    xmlChar mask;
-    int len;
-
-    if (utf == NULL)
-        return -1;
-    if (*utf < 0x80)
-        return 1;
-    /* check valid UTF8 character */
-    if (!(*utf & 0x40))
-        return -1;
-    /* determine number of bytes in char */
-    len = 2;
-    for (mask=0x20; mask != 0; mask>>=1) {
-        if (!(*utf & mask))
-            return len;
-        len++;
-    }
-    return -1;
-}
-
 /**
  * xsltUTF8Charcmp
  * @utf1: pointer to first UTF8 char
@@ -91,13 +63,16 @@ xsltUTF8Size(xmlChar *utf) {
  */
 static int
 xsltUTF8Charcmp(xmlChar *utf1, xmlChar *utf2) {
+    int len = xmlUTF8Strsize(utf1, 1);
 
+    if (len < 1)
+        return -1;
     if (utf1 == NULL ) {
         if (utf2 == NULL)
             return 0;
         return -1;
     }
-    return xmlStrncmp(utf1, utf2, xsltUTF8Size(utf1));
+    return xmlStrncmp(utf1, utf2, len);
 }
 
 /***** Stop temp insert *****/
@@ -205,7 +180,7 @@ xsltNumberFormatDecimal(xmlBufferPtr buffer,
     }
     if (i < 0)
         xsltGenericError(xsltGenericErrorContext,
-               "xsltNumberFormatDecimal: Internal buffer size exceeded");
+               "xsltNumberFormatDecimal: Internal buffer size exceeded\n");
     xmlBufferCat(buffer, pointer);
 }
 
@@ -599,25 +574,7 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
 {
     int amount = 0;
     int cnt = 0;
-    xmlNodePtr cur;
-
-    /* select the starting node */
-    switch (node->type) {
-       case XML_ELEMENT_NODE:
-           cur = node;
-           break;
-       case XML_ATTRIBUTE_NODE:
-           cur = ((xmlAttrPtr) node)->parent;
-           break;
-       case XML_TEXT_NODE:
-       case XML_PI_NODE:
-       case XML_COMMENT_NODE:
-           cur = node->parent;
-           break;
-       default:
-           cur = NULL;
-           break;
-    }
+    xmlNodePtr cur = node;
 
     while (cur != NULL) {
        /* process current node */
@@ -636,16 +593,25 @@ xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
             (cur->type == XML_HTML_DOCUMENT_NODE))
            break; /* while */
 
-       while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) ||
-              (cur->prev->type == XML_XINCLUDE_START) ||
-              (cur->prev->type == XML_XINCLUDE_END)))
-           cur = cur->prev;
-       if (cur->prev != NULL) {
-           for (cur = cur->prev; cur->last != NULL; cur = cur->last);
-       } else {
-           cur = cur->parent;
-       }
-
+        if (cur->type == XML_NAMESPACE_DECL) {
+            /*
+            * The XPath module stores the parent of a namespace node in
+            * the ns->next field.
+            */
+            cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
+        } else if (cur->type == XML_ATTRIBUTE_NODE) {
+            cur = cur->parent;
+        } else {
+            while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) ||
+                   (cur->prev->type == XML_XINCLUDE_START) ||
+                   (cur->prev->type == XML_XINCLUDE_END)))
+                cur = cur->prev;
+            if (cur->prev != NULL) {
+                for (cur = cur->prev; cur->last != NULL; cur = cur->last);
+            } else {
+                cur = cur->parent;
+            }
+        }
     }
 
     array[amount++] = (double) cnt;
@@ -891,7 +857,7 @@ xsltFormatNumberPreSuffix(xsltDecimalFormatPtr self, xmlChar **format, xsltForma
            }
        }
 
-       if ((len=xsltUTF8Size(*format)) < 1)
+       if ((len=xmlUTF8Strsize(*format, 1)) < 1)
            return -1;
        count += len;
        *format += len;
@@ -1073,7 +1039,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
        } else
            break; /* while */
 
-       if ((len=xsltUTF8Size(the_format)) < 1) {
+       if ((len=xmlUTF8Strsize(the_format, 1)) < 1) {
            found_error = 1;
            goto OUTPUT_NUMBER;
        }
@@ -1082,9 +1048,14 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
     }
 
     /* We have finished the integer part, now work on fraction */
-    if (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) {
+    if ( (*the_format != 0) &&
+         (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) ) {
         format_info.add_decimal = TRUE;
-       the_format += xsltUTF8Size(the_format); /* Skip over the decimal */
+        if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
+            found_error = 1;
+            goto OUTPUT_NUMBER;
+        }
+       the_format += len;      /* Skip over the decimal */
     }
 
     while (*the_format != 0) {
@@ -1103,7 +1074,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
                goto OUTPUT_NUMBER;
            }
            delayed_multiplier = 100;
-           if ((len = xsltUTF8Size(the_format)) < 1) {
+           if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
                found_error = 1;
                goto OUTPUT_NUMBER;
            }
@@ -1115,7 +1086,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
                goto OUTPUT_NUMBER;
            }
            delayed_multiplier = 1000;
-           if  ((len = xsltUTF8Size(the_format)) < 1) {
+           if  ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
                found_error = 1;
                goto OUTPUT_NUMBER;
            }
@@ -1124,7 +1095,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
        } else if (xsltUTF8Charcmp(the_format, self->grouping) != 0) {
            break; /* while */
        }
-       if ((len = xsltUTF8Size(the_format)) < 1) {
+       if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
            found_error = 1;
            goto OUTPUT_NUMBER;
        }
@@ -1201,7 +1172,7 @@ xsltFormatNumberConversion(xsltDecimalFormatPtr self,
                    delayed_multiplier = 0;
                else
                    break; /* while */
-               if ((len = xsltUTF8Size(the_format)) < 1) {
+               if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
                    found_error = 1;
                    goto OUTPUT_NUMBER;
                }
@@ -1267,12 +1238,12 @@ OUTPUT_NUMBER:
 
     /* Ready to output our number.  First see if "default sign" is required */
     if (default_sign != 0)
-       xmlBufferAdd(buffer, self->minusSign, xsltUTF8Size(self->minusSign));
+       xmlBufferAdd(buffer, self->minusSign, xmlUTF8Strsize(self->minusSign, 1));
 
     /* Put the prefix into the buffer */
     for (j = 0; j < prefix_length; j++) {
        if ((pchar = *prefix++) == SYMBOL_QUOTE) {
-           len = xsltUTF8Size(prefix);
+           len = xmlUTF8Strsize(prefix, 1);
            xmlBufferAdd(buffer, prefix, len);
            prefix += len;
            j += len - 1;       /* length of symbol less length of quote */
@@ -1309,20 +1280,20 @@ OUTPUT_NUMBER:
     /* Add leading zero, if required */
     if ((floor(number) == 0) &&
        (format_info.integer_digits + format_info.frac_digits == 0)) {
-        xmlBufferAdd(buffer, self->zeroDigit, xsltUTF8Size(self->zeroDigit));
+        xmlBufferAdd(buffer, self->zeroDigit, xmlUTF8Strsize(self->zeroDigit, 1));
     }
 
     /* Next the fractional part, if required */
     if (format_info.frac_digits + format_info.frac_hash == 0) {
         if (format_info.add_decimal)
            xmlBufferAdd(buffer, self->decimalPoint,
-                        xsltUTF8Size(self->decimalPoint));
+                        xmlUTF8Strsize(self->decimalPoint, 1));
     }
     else {
       number -= floor(number);
        if ((number != 0) || (format_info.frac_digits != 0)) {
            xmlBufferAdd(buffer, self->decimalPoint,
-                        xsltUTF8Size(self->decimalPoint));
+                        xmlUTF8Strsize(self->decimalPoint, 1));
            number = floor(scale * number + 0.5);
            for (j = format_info.frac_hash; j > 0; j--) {
                if (fmod(number, 10.0) >= 1.0)
@@ -1337,7 +1308,7 @@ OUTPUT_NUMBER:
     /* Put the suffix into the buffer */
     for (j = 0; j < suffix_length; j++) {
        if ((pchar = *suffix++) == SYMBOL_QUOTE) {
-            len = xsltUTF8Size(suffix);
+            len = xmlUTF8Strsize(suffix, 1);
            xmlBufferAdd(buffer, suffix, len);
            suffix += len;
            j += len - 1;       /* length of symbol less length of escape */
index 62dfe0a..e27e940 100644 (file)
@@ -85,6 +85,7 @@ struct _xsltCompMatch {
     const xmlChar *mode;         /* the mode */
     const xmlChar *modeURI;      /* the mode URI */
     xsltTemplatePtr template;    /* the associated template */
+    xmlNodePtr node;             /* the containing element */
 
     int direct;
     /* TODO fix the statically allocated size steps[] */
@@ -895,7 +896,9 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
                  xmlNodePtr matchNode, const xmlChar *mode,
                  const xmlChar *modeURI) {
     int i;
+    int found = 0;
     xmlNodePtr node = matchNode;
+    xmlNodePtr oldInst;
     xsltStepOpPtr step, sel = NULL;
     xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
 
@@ -929,6 +932,10 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
            return(0);
     }
 
+    /* Some XPath functions rely on inst being set correctly. */
+    oldInst = ctxt->inst;
+    ctxt->inst = comp->node;
+
     i = 0;
 restart:
     for (;i < comp->nbStep;i++) {
@@ -1121,12 +1128,9 @@ restart:
                 * as possible this costly computation.
                 */
                if (comp->direct) {
-                   if (states.states != NULL) {
-                       /* Free the rollback states */
-                       xmlFree(states.states);
-                   }
-                   return(xsltTestCompMatchDirect(ctxt, comp, matchNode,
-                                                  comp->nsList, comp->nsNr));
+                   found = xsltTestCompMatchDirect(ctxt, comp, matchNode,
+                                                   comp->nsList, comp->nsNr);
+                    goto exit;
                }
 
                if (!xsltTestPredicateMatch(ctxt, comp, node, step, sel))
@@ -1166,18 +1170,19 @@ restart:
        }
     }
 found:
+    found = 1;
+exit:
+    ctxt->inst = oldInst;
     if (states.states != NULL) {
         /* Free the rollback states */
        xmlFree(states.states);
     }
-    return(1);
+    return found;
 rollback:
     /* got an error try to rollback */
-    if (states.states == NULL)
-       return(0);
-    if (states.nbstates <= 0) {
-       xmlFree(states.states);
-       return(0);
+    if (states.states == NULL || states.nbstates <= 0) {
+        found = 0;
+       goto exit;
     }
     states.nbstates--;
     i = states.states[states.nbstates].step;
@@ -1456,6 +1461,7 @@ xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
                xsltTransformError(NULL, NULL, NULL,
                        "xsltCompileIdKeyPattern : ) expected\n");
                ctxt->error = 1;
+                xmlFree(lit);
                return;
            }
        }
@@ -1618,6 +1624,7 @@ parse_node_test:
                    xsltTransformError(NULL, NULL, NULL,
                            "xsltCompileStepPattern : Name expected\n");
                    ctxt->error = 1;
+                    xmlFree(URL);
                    goto error;
                }
            } else {
@@ -1925,6 +1932,7 @@ xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc,
            goto error;
        ctxt->cur = &(ctxt->base)[current - start];
        element->pattern = ctxt->base;
+        element->node = node;
        element->nsList = xmlGetNsList(doc, node);
        j = 0;
        if (element->nsList != NULL) {
index d47aa29..44d4983 100644 (file)
@@ -1394,9 +1394,6 @@ xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
        return;
     cur->psvi = comp;
 
-    if ((style == NULL) || (cur == NULL))
-       return;
-
     comp->numdata.doc = cur->doc;
     comp->numdata.node = cur;
     comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
@@ -2319,7 +2316,7 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
            xsltCheckInstructionElement(style, inst);
            inst->psvi = (void *) xsltDocumentComp(style, inst,
                                (xsltTransformFunction) xsltDocumentElem);
-       } else {
+       } else if ((style == NULL) || (style->forwards_compatible == 0)) {
            xsltTransformError(NULL, style, inst,
                 "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
            if (style != NULL) style->warnings++;
index 51b631c..6478cc5 100644 (file)
@@ -246,7 +246,7 @@ xsltCheckFilename (const char *path)
 {
 #ifdef HAVE_STAT
     struct stat stat_buffer;
-#if defined(WIN32) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
     DWORD dwAttrs;
 
     dwAttrs = GetFileAttributes(path);
@@ -351,7 +351,7 @@ xsltCheckWrite(xsltSecurityPrefsPtr sec,
     if ((uri->scheme == NULL) ||
        (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
 
-#if defined(WIN32) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__)
     if ((uri->path)&&(uri->path[0]=='/')&&
         (uri->path[1]!='\0')&&(uri->path[2]==':'))
     ret = xsltCheckWritePath(sec, ctxt, uri->path+1);
index a4d7364..f997cea 100644 (file)
@@ -45,6 +45,12 @@ xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
     xmlNodePtr oldInst;
     int oldProximityPosition, oldContextSize;
 
+    if ((ctxt == NULL) || (ctxt->inst == NULL)) {
+        xsltTransformError(ctxt, NULL, NULL,
+            "xsltEvalXPathPredicate: No context or instruction\n");
+        return(0);
+    }
+
     oldContextSize = ctxt->xpathCtxt->contextSize;
     oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
     oldNsNr = ctxt->xpathCtxt->nsNr;
@@ -106,6 +112,12 @@ xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
     int oldNsNr;
     xmlNsPtr *oldNamespaces;
 
+    if ((ctxt == NULL) || (ctxt->inst == NULL)) {
+        xsltTransformError(ctxt, NULL, NULL,
+            "xsltEvalXPathStringNs: No context or instruction\n");
+        return(0);
+    }
+
     oldInst = ctxt->inst;
     oldNode = ctxt->node;
     oldPos = ctxt->xpathCtxt->proximityPosition;
@@ -278,12 +290,12 @@ xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
                xsltTransformError(ctxt, NULL, inst,
                        "xsltAttrTemplateValueProcessNode: unmatched '{'\n");
                ret = xmlStrncat(ret, str, cur - str);
-               return(ret);
+               goto exit;
            }
            str++;
            expr = xmlStrndup(str, cur - str);
            if (expr == NULL)
-               return(ret);
+               goto exit;
            else if (*expr == '{') {
                ret = xmlStrcat(ret, expr);
                xmlFree(expr);
@@ -331,6 +343,7 @@ xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
        ret = xmlStrncat(ret, str, cur - str);
     }
 
+exit:
     if (nsList != NULL)
        xmlFree(nsList);
 
index 45ceaf1..5097b76 100644 (file)
@@ -23,6 +23,7 @@
 #ifdef WITH_XSLT_DEBUG
 #define WITH_XSLT_DEBUG_EXTRA
 #define WITH_XSLT_DEBUG_PROCESS
+#define WITH_XSLT_DEBUG_VARIABLE
 #endif
 
 #define XSLT_GENERATE_HTML_DOCTYPE
@@ -55,10 +56,9 @@ static xmlNsPtr
 xsltCopyNamespaceListInternal(xmlNodePtr node, xmlNsPtr cur);
 
 static xmlNodePtr
-xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
-                    xmlNodePtr invocNode,
-                    xmlNodePtr node,
-                    xmlNodePtr insert, int isLRE, int topElemVisited);
+xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
+            xmlNodePtr node, xmlNodePtr insert, int isLRE,
+            int topElemVisited);
 
 static void
 xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
@@ -434,7 +434,7 @@ xsltGetXIncludeDefault(void) {
     return(xsltDoXIncludeDefault);
 }
 
-unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL;
+static unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL;
 
 /**
  * xsltDebugSetDefaultTrace:
@@ -733,9 +733,6 @@ xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
  *                                                                     *
  ************************************************************************/
 
-xmlNodePtr xsltCopyTree(xsltTransformContextPtr ctxt,
-                        xmlNodePtr node, xmlNodePtr insert, int literal);
-
 /**
  * xsltAddChild:
  * @parent:  the parent node
@@ -751,7 +748,7 @@ static xmlNodePtr
 xsltAddChild(xmlNodePtr parent, xmlNodePtr cur) {
    xmlNodePtr ret;
 
-   if ((cur == NULL) || (parent == NULL))
+   if (cur == NULL)
        return(NULL);
    if (parent == NULL) {
        xmlFreeNode(cur);
@@ -783,13 +780,32 @@ xsltAddTextString(xsltTransformContextPtr ctxt, xmlNodePtr target,
         return(target);
 
     if (ctxt->lasttext == target->content) {
+        int minSize;
+
+        /* Check for integer overflow accounting for NUL terminator. */
+        if (len >= INT_MAX - ctxt->lasttuse) {
+            xsltTransformError(ctxt, NULL, target,
+                "xsltCopyText: text allocation failed\n");
+            return(NULL);
+        }
+        minSize = ctxt->lasttuse + len + 1;
 
-       if (ctxt->lasttuse + len >= ctxt->lasttsize) {
+        if (ctxt->lasttsize < minSize) {
            xmlChar *newbuf;
            int size;
+            int extra;
+
+            /* Double buffer size but increase by at least 100 bytes. */
+            extra = minSize < 100 ? 100 : minSize;
+
+            /* Check for integer overflow. */
+            if (extra > INT_MAX - ctxt->lasttsize) {
+                size = INT_MAX;
+            }
+            else {
+                size = ctxt->lasttsize + extra;
+            }
 
-           size = ctxt->lasttsize + len + 100;
-           size *= 2;
            newbuf = (xmlChar *) xmlRealloc(target->content,size);
            if (newbuf == NULL) {
                xsltTransformError(ctxt, NULL, target,
@@ -1090,7 +1106,7 @@ exit:
  *
  * Do a copy of an attribute.
  * Called by:
- *  - xsltCopyTreeInternal()
+ *  - xsltCopyTree()
  *  - xsltCopyOf()
  *  - xsltCopy()
  *
@@ -1191,7 +1207,7 @@ xsltShallowCopyAttr(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
  * @target element node.
  *
  * Called by:
- *  - xsltCopyTreeInternal()
+ *  - xsltCopyTree()
  *
  * Returns 0 on success and -1 on errors and internal errors.
  */
@@ -1313,7 +1329,7 @@ xsltShallowCopyElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
            *  copy over all namespace nodes in scope.
            *  The damn thing about this is, that we would need to
            *  use the xmlGetNsList(), for every single node; this is
-           *  also done in xsltCopyTreeInternal(), but only for the top node.
+           *  also done in xsltCopyTree(), but only for the top node.
            */
            if (node->ns != NULL) {
                if (isLRE) {
@@ -1371,7 +1387,7 @@ xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
     xmlNodePtr copy, ret = NULL;
 
     while (list != NULL) {
-       copy = xsltCopyTreeInternal(ctxt, invocNode,
+       copy = xsltCopyTree(ctxt, invocNode,
            list, insert, isLRE, topElemVisited);
        if (copy != NULL) {
            if (ret == NULL) {
@@ -1391,7 +1407,7 @@ xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
  * Do a copy of a namespace list. If @node is non-NULL the
  * new namespaces are added automatically.
  * Called by:
- *   xsltCopyTreeInternal()
+ *   xsltCopyTree()
  *
  * QUESTION: What is the exact difference between this function
  *  and xsltCopyNamespaceList() in "namespaces.c"?
@@ -1549,7 +1565,7 @@ occupied:
 }
 
 /**
- * xsltCopyTreeInternal:
+ * xsltCopyTree:
  * @ctxt:  the XSLT transformation context
  * @invocNode: responsible node in the stylesheet; used for error reports
  * @node:  the element node in the source tree
@@ -1568,10 +1584,9 @@ occupied:
  * Returns a pointer to the new tree, or NULL in case of error
  */
 static xmlNodePtr
-xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
-                    xmlNodePtr invocNode,
-                    xmlNodePtr node,
-                    xmlNodePtr insert, int isLRE, int topElemVisited)
+xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
+            xmlNodePtr node, xmlNodePtr insert, int isLRE,
+            int topElemVisited)
 {
     xmlNodePtr copy;
 
@@ -1627,7 +1642,7 @@ xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
        copy = xsltAddChild(insert, copy);
         if (copy == NULL) {
             xsltTransformError(ctxt, NULL, invocNode,
-            "xsltCopyTreeInternal: Copying of '%s' failed.\n", node->name);
+            "xsltCopyTree: Copying of '%s' failed.\n", node->name);
             return (copy);
         }
        /*
@@ -1758,34 +1773,11 @@ xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
        }
     } else {
        xsltTransformError(ctxt, NULL, invocNode,
-           "xsltCopyTreeInternal: Copying of '%s' failed.\n", node->name);
+           "xsltCopyTree: Copying of '%s' failed.\n", node->name);
     }
     return(copy);
 }
 
-/**
- * xsltCopyTree:
- * @ctxt:  the XSLT transformation context
- * @node:  the element node in the source tree
- * @insert:  the parent in the result tree
- * @literal:  indicates if @node is a Literal Result Element
- *
- * Make a copy of the full tree under the element node @node
- * and insert it as last child of @insert
- * For literal result element, some of the namespaces may not be copied
- * over according to section 7.1.
- * TODO: Why is this a public function?
- *
- * Returns a pointer to the new tree, or NULL in case of error
- */
-xmlNodePtr
-xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr node,
-            xmlNodePtr insert, int literal)
-{
-    return(xsltCopyTreeInternal(ctxt, node, node, insert, literal, 0));
-
-}
-
 /************************************************************************
  *                                                                     *
  *             Error/fallback processing                               *
@@ -1987,6 +1979,9 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
 
     /*
      * Handling of Elements: second pass, actual processing
+     *
+     * Note that params are passed to the next template. This matches
+     * XSLT 2.0 behavior but doesn't conform to XSLT 1.0.
      */
     oldSize = ctxt->xpathCtxt->contextSize;
     oldPos = ctxt->xpathCtxt->proximityPosition;
@@ -2266,30 +2261,28 @@ xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
 {
     xmlDocPtr cur = ctxt->localRVT, tmp;
 
-    while ((cur != NULL) && (cur != base)) {
-       if (cur->psvi == (void *) ((long) 1)) {
-           cur = (xmlDocPtr) cur->next;
-       } else {
-           tmp = cur;
-           cur = (xmlDocPtr) cur->next;
-
-           if (tmp == ctxt->localRVT)
-               ctxt->localRVT = cur;
+    if (cur == base)
+        return;
+    if (cur->prev != NULL)
+        xsltTransformError(ctxt, NULL, NULL, "localRVT not head of list\n");
 
-           /*
-           * We need ctxt->localRVTBase for extension instructions
-           * which return values (like EXSLT's function).
-           */
-           if (tmp == ctxt->localRVTBase)
-               ctxt->localRVTBase = cur;
+    do {
+        tmp = cur;
+        cur = (xmlDocPtr) cur->next;
+        if (tmp->psvi == XSLT_RVT_LOCAL) {
+            xsltReleaseRVT(ctxt, tmp);
+        } else if (tmp->psvi == XSLT_RVT_GLOBAL) {
+            xsltRegisterPersistRVT(ctxt, tmp);
+        } else if (tmp->psvi != XSLT_RVT_FUNC_RESULT) {
+            xmlGenericError(xmlGenericErrorContext,
+                    "xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
+                    tmp->psvi);
+        }
+    } while (cur != base);
 
-           if (tmp->prev)
-               tmp->prev->next = (xmlNodePtr) cur;
-           if (cur)
-               cur->prev = tmp->prev;
-           xsltReleaseRVT(ctxt, tmp);
-       }
-    }
+    if (base != NULL)
+        base->prev = NULL;
+    ctxt->localRVT = base;
 }
 
 /**
@@ -2315,7 +2308,7 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
     xmlNodePtr oldInsert, oldInst, oldCurInst, oldContextNode;
     xmlNodePtr cur, insert, copy = NULL;
     int level = 0, oldVarsNr;
-    xmlDocPtr oldLocalFragmentTop, oldLocalFragmentBase;
+    xmlDocPtr oldLocalFragmentTop;
 
 #ifdef XSLT_REFACTORED
     xsltStylePreCompPtr info;
@@ -2343,6 +2336,24 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
         return;
     CHECK_STOPPED;
 
+    /*
+    * Check for infinite recursion: stop if the maximum of nested templates
+    * is excceeded. Adjust xsltMaxDepth if you need more.
+    */
+    if (ctxt->depth >= ctxt->maxTemplateDepth) {
+        xsltTransformError(ctxt, NULL, list,
+           "xsltApplySequenceConstructor: A potential infinite template "
+            "recursion was detected.\n"
+           "You can adjust xsltMaxDepth (--maxdepth) in order to "
+           "raise the maximum number of nested template calls and "
+           "variables/params (currently set to %d).\n",
+           ctxt->maxTemplateDepth);
+        xsltDebug(ctxt, contextNode, list, NULL);
+       ctxt->state = XSLT_STATE_STOPPED;
+        return;
+    }
+    ctxt->depth++;
+
     oldLocalFragmentTop = ctxt->localRVT;
     oldInsert = insert = ctxt->insert;
     oldInst = oldCurInst = ctxt->inst;
@@ -2642,17 +2653,22 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
                        "xsltApplySequenceConstructor: extension construct %s\n",
                        cur->name));
 #endif
+                    /*
+                     * Disable the xsltCopyTextString optimization for
+                     * extension elements. Extensions could append text using
+                     * xmlAddChild which will free the buffer pointed to by
+                     * 'lasttext'. This buffer could later be reallocated with
+                     * a different size than recorded in 'lasttsize'. See bug
+                     * #777432.
+                     */
+                    if (cur->psvi == xsltExtMarker) {
+                        ctxt->lasttext = NULL;
+                    }
+
                    ctxt->insert = insert;
-                   /*
-                   * We need the fragment base for extension instructions
-                   * which return values (like EXSLT's function).
-                   */
-                   oldLocalFragmentBase = ctxt->localRVTBase;
-                   ctxt->localRVTBase = NULL;
 
                    func(ctxt, contextNode, cur, cur->psvi);
 
-                   ctxt->localRVTBase = oldLocalFragmentBase;
                    /*
                    * Cleanup temporary tree fragments.
                    */
@@ -2716,12 +2732,9 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
                oldCurInst = ctxt->inst;
                ctxt->inst = cur;
                 ctxt->insert = insert;
-               oldLocalFragmentBase = ctxt->localRVTBase;
-               ctxt->localRVTBase = NULL;
 
                 info->func(ctxt, contextNode, cur, (xsltElemPreCompPtr) info);
 
-               ctxt->localRVTBase = oldLocalFragmentBase;
                /*
                * Cleanup temporary tree fragments.
                */
@@ -2835,13 +2848,19 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
                     cur->name));
 #endif
 
+                /*
+                 * Disable the xsltCopyTextString optimization for
+                 * extension elements. Extensions could append text using
+                 * xmlAddChild which will free the buffer pointed to by
+                 * 'lasttext'. This buffer could later be reallocated with
+                 * a different size than recorded in 'lasttsize'. See bug
+                 * #777432.
+                 */
+                if (cur->psvi == xsltExtMarker) {
+                   ctxt->lasttext = NULL;
+                }
+
                 ctxt->insert = insert;
-               /*
-               * We need the fragment base for extension instructions
-               * which return values (like EXSLT's function).
-               */
-               oldLocalFragmentBase = ctxt->localRVTBase;
-               ctxt->localRVTBase = NULL;
 
                 function(ctxt, contextNode, cur, cur->psvi);
                /*
@@ -2850,7 +2869,6 @@ xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
                if (oldLocalFragmentTop != ctxt->localRVT)
                    xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
 
-               ctxt->localRVTBase = oldLocalFragmentBase;
                 ctxt->insert = oldInsert;
 
             }
@@ -2992,6 +3010,8 @@ error:
     ctxt->inst = oldInst;
     ctxt->insert = oldInsert;
 
+    ctxt->depth--;
+
 #ifdef WITH_DEBUGGER
     if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) {
         xslDropCall();
@@ -3026,7 +3046,7 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
     long start = 0;
     xmlNodePtr cur;
     xsltStackElemPtr tmpParam = NULL;
-    xmlDocPtr oldUserFragmentTop, oldLocalFragmentTop;
+    xmlDocPtr oldUserFragmentTop;
 
 #ifdef XSLT_REFACTORED
     xsltStyleItemParamPtr iparam;
@@ -3058,23 +3078,6 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
         return;
     CHECK_STOPPED;
 
-    /*
-    * Check for infinite recursion: stop if the maximum of nested templates
-    * is excceeded. Adjust xsltMaxDepth if you need more.
-    */
-    if (ctxt->templNr >= ctxt->maxTemplateDepth)
-    {
-        xsltTransformError(ctxt, NULL, list,
-           "xsltApplyXSLTTemplate: A potential infinite template recursion "
-           "was detected.\n"
-           "You can adjust xsltMaxDepth (--maxdepth) in order to "
-           "raise the maximum number of nested template calls and "
-           "variables/params (currently set to %d).\n",
-           ctxt->maxTemplateDepth);
-        xsltDebug(ctxt, contextNode, list, NULL);
-        return;
-    }
-
     if (ctxt->varsNr >= ctxt->maxTemplateVars)
        {
         xsltTransformError(ctxt, NULL, list,
@@ -3084,12 +3087,12 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
            "raise the maximum number of variables/params (currently set to %d).\n",
            ctxt->maxTemplateVars);
         xsltDebug(ctxt, contextNode, list, NULL);
+       ctxt->state = XSLT_STATE_STOPPED;
         return;
        }
 
     oldUserFragmentTop = ctxt->tmpRVT;
     ctxt->tmpRVT = NULL;
-    oldLocalFragmentTop = ctxt->localRVT;
 
     /*
     * Initiate a distinct scope of local params/variables.
@@ -3190,31 +3193,6 @@ xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
        xsltTemplateParamsCleanup(ctxt);
     ctxt->varsBase = oldVarsBase;
 
-    /*
-    * Clean up remaining local tree fragments.
-    * This also frees fragments which are the result of
-    * extension instructions. Should normally not be hit; but
-    * just for the case xsltExtensionInstructionResultFinalize()
-    * was not called by the extension author.
-    */
-    if (oldLocalFragmentTop != ctxt->localRVT) {
-       xmlDocPtr curdoc = ctxt->localRVT, tmp;
-
-       do {
-           tmp = curdoc;
-           curdoc = (xmlDocPtr) curdoc->next;
-           /* Need to housekeep localRVTBase */
-           if (tmp == ctxt->localRVTBase)
-               ctxt->localRVTBase = curdoc;
-           if (tmp->prev)
-               tmp->prev->next = (xmlNodePtr) curdoc;
-           if (curdoc)
-               curdoc->prev = tmp->prev;
-           xsltReleaseRVT(ctxt, tmp);
-       } while (curdoc != oldLocalFragmentTop);
-    }
-    ctxt->localRVT = oldLocalFragmentTop;
-
     /*
     * Release user-created fragments stored in the scope
     * of xsl:template. Note that this mechanism is deprecated:
@@ -3820,7 +3798,6 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
        xsltTransformError(ctxt, NULL, inst,
                          "xsltDocumentElem: unable to save to %s\n",
                          filename);
-       ctxt->state = XSLT_STATE_ERROR;
 #ifdef WITH_XSLT_DEBUG_EXTRA
     } else {
         xsltGenericDebug(xsltGenericDebugContext,
@@ -4433,8 +4410,7 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
                        xsltShallowCopyAttr(ctxt, inst,
                            ctxt->insert, (xmlAttrPtr) cur);
                    } else {
-                       xsltCopyTreeInternal(ctxt, inst,
-                           cur, ctxt->insert, 0, 0);
+                       xsltCopyTree(ctxt, inst, cur, ctxt->insert, 0, 0);
                    }
                }
            }
@@ -4685,6 +4661,10 @@ xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
 
        ctxt->currentTemplateRule = oldCurTemplRule;
     }
+    else {
+        /* Use built-in templates. */
+        xsltDefaultProcessOneNode(ctxt, contextNode, NULL);
+    }
 }
 
 /**
@@ -5632,6 +5612,7 @@ typedef struct xsltHTMLVersion {
 } xsltHTMLVersion;
 
 static xsltHTMLVersion xsltHTMLVersions[] = {
+    { "5", NULL, "about:legacy-compat" },
     { "4.01frame", "-//W3C//DTD HTML 4.01 Frameset//EN",
       "http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd"},
     { "4.01strict", "-//W3C//DTD HTML 4.01//EN",
@@ -5857,7 +5838,8 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
      */
     root = xmlDocGetRootElement(doc);
     if (root != NULL) {
-       if (((long) root->content) >= 0 && (xslDebugStatus == XSLT_DEBUG_NONE))
+       if (((ptrdiff_t) root->content >= 0) &&
+            (xslDebugStatus == XSLT_DEBUG_NONE))
            xmlXPathOrderDocElems(doc);
     }
 
@@ -6007,6 +5989,9 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
 
     xsltEvalGlobalVariables(ctxt);
 
+    /* Clean up any unused RVTs. */
+    xsltReleaseLocalRVTs(ctxt, NULL);
+
     ctxt->node = (xmlNodePtr) doc;
     ctxt->output = res;
     ctxt->insert = (xmlNodePtr) res;
@@ -6151,7 +6136,7 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
     /*
      * Be pedantic.
      */
-    if ((ctxt != NULL) && (ctxt->state == XSLT_STATE_ERROR)) {
+    if ((ctxt != NULL) && (ctxt->state != XSLT_STATE_OK)) {
        xmlFreeDoc(res);
        res = NULL;
     }
index fcd201d..fffb0c9 100644 (file)
 const xmlChar *xsltDocFragFake = (const xmlChar *) " fake node libxslt";
 #endif
 
-const xmlChar *xsltComputingGlobalVarMarker =
+static const xmlChar *xsltComputingGlobalVarMarker =
  (const xmlChar *) " var/param being computed";
 
-#define XSLT_VAR_GLOBAL 1<<0
-#define XSLT_VAR_IN_SELECT 1<<1
+#define XSLT_VAR_GLOBAL (1<<0)
+#define XSLT_VAR_IN_SELECT (1<<1)
 #define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable)
 
 /************************************************************************
@@ -101,6 +101,9 @@ xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
     if ((ctxt == NULL) || (RVT == NULL))
        return(-1);
 
+    RVT->prev = NULL;
+    RVT->psvi = XSLT_RVT_VARIABLE;
+
     /*
     * We'll restrict the lifetime of user-created fragments
     * insinde an xsl:variable and xsl:param to the lifetime of the
@@ -138,15 +141,18 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
     if ((ctxt == NULL) || (RVT == NULL))
        return(-1);
 
+    RVT->prev = NULL;
+
     /*
     * When evaluating "select" expressions of xsl:variable
     * and xsl:param, we need to bind newly created tree fragments
-    * to the variable itself; otherwise the tragment will be
+    * to the variable itself; otherwise the fragment will be
     * freed before we leave the scope of a var.
     */
     if ((ctxt->contextVariable != NULL) &&
        (XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT))
     {
+        RVT->psvi = XSLT_RVT_VARIABLE;
        RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
        XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
        return(0);
@@ -156,19 +162,11 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
     * If not reference by a returning instruction (like EXSLT's function),
     * then this fragment will be freed, when the instruction exits.
     */
+    RVT->psvi = XSLT_RVT_LOCAL;
     RVT->next = (xmlNodePtr) ctxt->localRVT;
     if (ctxt->localRVT != NULL)
        ctxt->localRVT->prev = (xmlNodePtr) RVT;
     ctxt->localRVT = RVT;
-    /*
-    * We need to keep track of the first registered fragment
-    * for extension instructions which return fragments
-    * (e.g. EXSLT'S function), in order to let
-    * xsltExtensionInstructionResultFinalize() clear the
-    * preserving flag on the fragments.
-    */
-    if (ctxt->localRVTBase == NULL)
-       ctxt->localRVTBase = RVT;
     return(0);
 }
 
@@ -183,26 +181,16 @@ xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
  * collector will free them after the function-calling process exits.
  *
  * Returns 0 in case of success and -1 in case of API or internal errors.
+ *
+ * This function is unsupported in newer releases of libxslt.
  */
 int
 xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt)
 {
-    xmlDocPtr cur;
-
-    if (ctxt == NULL)
-       return(-1);
-    if (ctxt->localRVTBase == NULL)
-       return(0);
-    /*
-    * Enable remaining local tree fragments to be freed
-    * by the fragment garbage collector.
-    */
-    cur = ctxt->localRVTBase;
-    do {
-       cur->psvi = NULL;
-       cur = (xmlDocPtr) cur->next;
-    } while (cur != NULL);
-    return(0);
+    xmlGenericError(xmlGenericErrorContext,
+            "xsltExtensionInstructionResultFinalize is unsupported "
+            "in this release of libxslt.\n");
+    return(-1);
 }
 
 /**
@@ -217,11 +205,35 @@ xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt)
  * tree fragments (via xsltCreateRVT()) with xsltRegisterLocalRVT().
  *
  * Returns 0 in case of success and -1 in case of error.
+ *
+ * It isn't necessary to call this function in newer releases of
+ * libxslt.
  */
 int
 xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt,
                                       xmlXPathObjectPtr obj)
 {
+    return(0);
+}
+
+/**
+ * xsltFlagRVTs:
+ * @ctxt: an XSLT transformation context
+ * @obj: an XPath object to be inspected for result tree fragments
+ * @val: the flag value
+ *
+ * Updates ownership information of RVTs in @obj according to @val.
+ *
+ * @val = XSLT_RVT_FUNC_RESULT for the result of an extension function, so its
+ *        RVTs won't be destroyed after leaving the returning scope.
+ * @val = XSLT_RVT_LOCAL for the result of an extension function to reset
+ *        the state of its RVTs after it was returned to a new scope.
+ * @val = XSLT_RVT_GLOBAL for parts of global variables.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+int
+xsltFlagRVTs(xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val) {
     int i;
     xmlNodePtr cur;
     xmlDocPtr doc;
@@ -254,36 +266,59 @@ xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt,
                doc = cur->doc;
            } else {
                xsltTransformError(ctxt, NULL, ctxt->inst,
-                   "Internal error in "
-                   "xsltExtensionInstructionResultRegister(): "
+                   "Internal error in xsltFlagRVTs(): "
                    "Cannot retrieve the doc of a namespace node.\n");
-               goto error;
+               return(-1);
            }
        } else {
            doc = cur->doc;
        }
        if (doc == NULL) {
            xsltTransformError(ctxt, NULL, ctxt->inst,
-               "Internal error in "
-               "xsltExtensionInstructionResultRegister(): "
+               "Internal error in xsltFlagRVTs(): "
                "Cannot retrieve the doc of a node.\n");
-           goto error;
+           return(-1);
        }
-       if (doc->name && (doc->name[0] == ' ')) {
+       if (doc->name && (doc->name[0] == ' ') &&
+            doc->psvi != XSLT_RVT_GLOBAL) {
            /*
            * This is a result tree fragment.
-           * We'll use the @psvi field for reference counting.
-           * TODO: How do we know if this is a value of a
-           *  global variable or a doc acquired via the
+           * We store ownership information in the @psvi field.
+           * TODO: How do we know if this is a doc acquired via the
            *  document() function?
            */
-           doc->psvi = (void *) ((long) 1);
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+            XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                "Flagging RVT %p: %p -> %p\n", doc, doc->psvi, val));
+#endif
+
+            if (val == XSLT_RVT_LOCAL) {
+                if (doc->psvi != XSLT_RVT_FUNC_RESULT) {
+                   xmlGenericError(xmlGenericErrorContext,
+                            "xsltFlagRVTs: Invalid transition %p => LOCAL\n",
+                            doc->psvi);
+                    return(-1);
+                }
+
+                xsltRegisterLocalRVT(ctxt, doc);
+            } else if (val == XSLT_RVT_GLOBAL) {
+                if (doc->psvi != XSLT_RVT_LOCAL) {
+                   xmlGenericError(xmlGenericErrorContext,
+                            "xsltFlagRVTs: Invalid transition %p => GLOBAL\n",
+                            doc->psvi);
+                    doc->psvi = XSLT_RVT_GLOBAL;
+                    return(-1);
+                }
+
+                /* Will be registered as persistant in xsltReleaseLocalRVTs. */
+                doc->psvi = XSLT_RVT_GLOBAL;
+            } else if (val == XSLT_RVT_FUNC_RESULT) {
+               doc->psvi = val;
+            }
        }
     }
 
     return(0);
-error:
-    return(-1);
 }
 
 /**
@@ -329,9 +364,9 @@ xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
        }
 
        /*
-       * Reset the reference counter.
+       * Reset the ownership information.
        */
-       RVT->psvi = 0;
+       RVT->psvi = NULL;
 
        RVT->next = (xmlNodePtr) ctxt->cache->RVT;
        ctxt->cache->RVT = RVT;
@@ -370,6 +405,8 @@ xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
 {
     if ((ctxt == NULL) || (RVT == NULL)) return(-1);
 
+    RVT->psvi = XSLT_RVT_GLOBAL;
+    RVT->prev = NULL;
     RVT->next = (xmlNodePtr) ctxt->persistRVT;
     if (ctxt->persistRVT != NULL)
        ctxt->persistRVT->prev = (xmlNodePtr) RVT;
@@ -520,35 +557,21 @@ xsltFreeStackElem(xsltStackElemPtr elem) {
     /*
     * Release the list of temporary Result Tree Fragments.
     */
-    if (elem->fragment) {
+    if (elem->context) {
        xmlDocPtr cur;
 
        while (elem->fragment != NULL) {
            cur = elem->fragment;
            elem->fragment = (xmlDocPtr) cur->next;
 
-           if (elem->context &&
-               (cur->psvi == (void *) ((long) 1)))
-           {
-               /*
-               * This fragment is a result of an extension instruction
-               * (e.g. XSLT's function) and needs to be preserved until
-               * the instruction exits.
-               * Example: The fragment of the variable must not be freed
-               *  since it is returned by the EXSLT function:
-               *  <f:function name="foo">
-               *   <xsl:variable name="bar">
-               *     <bar/>
-               *   </xsl:variable>
-               *   <f:result select="$bar"/>
-               *  </f:function>
-               *
-               */
-               xsltRegisterLocalRVT(elem->context, cur);
-           } else {
+            if (cur->psvi == XSLT_RVT_VARIABLE) {
                xsltReleaseRVT((xsltTransformContextPtr) elem->context,
                    cur);
-           }
+            } else if (cur->psvi != XSLT_RVT_FUNC_RESULT) {
+                xmlGenericError(xmlGenericErrorContext,
+                        "xsltFreeStackElem: Unexpected RVT flag %p\n",
+                        cur->psvi);
+            }
        }
     }
     /*
@@ -942,6 +965,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
                * the Result Tree Fragment.
                */
                variable->fragment = container;
+                container->psvi = XSLT_RVT_VARIABLE;
 
                oldOutput = ctxt->output;
                oldInsert = ctxt->insert;
@@ -1128,16 +1152,23 @@ xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt)
                xsltTransformError(ctxt, NULL, comp->inst,
                    "Evaluating global variable %s failed\n", elem->name);
            ctxt->state = XSLT_STATE_STOPPED;
+            goto error;
+        }
+
+        /*
+         * Mark all RVTs that are referenced from result as part
+         * of this variable so they won't be freed too early.
+         */
+        xsltFlagRVTs(ctxt, result, XSLT_RVT_GLOBAL);
+
 #ifdef WITH_XSLT_DEBUG_VARIABLE
 #ifdef LIBXML_DEBUG_ENABLED
-       } else {
-           if ((xsltGenericDebugContext == stdout) ||
-               (xsltGenericDebugContext == stderr))
-               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
-                                       result, 0);
+       if ((xsltGenericDebugContext == stdout) ||
+           (xsltGenericDebugContext == stderr))
+           xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+                                   result, 0);
 #endif
 #endif
-       }
     } else {
        if (elem->tree == NULL) {
            result = xmlXPathNewCString("");
@@ -1751,8 +1782,7 @@ xsltBuildVariable(xsltTransformContextPtr ctxt,
     elem->tree = tree;
     elem->value = xsltEvalVariable(ctxt, elem,
        (xsltStylePreCompPtr) comp);
-    if (elem->value != NULL)
-       elem->computed = 1;
+    elem->computed = 1;
     return(elem);
 }
 
index d076c25..411f344 100644 (file)
@@ -247,7 +247,7 @@ xsltIsBlank(xmlChar *str) {
  *                                                                     *
  ************************************************************************/
 static xsltDecimalFormatPtr
-xsltNewDecimalFormat(xmlChar *name)
+xsltNewDecimalFormat(const xmlChar *nsUri, xmlChar *name)
 {
     xsltDecimalFormatPtr self;
     /* UTF-8 for 0x2030 */
@@ -256,6 +256,7 @@ xsltNewDecimalFormat(xmlChar *name)
     self = xmlMalloc(sizeof(xsltDecimalFormat));
     if (self != NULL) {
        self->next = NULL;
+        self->nsUri = nsUri;
        self->name = name;
 
        /* Default values */
@@ -341,7 +342,39 @@ xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)
        for (result = style->decimalFormat->next;
             result != NULL;
             result = result->next) {
-           if (xmlStrEqual(name, result->name))
+           if ((result->nsUri == NULL) && xmlStrEqual(name, result->name))
+               return result;
+       }
+       style = xsltNextImport(style);
+    }
+    return result;
+}
+
+/**
+ * xsltDecimalFormatGetByQName:
+ * @style: the XSLT stylesheet
+ * @nsUri: the namespace URI of the QName
+ * @name: the local part of the QName
+ *
+ * Find decimal-format by QName
+ *
+ * Returns the xsltDecimalFormatPtr
+ */
+xsltDecimalFormatPtr
+xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri,
+                            const xmlChar *name)
+{
+    xsltDecimalFormatPtr result = NULL;
+
+    if (name == NULL)
+       return style->decimalFormat;
+
+    while (style != NULL) {
+       for (result = style->decimalFormat->next;
+            result != NULL;
+            result = result->next) {
+           if (xmlStrEqual(nsUri, result->nsUri) &&
+                xmlStrEqual(name, result->name))
                return result;
        }
        style = xsltNextImport(style);
@@ -719,7 +752,7 @@ xsltNewStylesheet(void) {
 
     ret->omitXmlDeclaration = -1;
     ret->standalone = -1;
-    ret->decimalFormat = xsltNewDecimalFormat(NULL);
+    ret->decimalFormat = xsltNewDecimalFormat(NULL, NULL);
     ret->indent = -1;
     ret->errors = 0;
     ret->warnings = 0;
@@ -782,9 +815,8 @@ xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
            ctxt->extras = (xsltRuntimeExtraPtr)
                xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));
            if (ctxt->extras == NULL) {
-               xmlGenericError(xmlGenericErrorContext,
+               xsltTransformError(ctxt, NULL, NULL,
                        "xsltAllocateExtraCtxt: out of memory\n");
-               ctxt->state = XSLT_STATE_ERROR;
                return(0);
            }
            for (i = 0;i < ctxt->extrasMax;i++) {
@@ -800,9 +832,8 @@ xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
            tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras,
                            ctxt->extrasMax * sizeof(xsltRuntimeExtra));
            if (tmp == NULL) {
-               xmlGenericError(xmlGenericErrorContext,
+               xsltTransformError(ctxt, NULL, NULL,
                        "xsltAllocateExtraCtxt: out of memory\n");
-               ctxt->state = XSLT_STATE_ERROR;
                return(0);
            }
            ctxt->extras = tmp;
@@ -1181,6 +1212,7 @@ xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
                xsltTransformError(NULL, style, cur,
                                  "invalid value for method: %s\n", prop);
                 if (style != NULL) style->warnings++;
+                xmlFree(prop);
             }
        } else {
            style->method = prop;
@@ -1358,18 +1390,37 @@ xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)
 
     prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL);
     if (prop != NULL) {
-       format = xsltDecimalFormatGetByName(style, prop);
+        const xmlChar *nsUri;
+
+        if (xmlValidateQName(prop, 0) != 0) {
+            xsltTransformError(NULL, style, cur,
+                "xsl:decimal-format: Invalid QName '%s'.\n", prop);
+           style->warnings++;
+            xmlFree(prop);
+            return;
+        }
+        /*
+        * TODO: Don't use xsltGetQNameURI().
+        */
+        nsUri = xsltGetQNameURI(cur, &prop);
+        if (prop == NULL) {
+           style->warnings++;
+            return;
+        }
+       format = xsltDecimalFormatGetByQName(style, nsUri, prop);
        if (format != NULL) {
            xsltTransformError(NULL, style, cur,
         "xsltParseStylestyleDecimalFormat: %s already exists\n", prop);
-           if (style != NULL) style->warnings++;
+           style->warnings++;
+            xmlFree(prop);
            return;
        }
-       format = xsltNewDecimalFormat(prop);
+       format = xsltNewDecimalFormat(nsUri, prop);
        if (format == NULL) {
            xsltTransformError(NULL, style, cur,
      "xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");
-           if (style != NULL) style->errors++;
+           style->errors++;
+            xmlFree(prop);
            return;
        }
        /* Append new decimal-format structure */
@@ -3396,7 +3447,7 @@ internal_err:
 #ifdef XSLT_REFACTORED
 #else
 static void
-xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
+xsltPreprocessStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
 {
     xmlNodePtr deleteNode, styleelem;
     int internalize = 0;
@@ -3427,7 +3478,7 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
        if (deleteNode != NULL) {
 #ifdef WITH_XSLT_DEBUG_BLANKS
            xsltGenericDebug(xsltGenericDebugContext,
-            "xsltPrecomputeStylesheet: removing ignorable blank node\n");
+            "xsltPreprocessStylesheet: removing ignorable blank node\n");
 #endif
            xmlUnlinkNode(deleteNode);
            xmlFreeNode(deleteNode);
@@ -3467,7 +3518,6 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
            }
            if (IS_XSLT_ELEM(cur)) {
                exclPrefixes = 0;
-               xsltStylePreCompute(style, cur);
                if (IS_XSLT_NAME(cur, "text")) {
                    for (;exclPrefixes > 0;exclPrefixes--)
                        exclPrefixPop(style);
@@ -3518,7 +3568,7 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
             * going back
             */
            if (exclPrefixes > 0) {
-               xsltPrecomputeStylesheet(style, cur->children);
+               xsltPreprocessStylesheet(style, cur->children);
                for (;exclPrefixes > 0;exclPrefixes--)
                    exclPrefixPop(style);
                goto skip_children;
@@ -3589,7 +3639,7 @@ skip_children:
     if (deleteNode != NULL) {
 #ifdef WITH_XSLT_DEBUG_PARSING
        xsltGenericDebug(xsltGenericDebugContext,
-        "xsltPrecomputeStylesheet: removing ignorable blank node\n");
+        "xsltPreprocessStylesheet: removing ignorable blank node\n");
 #endif
        xmlUnlinkNode(deleteNode);
        xmlFreeNode(deleteNode);
@@ -4834,10 +4884,12 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
            delete = NULL;
        }
        if (IS_XSLT_ELEM(cur)) {
+            xsltStylePreCompute(style, cur);
+
            if (IS_XSLT_NAME(cur, "text")) {
                /*
                * TODO: Processing of xsl:text should be moved to
-               *   xsltPrecomputeStylesheet(), since otherwise this
+               *   xsltPreprocessStylesheet(), since otherwise this
                *   will be performed for every multiply included
                *   stylesheet; i.e. this here is not skipped with
                *   the use of the style->nopreproc flag.
@@ -5367,6 +5419,7 @@ xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
                xsltTransformError(NULL, style, template,
                    "xsl:template : error invalid name '%s'\n", prop);
                if (style != NULL) style->errors++;
+                xmlFree(prop);
                goto error;
            }
            ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);
@@ -6026,7 +6079,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
        if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
             (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
            xsltTransformError(NULL, style, top,
-               "xsl:version: only 1.0 features are supported\n");
+               "xsl:version: only 1.1 features are supported\n");
            if (style != NULL) {
                 style->forwards_compatible = 1;
                 style->warnings++;
@@ -6097,31 +6150,31 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
            xsltTransformError(NULL, style, cur,
                        "xsltParseStylesheetTop: ignoring misplaced import element\n");
            if (style != NULL) style->errors++;
-    } else if (IS_XSLT_NAME(cur, "include")) {
+        } else if (IS_XSLT_NAME(cur, "include")) {
            if (xsltParseStylesheetInclude(style, cur) != 0)
                if (style != NULL) style->errors++;
-    } else if (IS_XSLT_NAME(cur, "strip-space")) {
+        } else if (IS_XSLT_NAME(cur, "strip-space")) {
            xsltParseStylesheetStripSpace(style, cur);
-    } else if (IS_XSLT_NAME(cur, "preserve-space")) {
+        } else if (IS_XSLT_NAME(cur, "preserve-space")) {
            xsltParseStylesheetPreserveSpace(style, cur);
-    } else if (IS_XSLT_NAME(cur, "output")) {
+        } else if (IS_XSLT_NAME(cur, "output")) {
            xsltParseStylesheetOutput(style, cur);
-    } else if (IS_XSLT_NAME(cur, "key")) {
+        } else if (IS_XSLT_NAME(cur, "key")) {
            xsltParseStylesheetKey(style, cur);
-    } else if (IS_XSLT_NAME(cur, "decimal-format")) {
+        } else if (IS_XSLT_NAME(cur, "decimal-format")) {
            xsltParseStylesheetDecimalFormat(style, cur);
-    } else if (IS_XSLT_NAME(cur, "attribute-set")) {
+        } else if (IS_XSLT_NAME(cur, "attribute-set")) {
            xsltParseStylesheetAttributeSet(style, cur);
-    } else if (IS_XSLT_NAME(cur, "variable")) {
+        } else if (IS_XSLT_NAME(cur, "variable")) {
            xsltParseGlobalVariable(style, cur);
-    } else if (IS_XSLT_NAME(cur, "param")) {
+        } else if (IS_XSLT_NAME(cur, "param")) {
            xsltParseGlobalParam(style, cur);
-    } else if (IS_XSLT_NAME(cur, "template")) {
+        } else if (IS_XSLT_NAME(cur, "template")) {
 #ifdef WITH_XSLT_DEBUG_PARSING
            templates++;
 #endif
            xsltParseStylesheetTemplate(style, cur);
-    } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
+        } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
            xsltNamespaceAlias(style, cur);
        } else {
             if ((style != NULL) && (style->forwards_compatible == 0)) {
@@ -6130,13 +6183,6 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
                        cur->name);
                if (style != NULL) style->errors++;
            }
-           else {
-                /* do Forwards-Compatible Processing */
-               xsltTransformError(NULL, style, cur,
-                       "xsltParseStylesheetTop: ignoring unknown %s element\n",
-                       cur->name);
-               if (style != NULL) style->warnings++;
-            }
        }
        cur = cur->next;
     }
@@ -6380,7 +6426,7 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
        ret->literal_result = 1;
     }
     if (!ret->nopreproc) {
-       xsltPrecomputeStylesheet(ret, cur);
+       xsltPreprocessStylesheet(ret, cur);
     }
     if (ret->literal_result == 0) {
        xsltParseStylesheetTop(ret, cur);
@@ -6403,10 +6449,11 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
                "xsltParseStylesheetProcess : document is stylesheet\n");
 #endif
 
-       if (!xmlStrEqual(prop, (const xmlChar *)"1.0")) {
+       if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
+            (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
            xsltTransformError(NULL, ret, cur,
-               "xsl:version: only 1.0 features are supported\n");
-            /* TODO set up compatibility when not XSLT 1.0 */
+               "xsl:version: only 1.1 features are supported\n");
+            ret->forwards_compatible = 1;
            ret->warnings++;
        }
        xmlFree(prop);
index 6e4e328..5fa5e58 100644 (file)
@@ -123,19 +123,6 @@ extern "C" {
 #define LIBXSLT_DEFAULT_PLUGINS_PATH() "@LIBXSLT_DEFAULT_PLUGINS_PATH@"
 #endif
 
-/**
- * Locale support
- */
-#if @XSLT_LOCALE_XLOCALE@
-#ifndef XSLT_LOCALE_XLOCALE
-#define XSLT_LOCALE_XLOCALE
-#endif
-#elif @XSLT_LOCALE_WINAPI@
-#ifndef XSLT_LOCALE_WINAPI
-#define XSLT_LOCALE_WINAPI
-#endif
-#endif
-
 /**
  * ATTRIBUTE_UNUSED:
  *
index 2b39b09..14b20ed 100644 (file)
 
 #include "xsltlocale.h"
 
-#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2
-#define newlocale __newlocale
-#define freelocale __freelocale
-#define strxfrm_l __strxfrm_l
-#define LC_COLLATE_MASK (1 << LC_COLLATE)
-#endif
-
 #define TOUPPER(c) (c & ~0x20)
 #define TOLOWER(c) (c | 0x20)
 #define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26)
@@ -87,7 +80,7 @@ xsltFreeLocales(void) {
  */
 xsltLocale
 xsltNewLocale(const xmlChar *languageTag) {
-#ifdef XSLT_LOCALE_XLOCALE
+#ifdef XSLT_LOCALE_POSIX
     xsltLocale locale;
     char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */
     const xmlChar *p = languageTag;
@@ -189,7 +182,7 @@ xsltNewLocale(const xmlChar *languageTag) {
     region = xsltDefaultRegion(localeName);
     if (region == NULL) goto end;
 
-    strcpy(localeName + llen + 1, region);
+    strcpy((char *) localeName + llen + 1, (char *) region);
     locale = xslt_locale_WINAPI(localeName);
 end:
     return(locale);
@@ -347,7 +340,7 @@ xsltDefaultRegion(const xmlChar *localeName) {
  */
 void
 xsltFreeLocale(xsltLocale locale) {
-#ifdef XSLT_LOCALE_XLOCALE
+#ifdef XSLT_LOCALE_POSIX
     freelocale(locale);
 #endif
 }
@@ -371,7 +364,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
     size_t xstrlen, r;
     xsltLocaleChar *xstr;
 
-#ifdef XSLT_LOCALE_XLOCALE
+#ifdef XSLT_LOCALE_POSIX
     xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1;
     xstr = (xsltLocaleChar *) xmlMalloc(xstrlen);
     if (xstr == NULL) {
@@ -384,7 +377,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
 #endif
 
 #ifdef XSLT_LOCALE_WINAPI
-    xstrlen = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
+    xstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0);
     if (xstrlen == 0) {
         xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
         return(NULL);
@@ -394,7 +387,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
         xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
         return(NULL);
     }
-    r = MultiByteToWideChar(CP_UTF8, 0, string, -1, xstr, xstrlen);
+    r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, xstr, xstrlen);
     if (r == 0) {
         xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
         xmlFree(xstr);
@@ -481,9 +474,11 @@ xsltIterateSupportedLocales(LPSTR lcid) {
     k = sscanf(lcid, "%lx", (long*)&p->lcid);
     if (k < 1) goto end;
     /*don't count terminating null character*/
-    k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME , iso639lang , sizeof(iso639lang ));
+    k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME,
+                       (char *) iso639lang, sizeof(iso639lang));
     if (--k < 1) goto end;
-    l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, iso3136ctry, sizeof(iso3136ctry));
+    l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME,
+                       (char *) iso3136ctry, sizeof(iso3136ctry));
     if (--l < 1) goto end;
 
     {  /*fill results*/
index 53facee..1b57648 100644 (file)
 #include <unistd.h>
 #endif
 
-/* gettimeofday on Windows ??? */
-#if defined(WIN32) && !defined(__CYGWIN__)
-#ifdef _MSC_VER
-#include <winsock2.h>
-#pragma comment(lib, "ws2_32.lib")
-#define gettimeofday(p1,p2)
-#define HAVE_GETTIMEOFDAY
+#if defined(_WIN32) && !defined(__CYGWIN__)
 #define XSLT_WIN32_PERFORMANCE_COUNTER
-#endif /* _MS_VER */
-#endif /* WIN32 */
+#endif
 
 /************************************************************************
  *                                                                     *
@@ -433,9 +426,8 @@ xsltMessage(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst) {
        } else if (xmlStrEqual(prop, (const xmlChar *)"no")) {
            terminate = 0;
        } else {
-           error(errctx,
+           xsltTransformError(ctxt, NULL, inst,
                "xsl:message : terminate expecting 'yes' or 'no'\n");
-           ctxt->state = XSLT_STATE_ERROR;
        }
        xmlFree(prop);
     }
@@ -598,7 +590,8 @@ xsltPrintErrorContext(xsltTransformContextPtr ctxt,
     void *errctx = xsltGenericErrorContext;
 
     if (ctxt != NULL) {
-       ctxt->state = XSLT_STATE_ERROR;
+        if (ctxt->state == XSLT_STATE_OK)
+           ctxt->state = XSLT_STATE_ERROR;
        if (ctxt->error != NULL) {
            error = ctxt->error;
            errctx = ctxt->errctx;
@@ -691,7 +684,8 @@ xsltTransformError(xsltTransformContextPtr ctxt,
     char * str;
 
     if (ctxt != NULL) {
-       ctxt->state = XSLT_STATE_ERROR;
+        if (ctxt->state == XSLT_STATE_OK)
+           ctxt->state = XSLT_STATE_ERROR;
        if (ctxt->error != NULL) {
            error = ctxt->error;
            errctx = ctxt->errctx;
@@ -1224,6 +1218,8 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
                        if (res[j] == NULL) {
                            if (res[j+incr] != NULL)
                                tst = 1;
+                       } else if (res[j+incr] == NULL) {
+                           tst = -1;
                        } else {
                            if (numb) {
                                /* We make NaN smaller than number in
@@ -1784,6 +1780,8 @@ static long calibration = -1;
  *
  * Returns the number of milliseconds used by xsltTimestamp()
  */
+#if !defined(XSLT_WIN32_PERFORMANCE_COUNTER) && \
+    (defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETTIMEOFDAY))
 static long
 xsltCalibrateTimestamps(void) {
     register int i;
@@ -1792,6 +1790,7 @@ xsltCalibrateTimestamps(void) {
        xsltTimestamp();
     return(xsltTimestamp() / 1000);
 }
+#endif
 
 /**
  * xsltCalibrateAdjust:
index 70bb756..63d90d0 100644 (file)
@@ -23,21 +23,21 @@ extern "C" {
  *
  * the version string like "1.2.3"
  */
-#define LIBXSLT_DOTTED_VERSION "1.1.28"
+#define LIBXSLT_DOTTED_VERSION "1.1.32"
 
 /**
  * LIBXSLT_VERSION:
  *
  * the version number: 1.2.3 value is 1002003
  */
-#define LIBXSLT_VERSION 10128
+#define LIBXSLT_VERSION 10132
 
 /**
  * LIBXSLT_VERSION_STRING:
  *
  * the version number string, 1.2.3 value is "1002003"
  */
-#define LIBXSLT_VERSION_STRING "10128"
+#define LIBXSLT_VERSION_STRING "10132"
 
 /**
  * LIBXSLT_VERSION_EXTRA:
@@ -53,7 +53,7 @@ extern "C" {
  * is insignifiant and being able to run xsltpoc -v is useful. On
  * by default
  */
-#if 0
+#if 1
 #define WITH_XSLT_DEBUG
 #endif
 
@@ -62,7 +62,7 @@ extern "C" {
  *
  * Whether module support is configured into libxslt
  */
-#if 0
+#if 1
 #ifndef WITH_MODULES
 #define WITH_MODULES
 #endif
index 1201807..1265c04 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef __XSLT_LIBXSLT_H__
 #define __XSLT_LIBXSLT_H__
 
-#if defined(WIN32) && !defined (__CYGWIN__) && !defined (__MINGW32__)
+#if defined(_WIN32) && !defined (__CYGWIN__) && !defined (__MINGW32__)
 #include <win32config.h>
 #else
 #include "config.h"
index 17b4c6f..24acf8d 100644 (file)
@@ -34,6 +34,41 @@ extern "C" {
     xsltRegisterAllElement(ctxt);                              \
     (ctxt)->xpathCtxt->extra = ctxt
 
+/*
+ * Flags for memory management of RVTs
+ */
+
+/**
+ * XSLT_RVT_LOCAL:
+ *
+ * RVT is destroyed after the current instructions ends.
+ */
+#define XSLT_RVT_LOCAL       ((void *)1)
+
+/**
+ * XSLT_RVT_VARIABLE:
+ *
+ * RVT is part of a local variable and destroyed after the variable goes out
+ * of scope.
+ */
+#define XSLT_RVT_VARIABLE    ((void *)2)
+
+/**
+ * XSLT_RVT_FUNC_RESULT:
+ *
+ * RVT is part of results returned with func:result. The RVT won't be
+ * destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or
+ * XSLT_RVT_VARIABLE in the template that receives the return value.
+ */
+#define XSLT_RVT_FUNC_RESULT ((void *)3)
+
+/**
+ * XSLT_RVT_GLOBAL:
+ *
+ * RVT is part of a global variable.
+ */
+#define XSLT_RVT_GLOBAL      ((void *)4)
+
 /*
  * Interfaces for the variable module.
  */
index 7123ace..47125b3 100644 (file)
@@ -324,6 +324,7 @@ struct _xsltDecimalFormat {
     xmlChar *percent;
     xmlChar *permille;
     xmlChar *zeroDigit;
+    const xmlChar *nsUri;
 };
 
 /**
@@ -1754,8 +1755,8 @@ struct _xsltTransformContext {
      * Speed optimization when coalescing text nodes
      */
     const xmlChar  *lasttext;          /* last text node content */
-    unsigned int    lasttsize;         /* last text node size */
-    unsigned int    lasttuse;          /* last text node use */
+    int             lasttsize;         /* last text node size */
+    int             lasttuse;          /* last text node use */
     /*
      * Per Context Debugging
      */
@@ -1783,9 +1784,9 @@ struct _xsltTransformContext {
     xmlDocPtr localRVT; /* list of local tree fragments; will be freed when
                           the instruction which created the fragment
                            exits */
-    xmlDocPtr localRVTBase;
+    xmlDocPtr localRVTBase; /* Obsolete */
     int keyInitLevel;   /* Needed to catch recursive keys issues */
-    int funcLevel;      /* Needed to catch recursive functions issues */
+    int depth;          /* Needed to catch recursions */
     int maxTemplateDepth;
     int maxTemplateVars;
 };
@@ -1854,6 +1855,10 @@ XSLTPUBFUN void XSLTCALL
 XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL
                        xsltDecimalFormatGetByName(xsltStylesheetPtr style,
                                                 xmlChar *name);
+XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL
+                       xsltDecimalFormatGetByQName(xsltStylesheetPtr style,
+                                                const xmlChar *nsUri,
+                                                 const xmlChar *name);
 
 XSLTPUBFUN xsltStylesheetPtr XSLTCALL
                        xsltParseStylesheetProcess(xsltStylesheetPtr ret,
@@ -1906,6 +1911,11 @@ XSLTPUBFUN int XSLTCALL
 XSLTPUBFUN int XSLTCALL
                        xsltExtensionInstructionResultFinalize(
                                                 xsltTransformContextPtr ctxt);
+XSLTPUBFUN int XSLTCALL
+                       xsltFlagRVTs(
+                                                xsltTransformContextPtr ctxt,
+                                                xmlXPathObjectPtr obj,
+                                                void *val);
 XSLTPUBFUN void XSLTCALL
                        xsltFreeRVTs            (xsltTransformContextPtr ctxt);
 XSLTPUBFUN void XSLTCALL
index 0b82bf7..f83bc88 100644 (file)
@@ -20,21 +20,21 @@ extern "C" {
  *
  * the version string like "1.2.3"
  */
-#define LIBXSLT_DOTTED_VERSION "1.1.29"
+#define LIBXSLT_DOTTED_VERSION "1.1.32"
 
 /**
  * LIBXSLT_VERSION:
  *
  * the version number: 1.2.3 value is 10203
  */
-#define LIBXSLT_VERSION 10129
+#define LIBXSLT_VERSION 10132
 
 /**
  * LIBXSLT_VERSION_STRING:
  *
  * the version number string, 1.2.3 value is "10203"
  */
-#define LIBXSLT_VERSION_STRING "10129"
+#define LIBXSLT_VERSION_STRING "10132"
 
 /**
  * LIBXSLT_VERSION_EXTRA:
@@ -123,19 +123,6 @@ extern "C" {
 #define LIBXSLT_DEFAULT_PLUGINS_PATH() "/usr/lib/libxslt-plugins"
 #endif
 
-/**
- * Locale support
- */
-#if 0
-#ifndef XSLT_LOCALE_XLOCALE
-#define XSLT_LOCALE_XLOCALE
-#endif
-#elif 1
-#ifndef XSLT_LOCALE_WINAPI
-#define XSLT_LOCALE_WINAPI
-#endif
-#endif
-
 /**
  * ATTRIBUTE_UNUSED:
  *
index b7b1b1f..657ceeb 100644 (file)
 #include <libxml/xmlstring.h>
 #include "xsltexports.h"
 
-#ifdef XSLT_LOCALE_XLOCALE
+#ifdef HAVE_STRXFRM_L
 
+/*
+ * XSLT_LOCALE_POSIX:
+ * Macro indicating to use POSIX locale extensions
+ */
+#define XSLT_LOCALE_POSIX
+
+#ifdef HAVE_LOCALE_H
 #include <locale.h>
+#endif
+#ifdef HAVE_XLOCALE_H
 #include <xlocale.h>
+#endif
 
-#ifdef __GLIBC__
-/*locale_t is defined only if _GNU_SOURCE is defined*/
-typedef __locale_t xsltLocale;
-#else
 typedef locale_t xsltLocale;
-#endif
 typedef xmlChar xsltLocaleChar;
 
-#elif defined(XSLT_LOCALE_WINAPI)
+#elif defined(_WIN32) && !defined(__CYGWIN__)
+
+/*
+ * XSLT_LOCALE_WINAPI:
+ * Macro indicating to use WinAPI for extended locale support
+ */
+#define XSLT_LOCALE_WINAPI
 
 #ifdef __REACTOS__
 #define WIN32_NO_STATUS
@@ -45,11 +56,9 @@ typedef wchar_t xsltLocaleChar;
 
 /*
  * XSLT_LOCALE_NONE:
- * Macro indicating that locale are not supported
+ * Macro indicating that there's no extended locale support
  */
-#ifndef XSLT_LOCALE_NONE
 #define XSLT_LOCALE_NONE
-#endif
 
 typedef void *xsltLocale;
 typedef xmlChar xsltLocaleChar;