| Index: third_party/libxslt/libxslt/xsltutils.c
|
| diff --git a/third_party/libxslt/libxslt/xsltutils.c b/third_party/libxslt/libxslt/xsltutils.c
|
| deleted file mode 100644
|
| index c250ccfabb8f34eaff5ed5ce18f509f3062404e8..0000000000000000000000000000000000000000
|
| --- a/third_party/libxslt/libxslt/xsltutils.c
|
| +++ /dev/null
|
| @@ -1,2483 +0,0 @@
|
| -/*
|
| - * xsltutils.c: Utilities for the XSL Transformation 1.0 engine
|
| - *
|
| - * Reference:
|
| - * http://www.w3.org/TR/1999/REC-xslt-19991116
|
| - *
|
| - * See Copyright for the status of this software.
|
| - *
|
| - * daniel@veillard.com
|
| - */
|
| -
|
| -#define IN_LIBXSLT
|
| -#include "libxslt.h"
|
| -
|
| -#ifndef XSLT_NEED_TRIO
|
| -#include <stdio.h>
|
| -#else
|
| -#include <trio.h>
|
| -#endif
|
| -
|
| -#include <string.h>
|
| -#include <time.h>
|
| -#ifdef HAVE_SYS_TIME_H
|
| -#include <sys/time.h>
|
| -#endif
|
| -#ifdef HAVE_UNISTD_H
|
| -#include <unistd.h>
|
| -#endif
|
| -#ifdef HAVE_STDLIB_H
|
| -#include <stdlib.h>
|
| -#endif
|
| -#include <stdarg.h>
|
| -
|
| -#include <libxml/xmlmemory.h>
|
| -#include <libxml/tree.h>
|
| -#include <libxml/HTMLtree.h>
|
| -#include <libxml/xmlerror.h>
|
| -#include <libxml/xmlIO.h>
|
| -#include "xsltutils.h"
|
| -#include "templates.h"
|
| -#include "xsltInternals.h"
|
| -#include "imports.h"
|
| -#include "transform.h"
|
| -
|
| -/* 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
|
| -#define XSLT_WIN32_PERFORMANCE_COUNTER
|
| -#endif /* _MS_VER */
|
| -#endif /* WIN32 */
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Convenience function *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/**
|
| - * xsltGetCNsProp:
|
| - * @style: the stylesheet
|
| - * @node: the node
|
| - * @name: the attribute name
|
| - * @nameSpace: the URI of the namespace
|
| - *
|
| - * Similar to xmlGetNsProp() but with a slightly different semantic
|
| - *
|
| - * Search and get the value of an attribute associated to a node
|
| - * This attribute has to be anchored in the namespace specified,
|
| - * or has no namespace and the element is in that namespace.
|
| - *
|
| - * This does the entity substitution.
|
| - * This function looks in DTD attribute declaration for #FIXED or
|
| - * default declaration values unless DTD use has been turned off.
|
| - *
|
| - * Returns the attribute value or NULL if not found. The string is allocated
|
| - * in the stylesheet dictionary.
|
| - */
|
| -const xmlChar *
|
| -xsltGetCNsProp(xsltStylesheetPtr style, xmlNodePtr node,
|
| - const xmlChar *name, const xmlChar *nameSpace) {
|
| - xmlAttrPtr prop;
|
| - xmlDocPtr doc;
|
| - xmlNsPtr ns;
|
| - xmlChar *tmp;
|
| - const xmlChar *ret;
|
| -
|
| - if ((node == NULL) || (style == NULL) || (style->dict == NULL))
|
| - return(NULL);
|
| -
|
| - if (nameSpace == NULL)
|
| - return xmlGetProp(node, name);
|
| -
|
| - if (node->type == XML_NAMESPACE_DECL)
|
| - return(NULL);
|
| - if (node->type == XML_ELEMENT_NODE)
|
| - prop = node->properties;
|
| - else
|
| - prop = NULL;
|
| - while (prop != NULL) {
|
| - /*
|
| - * One need to have
|
| - * - same attribute names
|
| - * - and the attribute carrying that namespace
|
| - */
|
| - if ((xmlStrEqual(prop->name, name)) &&
|
| - (((prop->ns == NULL) && (node->ns != NULL) &&
|
| - (xmlStrEqual(node->ns->href, nameSpace))) ||
|
| - ((prop->ns != NULL) &&
|
| - (xmlStrEqual(prop->ns->href, nameSpace))))) {
|
| -
|
| - tmp = xmlNodeListGetString(node->doc, prop->children, 1);
|
| - if (tmp == NULL)
|
| - ret = xmlDictLookup(style->dict, BAD_CAST "", 0);
|
| - else {
|
| - ret = xmlDictLookup(style->dict, tmp, -1);
|
| - xmlFree(tmp);
|
| - }
|
| - return ret;
|
| - }
|
| - prop = prop->next;
|
| - }
|
| - tmp = NULL;
|
| - /*
|
| - * Check if there is a default declaration in the internal
|
| - * or external subsets
|
| - */
|
| - doc = node->doc;
|
| - if (doc != NULL) {
|
| - if (doc->intSubset != NULL) {
|
| - xmlAttributePtr attrDecl;
|
| -
|
| - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
|
| - if ((attrDecl == NULL) && (doc->extSubset != NULL))
|
| - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
|
| -
|
| - if ((attrDecl != NULL) && (attrDecl->prefix != NULL)) {
|
| - /*
|
| - * The DTD declaration only allows a prefix search
|
| - */
|
| - ns = xmlSearchNs(doc, node, attrDecl->prefix);
|
| - if ((ns != NULL) && (xmlStrEqual(ns->href, nameSpace)))
|
| - return(xmlDictLookup(style->dict,
|
| - attrDecl->defaultValue, -1));
|
| - }
|
| - }
|
| - }
|
| - return(NULL);
|
| -}
|
| -/**
|
| - * xsltGetNsProp:
|
| - * @node: the node
|
| - * @name: the attribute name
|
| - * @nameSpace: the URI of the namespace
|
| - *
|
| - * Similar to xmlGetNsProp() but with a slightly different semantic
|
| - *
|
| - * Search and get the value of an attribute associated to a node
|
| - * This attribute has to be anchored in the namespace specified,
|
| - * or has no namespace and the element is in that namespace.
|
| - *
|
| - * This does the entity substitution.
|
| - * This function looks in DTD attribute declaration for #FIXED or
|
| - * default declaration values unless DTD use has been turned off.
|
| - *
|
| - * Returns the attribute value or NULL if not found.
|
| - * It's up to the caller to free the memory.
|
| - */
|
| -xmlChar *
|
| -xsltGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) {
|
| - xmlAttrPtr prop;
|
| - xmlDocPtr doc;
|
| - xmlNsPtr ns;
|
| -
|
| - if (node == NULL)
|
| - return(NULL);
|
| -
|
| - if (nameSpace == NULL)
|
| - return xmlGetProp(node, name);
|
| -
|
| - if (node->type == XML_NAMESPACE_DECL)
|
| - return(NULL);
|
| - if (node->type == XML_ELEMENT_NODE)
|
| - prop = node->properties;
|
| - else
|
| - prop = NULL;
|
| - /*
|
| - * TODO: Substitute xmlGetProp() for xmlGetNsProp(), since the former
|
| - * is not namespace-aware and will return an attribute with equal
|
| - * name regardless of its namespace.
|
| - * Example:
|
| - * <xsl:element foo:name="myName"/>
|
| - * So this would return "myName" even if an attribute @name
|
| - * in the XSLT was requested.
|
| - */
|
| - while (prop != NULL) {
|
| - /*
|
| - * One need to have
|
| - * - same attribute names
|
| - * - and the attribute carrying that namespace
|
| - */
|
| - if ((xmlStrEqual(prop->name, name)) &&
|
| - (((prop->ns == NULL) && (node->ns != NULL) &&
|
| - (xmlStrEqual(node->ns->href, nameSpace))) ||
|
| - ((prop->ns != NULL) &&
|
| - (xmlStrEqual(prop->ns->href, nameSpace))))) {
|
| - xmlChar *ret;
|
| -
|
| - ret = xmlNodeListGetString(node->doc, prop->children, 1);
|
| - if (ret == NULL) return(xmlStrdup((xmlChar *)""));
|
| - return(ret);
|
| - }
|
| - prop = prop->next;
|
| - }
|
| -
|
| - /*
|
| - * Check if there is a default declaration in the internal
|
| - * or external subsets
|
| - */
|
| - doc = node->doc;
|
| - if (doc != NULL) {
|
| - if (doc->intSubset != NULL) {
|
| - xmlAttributePtr attrDecl;
|
| -
|
| - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
|
| - if ((attrDecl == NULL) && (doc->extSubset != NULL))
|
| - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
|
| -
|
| - if ((attrDecl != NULL) && (attrDecl->prefix != NULL)) {
|
| - /*
|
| - * The DTD declaration only allows a prefix search
|
| - */
|
| - ns = xmlSearchNs(doc, node, attrDecl->prefix);
|
| - if ((ns != NULL) && (xmlStrEqual(ns->href, nameSpace)))
|
| - return(xmlStrdup(attrDecl->defaultValue));
|
| - }
|
| - }
|
| - }
|
| - return(NULL);
|
| -}
|
| -
|
| -/**
|
| - * xsltGetUTF8Char:
|
| - * @utf: a sequence of UTF-8 encoded bytes
|
| - * @len: a pointer to @bytes len
|
| - *
|
| - * Read one UTF8 Char from @utf
|
| - * Function copied from libxml2 xmlGetUTF8Char() ... to discard ultimately
|
| - * and use the original API
|
| - *
|
| - * Returns the char value or -1 in case of error and update @len with the
|
| - * number of bytes used
|
| - */
|
| -int
|
| -xsltGetUTF8Char(const unsigned char *utf, int *len) {
|
| - unsigned int c;
|
| -
|
| - if (utf == NULL)
|
| - goto error;
|
| - if (len == NULL)
|
| - goto error;
|
| - if (*len < 1)
|
| - goto error;
|
| -
|
| - c = utf[0];
|
| - if (c & 0x80) {
|
| - if (*len < 2)
|
| - goto error;
|
| - if ((utf[1] & 0xc0) != 0x80)
|
| - goto error;
|
| - if ((c & 0xe0) == 0xe0) {
|
| - if (*len < 3)
|
| - goto error;
|
| - if ((utf[2] & 0xc0) != 0x80)
|
| - goto error;
|
| - if ((c & 0xf0) == 0xf0) {
|
| - if (*len < 4)
|
| - goto error;
|
| - if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
|
| - goto error;
|
| - *len = 4;
|
| - /* 4-byte code */
|
| - c = (utf[0] & 0x7) << 18;
|
| - c |= (utf[1] & 0x3f) << 12;
|
| - c |= (utf[2] & 0x3f) << 6;
|
| - c |= utf[3] & 0x3f;
|
| - } else {
|
| - /* 3-byte code */
|
| - *len = 3;
|
| - c = (utf[0] & 0xf) << 12;
|
| - c |= (utf[1] & 0x3f) << 6;
|
| - c |= utf[2] & 0x3f;
|
| - }
|
| - } else {
|
| - /* 2-byte code */
|
| - *len = 2;
|
| - c = (utf[0] & 0x1f) << 6;
|
| - c |= utf[1] & 0x3f;
|
| - }
|
| - } else {
|
| - /* 1-byte code */
|
| - *len = 1;
|
| - }
|
| - return(c);
|
| -
|
| -error:
|
| - if (len != NULL)
|
| - *len = 0;
|
| - return(-1);
|
| -}
|
| -
|
| -#ifdef XSLT_REFACTORED
|
| -
|
| -/**
|
| - * xsltPointerListAddSize:
|
| - * @list: the pointer list structure
|
| - * @item: the item to be stored
|
| - * @initialSize: the initial size of the list
|
| - *
|
| - * Adds an item to the list.
|
| - *
|
| - * Returns the position of the added item in the list or
|
| - * -1 in case of an error.
|
| - */
|
| -int
|
| -xsltPointerListAddSize(xsltPointerListPtr list,
|
| - void *item,
|
| - int initialSize)
|
| -{
|
| - if (list->items == NULL) {
|
| - if (initialSize <= 0)
|
| - initialSize = 1;
|
| - list->items = (void **) xmlMalloc(
|
| - initialSize * sizeof(void *));
|
| - if (list->items == NULL) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "xsltPointerListAddSize: memory allocation failure.\n");
|
| - return(-1);
|
| - }
|
| - list->number = 0;
|
| - list->size = initialSize;
|
| - } else if (list->size <= list->number) {
|
| - list->size *= 2;
|
| - list->items = (void **) xmlRealloc(list->items,
|
| - list->size * sizeof(void *));
|
| - if (list->items == NULL) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "xsltPointerListAddSize: memory re-allocation failure.\n");
|
| - list->size = 0;
|
| - return(-1);
|
| - }
|
| - }
|
| - list->items[list->number++] = item;
|
| - return(0);
|
| -}
|
| -
|
| -/**
|
| - * xsltPointerListCreate:
|
| - * @initialSize: the initial size for the list
|
| - *
|
| - * Creates an xsltPointerList structure.
|
| - *
|
| - * Returns a xsltPointerList structure or NULL in case of an error.
|
| - */
|
| -xsltPointerListPtr
|
| -xsltPointerListCreate(int initialSize)
|
| -{
|
| - xsltPointerListPtr ret;
|
| -
|
| - ret = xmlMalloc(sizeof(xsltPointerList));
|
| - if (ret == NULL) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "xsltPointerListCreate: memory allocation failure.\n");
|
| - return (NULL);
|
| - }
|
| - memset(ret, 0, sizeof(xsltPointerList));
|
| - if (initialSize > 0) {
|
| - xsltPointerListAddSize(ret, NULL, initialSize);
|
| - ret->number = 0;
|
| - }
|
| - return (ret);
|
| -}
|
| -
|
| -/**
|
| - * xsltPointerListFree:
|
| - * @list: pointer to the list to be freed
|
| - *
|
| - * Frees the xsltPointerList structure. This does not free
|
| - * the content of the list.
|
| - */
|
| -void
|
| -xsltPointerListFree(xsltPointerListPtr list)
|
| -{
|
| - if (list == NULL)
|
| - return;
|
| - if (list->items != NULL)
|
| - xmlFree(list->items);
|
| - xmlFree(list);
|
| -}
|
| -
|
| -/**
|
| - * xsltPointerListClear:
|
| - * @list: pointer to the list to be cleared
|
| - *
|
| - * Resets the list, but does not free the allocated array
|
| - * and does not free the content of the list.
|
| - */
|
| -void
|
| -xsltPointerListClear(xsltPointerListPtr list)
|
| -{
|
| - if (list->items != NULL) {
|
| - xmlFree(list->items);
|
| - list->items = NULL;
|
| - }
|
| - list->number = 0;
|
| - list->size = 0;
|
| -}
|
| -
|
| -#endif /* XSLT_REFACTORED */
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Handling of XSLT stylesheets messages *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/**
|
| - * xsltMessage:
|
| - * @ctxt: an XSLT processing context
|
| - * @node: The current node
|
| - * @inst: The node containing the message instruction
|
| - *
|
| - * Process and xsl:message construct
|
| - */
|
| -void
|
| -xsltMessage(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst) {
|
| - xmlGenericErrorFunc error = xsltGenericError;
|
| - void *errctx = xsltGenericErrorContext;
|
| - xmlChar *prop, *message;
|
| - int terminate = 0;
|
| -
|
| - if ((ctxt == NULL) || (inst == NULL))
|
| - return;
|
| -
|
| - if (ctxt->error != NULL) {
|
| - error = ctxt->error;
|
| - errctx = ctxt->errctx;
|
| - }
|
| -
|
| - prop = xmlGetNsProp(inst, (const xmlChar *)"terminate", NULL);
|
| - if (prop != NULL) {
|
| - if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
|
| - terminate = 1;
|
| - } else if (xmlStrEqual(prop, (const xmlChar *)"no")) {
|
| - terminate = 0;
|
| - } else {
|
| - xsltTransformError(ctxt, NULL, inst,
|
| - "xsl:message : terminate expecting 'yes' or 'no'\n");
|
| - }
|
| - xmlFree(prop);
|
| - }
|
| - message = xsltEvalTemplateString(ctxt, node, inst);
|
| - if (message != NULL) {
|
| - int len = xmlStrlen(message);
|
| -
|
| - error(errctx, "%s", (const char *)message);
|
| - if ((len > 0) && (message[len - 1] != '\n'))
|
| - error(errctx, "\n");
|
| - xmlFree(message);
|
| - }
|
| - if (terminate)
|
| - ctxt->state = XSLT_STATE_STOPPED;
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Handling of out of context errors *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -#define XSLT_GET_VAR_STR(msg, str) { \
|
| - int size; \
|
| - int chars; \
|
| - char *larger; \
|
| - va_list ap; \
|
| - \
|
| - str = (char *) xmlMalloc(150); \
|
| - if (str == NULL) \
|
| - return; \
|
| - \
|
| - size = 150; \
|
| - \
|
| - while (size < 64000) { \
|
| - va_start(ap, msg); \
|
| - chars = vsnprintf(str, size, msg, ap); \
|
| - va_end(ap); \
|
| - if ((chars > -1) && (chars < size)) \
|
| - break; \
|
| - if (chars > -1) \
|
| - size += chars + 1; \
|
| - else \
|
| - size += 100; \
|
| - if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
|
| - xmlFree(str); \
|
| - return; \
|
| - } \
|
| - str = larger; \
|
| - } \
|
| -}
|
| -/**
|
| - * xsltGenericErrorDefaultFunc:
|
| - * @ctx: an error context
|
| - * @msg: the message to display/transmit
|
| - * @...: extra parameters for the message display
|
| - *
|
| - * Default handler for out of context error messages.
|
| - */
|
| -static void LIBXSLT_ATTR_FORMAT(2,3)
|
| -xsltGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
|
| - va_list args;
|
| -
|
| - if (xsltGenericErrorContext == NULL)
|
| - xsltGenericErrorContext = (void *) stderr;
|
| -
|
| - va_start(args, msg);
|
| - vfprintf((FILE *)xsltGenericErrorContext, msg, args);
|
| - va_end(args);
|
| -}
|
| -
|
| -xmlGenericErrorFunc xsltGenericError = xsltGenericErrorDefaultFunc;
|
| -void *xsltGenericErrorContext = NULL;
|
| -
|
| -
|
| -/**
|
| - * xsltSetGenericErrorFunc:
|
| - * @ctx: the new error handling context
|
| - * @handler: the new handler function
|
| - *
|
| - * Function to reset the handler and the error context for out of
|
| - * context error messages.
|
| - * This simply means that @handler will be called for subsequent
|
| - * error messages while not parsing nor validating. And @ctx will
|
| - * be passed as first argument to @handler
|
| - * One can simply force messages to be emitted to another FILE * than
|
| - * stderr by setting @ctx to this file handle and @handler to NULL.
|
| - */
|
| -void
|
| -xsltSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
|
| - xsltGenericErrorContext = ctx;
|
| - if (handler != NULL)
|
| - xsltGenericError = handler;
|
| - else
|
| - xsltGenericError = xsltGenericErrorDefaultFunc;
|
| -}
|
| -
|
| -/**
|
| - * xsltGenericDebugDefaultFunc:
|
| - * @ctx: an error context
|
| - * @msg: the message to display/transmit
|
| - * @...: extra parameters for the message display
|
| - *
|
| - * Default handler for out of context error messages.
|
| - */
|
| -static void LIBXSLT_ATTR_FORMAT(2,3)
|
| -xsltGenericDebugDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
|
| - va_list args;
|
| -
|
| - if (xsltGenericDebugContext == NULL)
|
| - return;
|
| -
|
| - va_start(args, msg);
|
| - vfprintf((FILE *)xsltGenericDebugContext, msg, args);
|
| - va_end(args);
|
| -}
|
| -
|
| -xmlGenericErrorFunc xsltGenericDebug = xsltGenericDebugDefaultFunc;
|
| -void *xsltGenericDebugContext = NULL;
|
| -
|
| -
|
| -/**
|
| - * xsltSetGenericDebugFunc:
|
| - * @ctx: the new error handling context
|
| - * @handler: the new handler function
|
| - *
|
| - * Function to reset the handler and the error context for out of
|
| - * context error messages.
|
| - * This simply means that @handler will be called for subsequent
|
| - * error messages while not parsing or validating. And @ctx will
|
| - * be passed as first argument to @handler
|
| - * One can simply force messages to be emitted to another FILE * than
|
| - * stderr by setting @ctx to this file handle and @handler to NULL.
|
| - */
|
| -void
|
| -xsltSetGenericDebugFunc(void *ctx, xmlGenericErrorFunc handler) {
|
| - xsltGenericDebugContext = ctx;
|
| - if (handler != NULL)
|
| - xsltGenericDebug = handler;
|
| - else
|
| - xsltGenericDebug = xsltGenericDebugDefaultFunc;
|
| -}
|
| -
|
| -/**
|
| - * xsltPrintErrorContext:
|
| - * @ctxt: the transformation context
|
| - * @style: the stylesheet
|
| - * @node: the current node being processed
|
| - *
|
| - * Display the context of an error.
|
| - */
|
| -void
|
| -xsltPrintErrorContext(xsltTransformContextPtr ctxt,
|
| - xsltStylesheetPtr style, xmlNodePtr node) {
|
| - int line = 0;
|
| - const xmlChar *file = NULL;
|
| - const xmlChar *name = NULL;
|
| - const char *type = "error";
|
| - xmlGenericErrorFunc error = xsltGenericError;
|
| - void *errctx = xsltGenericErrorContext;
|
| -
|
| - if (ctxt != NULL) {
|
| - if (ctxt->state == XSLT_STATE_OK)
|
| - ctxt->state = XSLT_STATE_ERROR;
|
| - if (ctxt->error != NULL) {
|
| - error = ctxt->error;
|
| - errctx = ctxt->errctx;
|
| - }
|
| - }
|
| - if ((node == NULL) && (ctxt != NULL))
|
| - node = ctxt->inst;
|
| -
|
| - if (node != NULL) {
|
| - if ((node->type == XML_DOCUMENT_NODE) ||
|
| - (node->type == XML_HTML_DOCUMENT_NODE)) {
|
| - xmlDocPtr doc = (xmlDocPtr) node;
|
| -
|
| - file = doc->URL;
|
| - } else {
|
| - line = xmlGetLineNo(node);
|
| - if ((node->doc != NULL) && (node->doc->URL != NULL))
|
| - file = node->doc->URL;
|
| - if (node->name != NULL)
|
| - name = node->name;
|
| - }
|
| - }
|
| -
|
| - if (ctxt != NULL)
|
| - type = "runtime error";
|
| - else if (style != NULL) {
|
| -#ifdef XSLT_REFACTORED
|
| - if (XSLT_CCTXT(style)->errSeverity == XSLT_ERROR_SEVERITY_WARNING)
|
| - type = "compilation warning";
|
| - else
|
| - type = "compilation error";
|
| -#else
|
| - type = "compilation error";
|
| -#endif
|
| - }
|
| -
|
| - if ((file != NULL) && (line != 0) && (name != NULL))
|
| - error(errctx, "%s: file %s line %d element %s\n",
|
| - type, file, line, name);
|
| - else if ((file != NULL) && (name != NULL))
|
| - error(errctx, "%s: file %s element %s\n", type, file, name);
|
| - else if ((file != NULL) && (line != 0))
|
| - error(errctx, "%s: file %s line %d\n", type, file, line);
|
| - else if (file != NULL)
|
| - error(errctx, "%s: file %s\n", type, file);
|
| - else if (name != NULL)
|
| - error(errctx, "%s: element %s\n", type, name);
|
| - else
|
| - error(errctx, "%s\n", type);
|
| -}
|
| -
|
| -/**
|
| - * xsltSetTransformErrorFunc:
|
| - * @ctxt: the XSLT transformation context
|
| - * @ctx: the new error handling context
|
| - * @handler: the new handler function
|
| - *
|
| - * Function to reset the handler and the error context for out of
|
| - * context error messages specific to a given XSLT transromation.
|
| - *
|
| - * This simply means that @handler will be called for subsequent
|
| - * error messages while running the transformation.
|
| - */
|
| -void
|
| -xsltSetTransformErrorFunc(xsltTransformContextPtr ctxt,
|
| - void *ctx, xmlGenericErrorFunc handler)
|
| -{
|
| - ctxt->error = handler;
|
| - ctxt->errctx = ctx;
|
| -}
|
| -
|
| -/**
|
| - * xsltTransformError:
|
| - * @ctxt: an XSLT transformation context
|
| - * @style: the XSLT stylesheet used
|
| - * @node: the current node in the stylesheet
|
| - * @msg: the message to display/transmit
|
| - * @...: extra parameters for the message display
|
| - *
|
| - * Display and format an error messages, gives file, line, position and
|
| - * extra parameters, will use the specific transformation context if available
|
| - */
|
| -void
|
| -xsltTransformError(xsltTransformContextPtr ctxt,
|
| - xsltStylesheetPtr style,
|
| - xmlNodePtr node,
|
| - const char *msg, ...) {
|
| - xmlGenericErrorFunc error = xsltGenericError;
|
| - void *errctx = xsltGenericErrorContext;
|
| - char * str;
|
| -
|
| - if (ctxt != NULL) {
|
| - if (ctxt->state == XSLT_STATE_OK)
|
| - ctxt->state = XSLT_STATE_ERROR;
|
| - if (ctxt->error != NULL) {
|
| - error = ctxt->error;
|
| - errctx = ctxt->errctx;
|
| - }
|
| - }
|
| - if ((node == NULL) && (ctxt != NULL))
|
| - node = ctxt->inst;
|
| - xsltPrintErrorContext(ctxt, style, node);
|
| - XSLT_GET_VAR_STR(msg, str);
|
| - error(errctx, "%s", str);
|
| - if (str != NULL)
|
| - xmlFree(str);
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * QNames *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/**
|
| - * xsltSplitQName:
|
| - * @dict: a dictionary
|
| - * @name: the full QName
|
| - * @prefix: the return value
|
| - *
|
| - * Split QNames into prefix and local names, both allocated from a dictionary.
|
| - *
|
| - * Returns: the localname or NULL in case of error.
|
| - */
|
| -const xmlChar *
|
| -xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix) {
|
| - int len = 0;
|
| - const xmlChar *ret = NULL;
|
| -
|
| - *prefix = NULL;
|
| - if ((name == NULL) || (dict == NULL)) return(NULL);
|
| - if (name[0] == ':')
|
| - return(xmlDictLookup(dict, name, -1));
|
| - while ((name[len] != 0) && (name[len] != ':')) len++;
|
| - if (name[len] == 0) return(xmlDictLookup(dict, name, -1));
|
| - *prefix = xmlDictLookup(dict, name, len);
|
| - ret = xmlDictLookup(dict, &name[len + 1], -1);
|
| - return(ret);
|
| -}
|
| -
|
| -/**
|
| - * xsltGetQNameURI:
|
| - * @node: the node holding the QName
|
| - * @name: pointer to the initial QName value
|
| - *
|
| - * This function analyzes @name, if the name contains a prefix,
|
| - * the function seaches the associated namespace in scope for it.
|
| - * It will also replace @name value with the NCName, the old value being
|
| - * freed.
|
| - * Errors in the prefix lookup are signalled by setting @name to NULL.
|
| - *
|
| - * NOTE: the namespace returned is a pointer to the place where it is
|
| - * defined and hence has the same lifespan as the document holding it.
|
| - *
|
| - * Returns the namespace URI if there is a prefix, or NULL if @name is
|
| - * not prefixed.
|
| - */
|
| -const xmlChar *
|
| -xsltGetQNameURI(xmlNodePtr node, xmlChar ** name)
|
| -{
|
| - int len = 0;
|
| - xmlChar *qname;
|
| - xmlNsPtr ns;
|
| -
|
| - if (name == NULL)
|
| - return(NULL);
|
| - qname = *name;
|
| - if ((qname == NULL) || (*qname == 0))
|
| - return(NULL);
|
| - if (node == NULL) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "QName: no element for namespace lookup %s\n",
|
| - qname);
|
| - xmlFree(qname);
|
| - *name = NULL;
|
| - return(NULL);
|
| - }
|
| -
|
| - /* nasty but valid */
|
| - if (qname[0] == ':')
|
| - return(NULL);
|
| -
|
| - /*
|
| - * we are not trying to validate but just to cut, and yes it will
|
| - * work even if this is a set of UTF-8 encoded chars
|
| - */
|
| - while ((qname[len] != 0) && (qname[len] != ':'))
|
| - len++;
|
| -
|
| - if (qname[len] == 0)
|
| - return(NULL);
|
| -
|
| - /*
|
| - * handle xml: separately, this one is magical
|
| - */
|
| - if ((qname[0] == 'x') && (qname[1] == 'm') &&
|
| - (qname[2] == 'l') && (qname[3] == ':')) {
|
| - if (qname[4] == 0)
|
| - return(NULL);
|
| - *name = xmlStrdup(&qname[4]);
|
| - xmlFree(qname);
|
| - return(XML_XML_NAMESPACE);
|
| - }
|
| -
|
| - qname[len] = 0;
|
| - ns = xmlSearchNs(node->doc, node, qname);
|
| - if (ns == NULL) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "%s:%s : no namespace bound to prefix %s\n",
|
| - qname, &qname[len + 1], qname);
|
| - *name = NULL;
|
| - xmlFree(qname);
|
| - return(NULL);
|
| - }
|
| - *name = xmlStrdup(&qname[len + 1]);
|
| - xmlFree(qname);
|
| - return(ns->href);
|
| -}
|
| -
|
| -/**
|
| - * xsltGetQNameURI2:
|
| - * @style: stylesheet pointer
|
| - * @node: the node holding the QName
|
| - * @name: pointer to the initial QName value
|
| - *
|
| - * This function is similar to xsltGetQNameURI, but is used when
|
| - * @name is a dictionary entry.
|
| - *
|
| - * Returns the namespace URI if there is a prefix, or NULL if @name is
|
| - * not prefixed.
|
| - */
|
| -const xmlChar *
|
| -xsltGetQNameURI2(xsltStylesheetPtr style, xmlNodePtr node,
|
| - const xmlChar **name) {
|
| - int len = 0;
|
| - xmlChar *qname;
|
| - xmlNsPtr ns;
|
| -
|
| - if (name == NULL)
|
| - return(NULL);
|
| - qname = (xmlChar *)*name;
|
| - if ((qname == NULL) || (*qname == 0))
|
| - return(NULL);
|
| - if (node == NULL) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "QName: no element for namespace lookup %s\n",
|
| - qname);
|
| - *name = NULL;
|
| - return(NULL);
|
| - }
|
| -
|
| - /*
|
| - * we are not trying to validate but just to cut, and yes it will
|
| - * work even if this is a set of UTF-8 encoded chars
|
| - */
|
| - while ((qname[len] != 0) && (qname[len] != ':'))
|
| - len++;
|
| -
|
| - if (qname[len] == 0)
|
| - return(NULL);
|
| -
|
| - /*
|
| - * handle xml: separately, this one is magical
|
| - */
|
| - if ((qname[0] == 'x') && (qname[1] == 'm') &&
|
| - (qname[2] == 'l') && (qname[3] == ':')) {
|
| - if (qname[4] == 0)
|
| - return(NULL);
|
| - *name = xmlDictLookup(style->dict, &qname[4], -1);
|
| - return(XML_XML_NAMESPACE);
|
| - }
|
| -
|
| - qname = xmlStrndup(*name, len);
|
| - ns = xmlSearchNs(node->doc, node, qname);
|
| - if (ns == NULL) {
|
| - if (style) {
|
| - xsltTransformError(NULL, style, node,
|
| - "No namespace bound to prefix '%s'.\n",
|
| - qname);
|
| - style->errors++;
|
| - } else {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "%s : no namespace bound to prefix %s\n",
|
| - *name, qname);
|
| - }
|
| - *name = NULL;
|
| - xmlFree(qname);
|
| - return(NULL);
|
| - }
|
| - *name = xmlDictLookup(style->dict, (*name)+len+1, -1);
|
| - xmlFree(qname);
|
| - return(ns->href);
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Sorting *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/**
|
| - * xsltDocumentSortFunction:
|
| - * @list: the node set
|
| - *
|
| - * reorder the current node list @list accordingly to the document order
|
| - * This function is slow, obsolete and should not be used anymore.
|
| - */
|
| -void
|
| -xsltDocumentSortFunction(xmlNodeSetPtr list) {
|
| - int i, j;
|
| - int len, tst;
|
| - xmlNodePtr node;
|
| -
|
| - if (list == NULL)
|
| - return;
|
| - len = list->nodeNr;
|
| - if (len <= 1)
|
| - return;
|
| - /* TODO: sort is really not optimized, does it needs to ? */
|
| - for (i = 0;i < len -1;i++) {
|
| - for (j = i + 1; j < len; j++) {
|
| - tst = xmlXPathCmpNodes(list->nodeTab[i], list->nodeTab[j]);
|
| - if (tst == -1) {
|
| - node = list->nodeTab[i];
|
| - list->nodeTab[i] = list->nodeTab[j];
|
| - list->nodeTab[j] = node;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * xsltComputeSortResult:
|
| - * @ctxt: a XSLT process context
|
| - * @sort: node list
|
| - *
|
| - * reorder the current node list accordingly to the set of sorting
|
| - * requirement provided by the array of nodes.
|
| - *
|
| - * Returns a ordered XPath nodeset or NULL in case of error.
|
| - */
|
| -xmlXPathObjectPtr *
|
| -xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
|
| -#ifdef XSLT_REFACTORED
|
| - xsltStyleItemSortPtr comp;
|
| -#else
|
| - xsltStylePreCompPtr comp;
|
| -#endif
|
| - xmlXPathObjectPtr *results = NULL;
|
| - xmlNodeSetPtr list = NULL;
|
| - xmlXPathObjectPtr res;
|
| - int len = 0;
|
| - int i;
|
| - xmlNodePtr oldNode;
|
| - xmlNodePtr oldInst;
|
| - int oldPos, oldSize ;
|
| - int oldNsNr;
|
| - xmlNsPtr *oldNamespaces;
|
| -
|
| - comp = sort->psvi;
|
| - if (comp == NULL) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "xsl:sort : compilation failed\n");
|
| - return(NULL);
|
| - }
|
| -
|
| - if ((comp->select == NULL) || (comp->comp == NULL))
|
| - return(NULL);
|
| -
|
| - list = ctxt->nodeList;
|
| - if ((list == NULL) || (list->nodeNr <= 1))
|
| - return(NULL);
|
| -
|
| - len = list->nodeNr;
|
| -
|
| - /* TODO: xsl:sort lang attribute */
|
| - /* TODO: xsl:sort case-order attribute */
|
| -
|
| -
|
| - results = xmlMalloc(len * sizeof(xmlXPathObjectPtr));
|
| - if (results == NULL) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "xsltComputeSortResult: memory allocation failure\n");
|
| - return(NULL);
|
| - }
|
| -
|
| - oldNode = ctxt->node;
|
| - oldInst = ctxt->inst;
|
| - oldPos = ctxt->xpathCtxt->proximityPosition;
|
| - oldSize = ctxt->xpathCtxt->contextSize;
|
| - oldNsNr = ctxt->xpathCtxt->nsNr;
|
| - oldNamespaces = ctxt->xpathCtxt->namespaces;
|
| - for (i = 0;i < len;i++) {
|
| - ctxt->inst = sort;
|
| - ctxt->xpathCtxt->contextSize = len;
|
| - ctxt->xpathCtxt->proximityPosition = i + 1;
|
| - ctxt->node = list->nodeTab[i];
|
| - ctxt->xpathCtxt->node = ctxt->node;
|
| -#ifdef XSLT_REFACTORED
|
| - if (comp->inScopeNs != NULL) {
|
| - ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;
|
| - ctxt->xpathCtxt->nsNr = comp->inScopeNs->xpathNumber;
|
| - } else {
|
| - ctxt->xpathCtxt->namespaces = NULL;
|
| - ctxt->xpathCtxt->nsNr = 0;
|
| - }
|
| -#else
|
| - ctxt->xpathCtxt->namespaces = comp->nsList;
|
| - ctxt->xpathCtxt->nsNr = comp->nsNr;
|
| -#endif
|
| - res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);
|
| - if (res != NULL) {
|
| - if (res->type != XPATH_STRING)
|
| - res = xmlXPathConvertString(res);
|
| - if (comp->number)
|
| - res = xmlXPathConvertNumber(res);
|
| - res->index = i; /* Save original pos for dupl resolv */
|
| - if (comp->number) {
|
| - if (res->type == XPATH_NUMBER) {
|
| - results[i] = res;
|
| - } else {
|
| -#ifdef WITH_XSLT_DEBUG_PROCESS
|
| - xsltGenericDebug(xsltGenericDebugContext,
|
| - "xsltComputeSortResult: select didn't evaluate to a number\n");
|
| -#endif
|
| - results[i] = NULL;
|
| - }
|
| - } else {
|
| - if (res->type == XPATH_STRING) {
|
| - if (comp->locale != (xsltLocale)0) {
|
| - xmlChar *str = res->stringval;
|
| - res->stringval = (xmlChar *) xsltStrxfrm(comp->locale, str);
|
| - xmlFree(str);
|
| - }
|
| -
|
| - results[i] = res;
|
| - } else {
|
| -#ifdef WITH_XSLT_DEBUG_PROCESS
|
| - xsltGenericDebug(xsltGenericDebugContext,
|
| - "xsltComputeSortResult: select didn't evaluate to a string\n");
|
| -#endif
|
| - results[i] = NULL;
|
| - }
|
| - }
|
| - } else {
|
| - ctxt->state = XSLT_STATE_STOPPED;
|
| - results[i] = NULL;
|
| - }
|
| - }
|
| - ctxt->node = oldNode;
|
| - ctxt->inst = oldInst;
|
| - ctxt->xpathCtxt->contextSize = oldSize;
|
| - ctxt->xpathCtxt->proximityPosition = oldPos;
|
| - ctxt->xpathCtxt->nsNr = oldNsNr;
|
| - ctxt->xpathCtxt->namespaces = oldNamespaces;
|
| -
|
| - return(results);
|
| -}
|
| -
|
| -/**
|
| - * xsltDefaultSortFunction:
|
| - * @ctxt: a XSLT process context
|
| - * @sorts: array of sort nodes
|
| - * @nbsorts: the number of sorts in the array
|
| - *
|
| - * reorder the current node list accordingly to the set of sorting
|
| - * requirement provided by the arry of nodes.
|
| - */
|
| -void
|
| -xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
|
| - int nbsorts) {
|
| -#ifdef XSLT_REFACTORED
|
| - xsltStyleItemSortPtr comp;
|
| -#else
|
| - xsltStylePreCompPtr comp;
|
| -#endif
|
| - xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];
|
| - xmlXPathObjectPtr *results = NULL, *res;
|
| - xmlNodeSetPtr list = NULL;
|
| - int descending, number, desc, numb;
|
| - int len = 0;
|
| - int i, j, incr;
|
| - int tst;
|
| - int depth;
|
| - xmlNodePtr node;
|
| - xmlXPathObjectPtr tmp;
|
| - int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];
|
| -
|
| - if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
|
| - (nbsorts >= XSLT_MAX_SORT))
|
| - return;
|
| - if (sorts[0] == NULL)
|
| - return;
|
| - comp = sorts[0]->psvi;
|
| - if (comp == NULL)
|
| - return;
|
| -
|
| - list = ctxt->nodeList;
|
| - if ((list == NULL) || (list->nodeNr <= 1))
|
| - return; /* nothing to do */
|
| -
|
| - for (j = 0; j < nbsorts; j++) {
|
| - comp = sorts[j]->psvi;
|
| - tempstype[j] = 0;
|
| - if ((comp->stype == NULL) && (comp->has_stype != 0)) {
|
| - comp->stype =
|
| - xsltEvalAttrValueTemplate(ctxt, sorts[j],
|
| - (const xmlChar *) "data-type",
|
| - XSLT_NAMESPACE);
|
| - if (comp->stype != NULL) {
|
| - tempstype[j] = 1;
|
| - if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
|
| - comp->number = 0;
|
| - else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
|
| - comp->number = 1;
|
| - else {
|
| - xsltTransformError(ctxt, NULL, sorts[j],
|
| - "xsltDoSortFunction: no support for data-type = %s\n",
|
| - comp->stype);
|
| - comp->number = 0; /* use default */
|
| - }
|
| - }
|
| - }
|
| - temporder[j] = 0;
|
| - if ((comp->order == NULL) && (comp->has_order != 0)) {
|
| - comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
|
| - (const xmlChar *) "order",
|
| - XSLT_NAMESPACE);
|
| - if (comp->order != NULL) {
|
| - temporder[j] = 1;
|
| - if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
|
| - comp->descending = 0;
|
| - else if (xmlStrEqual(comp->order,
|
| - (const xmlChar *) "descending"))
|
| - comp->descending = 1;
|
| - else {
|
| - xsltTransformError(ctxt, NULL, sorts[j],
|
| - "xsltDoSortFunction: invalid value %s for order\n",
|
| - comp->order);
|
| - comp->descending = 0; /* use default */
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - len = list->nodeNr;
|
| -
|
| - resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
|
| - for (i = 1;i < XSLT_MAX_SORT;i++)
|
| - resultsTab[i] = NULL;
|
| -
|
| - results = resultsTab[0];
|
| -
|
| - comp = sorts[0]->psvi;
|
| - descending = comp->descending;
|
| - number = comp->number;
|
| - if (results == NULL)
|
| - return;
|
| -
|
| - /* Shell's sort of node-set */
|
| - for (incr = len / 2; incr > 0; incr /= 2) {
|
| - for (i = incr; i < len; i++) {
|
| - j = i - incr;
|
| - if (results[i] == NULL)
|
| - continue;
|
| -
|
| - while (j >= 0) {
|
| - if (results[j] == NULL)
|
| - tst = 1;
|
| - else {
|
| - if (number) {
|
| - /* We make NaN smaller than number in accordance
|
| - with XSLT spec */
|
| - if (xmlXPathIsNaN(results[j]->floatval)) {
|
| - if (xmlXPathIsNaN(results[j + incr]->floatval))
|
| - tst = 0;
|
| - else
|
| - tst = -1;
|
| - } else if (xmlXPathIsNaN(results[j + incr]->floatval))
|
| - tst = 1;
|
| - else if (results[j]->floatval ==
|
| - results[j + incr]->floatval)
|
| - tst = 0;
|
| - else if (results[j]->floatval >
|
| - results[j + incr]->floatval)
|
| - tst = 1;
|
| - else tst = -1;
|
| - } else if(comp->locale != (xsltLocale)0) {
|
| - tst = xsltLocaleStrcmp(
|
| - comp->locale,
|
| - (xsltLocaleChar *) results[j]->stringval,
|
| - (xsltLocaleChar *) results[j + incr]->stringval);
|
| - } else {
|
| - tst = xmlStrcmp(results[j]->stringval,
|
| - results[j + incr]->stringval);
|
| - }
|
| - if (descending)
|
| - tst = -tst;
|
| - }
|
| - if (tst == 0) {
|
| - /*
|
| - * Okay we need to use multi level sorts
|
| - */
|
| - depth = 1;
|
| - while (depth < nbsorts) {
|
| - if (sorts[depth] == NULL)
|
| - break;
|
| - comp = sorts[depth]->psvi;
|
| - if (comp == NULL)
|
| - break;
|
| - desc = comp->descending;
|
| - numb = comp->number;
|
| -
|
| - /*
|
| - * Compute the result of the next level for the
|
| - * full set, this might be optimized ... or not
|
| - */
|
| - if (resultsTab[depth] == NULL)
|
| - resultsTab[depth] = xsltComputeSortResult(ctxt,
|
| - sorts[depth]);
|
| - res = resultsTab[depth];
|
| - if (res == NULL)
|
| - break;
|
| - if (res[j] == NULL) {
|
| - if (res[j+incr] != NULL)
|
| - tst = 1;
|
| - } else {
|
| - if (numb) {
|
| - /* We make NaN smaller than number in
|
| - accordance with XSLT spec */
|
| - if (xmlXPathIsNaN(res[j]->floatval)) {
|
| - if (xmlXPathIsNaN(res[j +
|
| - incr]->floatval))
|
| - tst = 0;
|
| - else
|
| - tst = -1;
|
| - } else if (xmlXPathIsNaN(res[j + incr]->
|
| - floatval))
|
| - tst = 1;
|
| - else if (res[j]->floatval == res[j + incr]->
|
| - floatval)
|
| - tst = 0;
|
| - else if (res[j]->floatval >
|
| - res[j + incr]->floatval)
|
| - tst = 1;
|
| - else tst = -1;
|
| - } else if(comp->locale != (xsltLocale)0) {
|
| - tst = xsltLocaleStrcmp(
|
| - comp->locale,
|
| - (xsltLocaleChar *) res[j]->stringval,
|
| - (xsltLocaleChar *) res[j + incr]->stringval);
|
| - } else {
|
| - tst = xmlStrcmp(res[j]->stringval,
|
| - res[j + incr]->stringval);
|
| - }
|
| - if (desc)
|
| - tst = -tst;
|
| - }
|
| -
|
| - /*
|
| - * if we still can't differenciate at this level
|
| - * try one level deeper.
|
| - */
|
| - if (tst != 0)
|
| - break;
|
| - depth++;
|
| - }
|
| - }
|
| - if (tst == 0) {
|
| - tst = results[j]->index > results[j + incr]->index;
|
| - }
|
| - if (tst > 0) {
|
| - tmp = results[j];
|
| - results[j] = results[j + incr];
|
| - results[j + incr] = tmp;
|
| - node = list->nodeTab[j];
|
| - list->nodeTab[j] = list->nodeTab[j + incr];
|
| - list->nodeTab[j + incr] = node;
|
| - depth = 1;
|
| - while (depth < nbsorts) {
|
| - if (sorts[depth] == NULL)
|
| - break;
|
| - if (resultsTab[depth] == NULL)
|
| - break;
|
| - res = resultsTab[depth];
|
| - tmp = res[j];
|
| - res[j] = res[j + incr];
|
| - res[j + incr] = tmp;
|
| - depth++;
|
| - }
|
| - j -= incr;
|
| - } else
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - for (j = 0; j < nbsorts; j++) {
|
| - comp = sorts[j]->psvi;
|
| - if (tempstype[j] == 1) {
|
| - /* The data-type needs to be recomputed each time */
|
| - xmlFree((void *)(comp->stype));
|
| - comp->stype = NULL;
|
| - }
|
| - if (temporder[j] == 1) {
|
| - /* The order needs to be recomputed each time */
|
| - xmlFree((void *)(comp->order));
|
| - comp->order = NULL;
|
| - }
|
| - if (resultsTab[j] != NULL) {
|
| - for (i = 0;i < len;i++)
|
| - xmlXPathFreeObject(resultsTab[j][i]);
|
| - xmlFree(resultsTab[j]);
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| -static xsltSortFunc xsltSortFunction = xsltDefaultSortFunction;
|
| -
|
| -/**
|
| - * xsltDoSortFunction:
|
| - * @ctxt: a XSLT process context
|
| - * @sorts: array of sort nodes
|
| - * @nbsorts: the number of sorts in the array
|
| - *
|
| - * reorder the current node list accordingly to the set of sorting
|
| - * requirement provided by the arry of nodes.
|
| - * This is a wrapper function, the actual function used is specified
|
| - * using xsltSetCtxtSortFunc() to set the context specific sort function,
|
| - * or xsltSetSortFunc() to set the global sort function.
|
| - * If a sort function is set on the context, this will get called.
|
| - * Otherwise the global sort function is called.
|
| - */
|
| -void
|
| -xsltDoSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr * sorts,
|
| - int nbsorts)
|
| -{
|
| - if (ctxt->sortfunc != NULL)
|
| - (ctxt->sortfunc)(ctxt, sorts, nbsorts);
|
| - else if (xsltSortFunction != NULL)
|
| - xsltSortFunction(ctxt, sorts, nbsorts);
|
| -}
|
| -
|
| -/**
|
| - * xsltSetSortFunc:
|
| - * @handler: the new handler function
|
| - *
|
| - * Function to reset the global handler for XSLT sorting.
|
| - * If the handler is NULL, the default sort function will be used.
|
| - */
|
| -void
|
| -xsltSetSortFunc(xsltSortFunc handler) {
|
| - if (handler != NULL)
|
| - xsltSortFunction = handler;
|
| - else
|
| - xsltSortFunction = xsltDefaultSortFunction;
|
| -}
|
| -
|
| -/**
|
| - * xsltSetCtxtSortFunc:
|
| - * @ctxt: a XSLT process context
|
| - * @handler: the new handler function
|
| - *
|
| - * Function to set the handler for XSLT sorting
|
| - * for the specified context.
|
| - * If the handler is NULL, then the global
|
| - * sort function will be called
|
| - */
|
| -void
|
| -xsltSetCtxtSortFunc(xsltTransformContextPtr ctxt, xsltSortFunc handler) {
|
| - ctxt->sortfunc = handler;
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Parsing options *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/**
|
| - * xsltSetCtxtParseOptions:
|
| - * @ctxt: a XSLT process context
|
| - * @options: a combination of libxml2 xmlParserOption
|
| - *
|
| - * Change the default parser option passed by the XSLT engine to the
|
| - * parser when using document() loading.
|
| - *
|
| - * Returns the previous options or -1 in case of error
|
| - */
|
| -int
|
| -xsltSetCtxtParseOptions(xsltTransformContextPtr ctxt, int options)
|
| -{
|
| - int oldopts;
|
| -
|
| - if (ctxt == NULL)
|
| - return(-1);
|
| - oldopts = ctxt->parserOptions;
|
| - if (ctxt->xinclude)
|
| - oldopts |= XML_PARSE_XINCLUDE;
|
| - ctxt->parserOptions = options;
|
| - if (options & XML_PARSE_XINCLUDE)
|
| - ctxt->xinclude = 1;
|
| - else
|
| - ctxt->xinclude = 0;
|
| - return(oldopts);
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Output *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/**
|
| - * xsltSaveResultTo:
|
| - * @buf: an output buffer
|
| - * @result: the result xmlDocPtr
|
| - * @style: the stylesheet
|
| - *
|
| - * Save the result @result obtained by applying the @style stylesheet
|
| - * to an I/O output channel @buf
|
| - *
|
| - * Returns the number of byte written or -1 in case of failure.
|
| - */
|
| -int
|
| -xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result,
|
| - xsltStylesheetPtr style) {
|
| - const xmlChar *encoding;
|
| - int base;
|
| - const xmlChar *method;
|
| - int indent;
|
| -
|
| - if ((buf == NULL) || (result == NULL) || (style == NULL))
|
| - return(-1);
|
| - if ((result->children == NULL) ||
|
| - ((result->children->type == XML_DTD_NODE) &&
|
| - (result->children->next == NULL)))
|
| - return(0);
|
| -
|
| - if ((style->methodURI != NULL) &&
|
| - ((style->method == NULL) ||
|
| - (!xmlStrEqual(style->method, (const xmlChar *) "xhtml")))) {
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "xsltSaveResultTo : unknown ouput method\n");
|
| - return(-1);
|
| - }
|
| -
|
| - base = buf->written;
|
| -
|
| - XSLT_GET_IMPORT_PTR(method, style, method)
|
| - XSLT_GET_IMPORT_PTR(encoding, style, encoding)
|
| - XSLT_GET_IMPORT_INT(indent, style, indent);
|
| -
|
| - if ((method == NULL) && (result->type == XML_HTML_DOCUMENT_NODE))
|
| - method = (const xmlChar *) "html";
|
| -
|
| - if ((method != NULL) &&
|
| - (xmlStrEqual(method, (const xmlChar *) "html"))) {
|
| - if (encoding != NULL) {
|
| - htmlSetMetaEncoding(result, (const xmlChar *) encoding);
|
| - } else {
|
| - htmlSetMetaEncoding(result, (const xmlChar *) "UTF-8");
|
| - }
|
| - if (indent == -1)
|
| - indent = 1;
|
| - htmlDocContentDumpFormatOutput(buf, result, (const char *) encoding,
|
| - indent);
|
| - xmlOutputBufferFlush(buf);
|
| - } else if ((method != NULL) &&
|
| - (xmlStrEqual(method, (const xmlChar *) "xhtml"))) {
|
| - if (encoding != NULL) {
|
| - htmlSetMetaEncoding(result, (const xmlChar *) encoding);
|
| - } else {
|
| - htmlSetMetaEncoding(result, (const xmlChar *) "UTF-8");
|
| - }
|
| - htmlDocContentDumpOutput(buf, result, (const char *) encoding);
|
| - xmlOutputBufferFlush(buf);
|
| - } else if ((method != NULL) &&
|
| - (xmlStrEqual(method, (const xmlChar *) "text"))) {
|
| - xmlNodePtr cur;
|
| -
|
| - cur = result->children;
|
| - while (cur != NULL) {
|
| - if (cur->type == XML_TEXT_NODE)
|
| - xmlOutputBufferWriteString(buf, (const char *) cur->content);
|
| -
|
| - /*
|
| - * Skip to next node
|
| - */
|
| - if (cur->children != NULL) {
|
| - if ((cur->children->type != XML_ENTITY_DECL) &&
|
| - (cur->children->type != XML_ENTITY_REF_NODE) &&
|
| - (cur->children->type != XML_ENTITY_NODE)) {
|
| - cur = cur->children;
|
| - continue;
|
| - }
|
| - }
|
| - if (cur->next != NULL) {
|
| - cur = cur->next;
|
| - continue;
|
| - }
|
| -
|
| - do {
|
| - cur = cur->parent;
|
| - if (cur == NULL)
|
| - break;
|
| - if (cur == (xmlNodePtr) style->doc) {
|
| - cur = NULL;
|
| - break;
|
| - }
|
| - if (cur->next != NULL) {
|
| - cur = cur->next;
|
| - break;
|
| - }
|
| - } while (cur != NULL);
|
| - }
|
| - xmlOutputBufferFlush(buf);
|
| - } else {
|
| - int omitXmlDecl;
|
| - int standalone;
|
| -
|
| - XSLT_GET_IMPORT_INT(omitXmlDecl, style, omitXmlDeclaration);
|
| - XSLT_GET_IMPORT_INT(standalone, style, standalone);
|
| -
|
| - if (omitXmlDecl != 1) {
|
| - xmlOutputBufferWriteString(buf, "<?xml version=");
|
| - if (result->version != NULL) {
|
| - xmlOutputBufferWriteString(buf, "\"");
|
| - xmlOutputBufferWriteString(buf, (const char *)result->version);
|
| - xmlOutputBufferWriteString(buf, "\"");
|
| - } else
|
| - xmlOutputBufferWriteString(buf, "\"1.0\"");
|
| - if (encoding == NULL) {
|
| - if (result->encoding != NULL)
|
| - encoding = result->encoding;
|
| - else if (result->charset != XML_CHAR_ENCODING_UTF8)
|
| - encoding = (const xmlChar *)
|
| - xmlGetCharEncodingName((xmlCharEncoding)
|
| - result->charset);
|
| - }
|
| - if (encoding != NULL) {
|
| - xmlOutputBufferWriteString(buf, " encoding=");
|
| - xmlOutputBufferWriteString(buf, "\"");
|
| - xmlOutputBufferWriteString(buf, (const char *) encoding);
|
| - xmlOutputBufferWriteString(buf, "\"");
|
| - }
|
| - switch (standalone) {
|
| - case 0:
|
| - xmlOutputBufferWriteString(buf, " standalone=\"no\"");
|
| - break;
|
| - case 1:
|
| - xmlOutputBufferWriteString(buf, " standalone=\"yes\"");
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - xmlOutputBufferWriteString(buf, "?>\n");
|
| - }
|
| - if (result->children != NULL) {
|
| - xmlNodePtr child = result->children;
|
| -
|
| - while (child != NULL) {
|
| - xmlNodeDumpOutput(buf, result, child, 0, (indent == 1),
|
| - (const char *) encoding);
|
| - if (indent && ((child->type == XML_DTD_NODE) ||
|
| - ((child->type == XML_COMMENT_NODE) &&
|
| - (child->next != NULL))))
|
| - xmlOutputBufferWriteString(buf, "\n");
|
| - child = child->next;
|
| - }
|
| - if (indent)
|
| - xmlOutputBufferWriteString(buf, "\n");
|
| - }
|
| - xmlOutputBufferFlush(buf);
|
| - }
|
| - return(buf->written - base);
|
| -}
|
| -
|
| -/**
|
| - * xsltSaveResultToFilename:
|
| - * @URL: a filename or URL
|
| - * @result: the result xmlDocPtr
|
| - * @style: the stylesheet
|
| - * @compression: the compression factor (0 - 9 included)
|
| - *
|
| - * Save the result @result obtained by applying the @style stylesheet
|
| - * to a file or @URL
|
| - *
|
| - * Returns the number of byte written or -1 in case of failure.
|
| - */
|
| -int
|
| -xsltSaveResultToFilename(const char *URL, xmlDocPtr result,
|
| - xsltStylesheetPtr style, int compression) {
|
| - xmlOutputBufferPtr buf;
|
| - const xmlChar *encoding;
|
| - int ret;
|
| -
|
| - if ((URL == NULL) || (result == NULL) || (style == NULL))
|
| - return(-1);
|
| - if (result->children == NULL)
|
| - return(0);
|
| -
|
| - XSLT_GET_IMPORT_PTR(encoding, style, encoding)
|
| - if (encoding != NULL) {
|
| - xmlCharEncodingHandlerPtr encoder;
|
| -
|
| - encoder = xmlFindCharEncodingHandler((char *)encoding);
|
| - if ((encoder != NULL) &&
|
| - (xmlStrEqual((const xmlChar *)encoder->name,
|
| - (const xmlChar *) "UTF-8")))
|
| - encoder = NULL;
|
| - buf = xmlOutputBufferCreateFilename(URL, encoder, compression);
|
| - } else {
|
| - buf = xmlOutputBufferCreateFilename(URL, NULL, compression);
|
| - }
|
| - if (buf == NULL)
|
| - return(-1);
|
| - xsltSaveResultTo(buf, result, style);
|
| - ret = xmlOutputBufferClose(buf);
|
| - return(ret);
|
| -}
|
| -
|
| -/**
|
| - * xsltSaveResultToFile:
|
| - * @file: a FILE * I/O
|
| - * @result: the result xmlDocPtr
|
| - * @style: the stylesheet
|
| - *
|
| - * Save the result @result obtained by applying the @style stylesheet
|
| - * to an open FILE * I/O.
|
| - * This does not close the FILE @file
|
| - *
|
| - * Returns the number of bytes written or -1 in case of failure.
|
| - */
|
| -int
|
| -xsltSaveResultToFile(FILE *file, xmlDocPtr result, xsltStylesheetPtr style) {
|
| - xmlOutputBufferPtr buf;
|
| - const xmlChar *encoding;
|
| - int ret;
|
| -
|
| - if ((file == NULL) || (result == NULL) || (style == NULL))
|
| - return(-1);
|
| - if (result->children == NULL)
|
| - return(0);
|
| -
|
| - XSLT_GET_IMPORT_PTR(encoding, style, encoding)
|
| - if (encoding != NULL) {
|
| - xmlCharEncodingHandlerPtr encoder;
|
| -
|
| - encoder = xmlFindCharEncodingHandler((char *)encoding);
|
| - if ((encoder != NULL) &&
|
| - (xmlStrEqual((const xmlChar *)encoder->name,
|
| - (const xmlChar *) "UTF-8")))
|
| - encoder = NULL;
|
| - buf = xmlOutputBufferCreateFile(file, encoder);
|
| - } else {
|
| - buf = xmlOutputBufferCreateFile(file, NULL);
|
| - }
|
| -
|
| - if (buf == NULL)
|
| - return(-1);
|
| - xsltSaveResultTo(buf, result, style);
|
| - ret = xmlOutputBufferClose(buf);
|
| - return(ret);
|
| -}
|
| -
|
| -/**
|
| - * xsltSaveResultToFd:
|
| - * @fd: a file descriptor
|
| - * @result: the result xmlDocPtr
|
| - * @style: the stylesheet
|
| - *
|
| - * Save the result @result obtained by applying the @style stylesheet
|
| - * to an open file descriptor
|
| - * This does not close the descriptor.
|
| - *
|
| - * Returns the number of bytes written or -1 in case of failure.
|
| - */
|
| -int
|
| -xsltSaveResultToFd(int fd, xmlDocPtr result, xsltStylesheetPtr style) {
|
| - xmlOutputBufferPtr buf;
|
| - const xmlChar *encoding;
|
| - int ret;
|
| -
|
| - if ((fd < 0) || (result == NULL) || (style == NULL))
|
| - return(-1);
|
| - if (result->children == NULL)
|
| - return(0);
|
| -
|
| - XSLT_GET_IMPORT_PTR(encoding, style, encoding)
|
| - if (encoding != NULL) {
|
| - xmlCharEncodingHandlerPtr encoder;
|
| -
|
| - encoder = xmlFindCharEncodingHandler((char *)encoding);
|
| - if ((encoder != NULL) &&
|
| - (xmlStrEqual((const xmlChar *)encoder->name,
|
| - (const xmlChar *) "UTF-8")))
|
| - encoder = NULL;
|
| - buf = xmlOutputBufferCreateFd(fd, encoder);
|
| - } else {
|
| - buf = xmlOutputBufferCreateFd(fd, NULL);
|
| - }
|
| - if (buf == NULL)
|
| - return(-1);
|
| - xsltSaveResultTo(buf, result, style);
|
| - ret = xmlOutputBufferClose(buf);
|
| - return(ret);
|
| -}
|
| -
|
| -/**
|
| - * xsltSaveResultToString:
|
| - * @doc_txt_ptr: Memory pointer for allocated XML text
|
| - * @doc_txt_len: Length of the generated XML text
|
| - * @result: the result xmlDocPtr
|
| - * @style: the stylesheet
|
| - *
|
| - * Save the result @result obtained by applying the @style stylesheet
|
| - * to a new allocated string.
|
| - *
|
| - * Returns 0 in case of success and -1 in case of error
|
| - */
|
| -int
|
| -xsltSaveResultToString(xmlChar **doc_txt_ptr, int * doc_txt_len,
|
| - xmlDocPtr result, xsltStylesheetPtr style) {
|
| - xmlOutputBufferPtr buf;
|
| - const xmlChar *encoding;
|
| -
|
| - *doc_txt_ptr = NULL;
|
| - *doc_txt_len = 0;
|
| - if (result->children == NULL)
|
| - return(0);
|
| -
|
| - XSLT_GET_IMPORT_PTR(encoding, style, encoding)
|
| - if (encoding != NULL) {
|
| - xmlCharEncodingHandlerPtr encoder;
|
| -
|
| - encoder = xmlFindCharEncodingHandler((char *)encoding);
|
| - if ((encoder != NULL) &&
|
| - (xmlStrEqual((const xmlChar *)encoder->name,
|
| - (const xmlChar *) "UTF-8")))
|
| - encoder = NULL;
|
| - buf = xmlAllocOutputBuffer(encoder);
|
| - } else {
|
| - buf = xmlAllocOutputBuffer(NULL);
|
| - }
|
| - if (buf == NULL)
|
| - return(-1);
|
| - xsltSaveResultTo(buf, result, style);
|
| -#ifdef LIBXML2_NEW_BUFFER
|
| - if (buf->conv != NULL) {
|
| - *doc_txt_len = xmlBufUse(buf->conv);
|
| - *doc_txt_ptr = xmlStrndup(xmlBufContent(buf->conv), *doc_txt_len);
|
| - } else {
|
| - *doc_txt_len = xmlBufUse(buf->buffer);
|
| - *doc_txt_ptr = xmlStrndup(xmlBufContent(buf->buffer), *doc_txt_len);
|
| - }
|
| -#else
|
| - if (buf->conv != NULL) {
|
| - *doc_txt_len = buf->conv->use;
|
| - *doc_txt_ptr = xmlStrndup(buf->conv->content, *doc_txt_len);
|
| - } else {
|
| - *doc_txt_len = buf->buffer->use;
|
| - *doc_txt_ptr = xmlStrndup(buf->buffer->content, *doc_txt_len);
|
| - }
|
| -#endif
|
| - (void)xmlOutputBufferClose(buf);
|
| - return 0;
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Generating profiling informations *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -static long calibration = -1;
|
| -
|
| -/**
|
| - * xsltCalibrateTimestamps:
|
| - *
|
| - * Used for to calibrate the xsltTimestamp() function
|
| - * Should work if launched at startup and we don't loose our quantum :-)
|
| - *
|
| - * Returns the number of milliseconds used by xsltTimestamp()
|
| - */
|
| -static long
|
| -xsltCalibrateTimestamps(void) {
|
| - register int i;
|
| -
|
| - for (i = 0;i < 999;i++)
|
| - xsltTimestamp();
|
| - return(xsltTimestamp() / 1000);
|
| -}
|
| -
|
| -/**
|
| - * xsltCalibrateAdjust:
|
| - * @delta: a negative dealy value found
|
| - *
|
| - * Used for to correct the calibration for xsltTimestamp()
|
| - */
|
| -void
|
| -xsltCalibrateAdjust(long delta) {
|
| - calibration += delta;
|
| -}
|
| -
|
| -/**
|
| - * xsltTimestamp:
|
| - *
|
| - * Used for gathering profiling data
|
| - *
|
| - * Returns the number of tenth of milliseconds since the beginning of the
|
| - * profiling
|
| - */
|
| -long
|
| -xsltTimestamp(void)
|
| -{
|
| -#ifdef XSLT_WIN32_PERFORMANCE_COUNTER
|
| - BOOL ok;
|
| - LARGE_INTEGER performanceCount;
|
| - LARGE_INTEGER performanceFrequency;
|
| - LONGLONG quadCount;
|
| - double seconds;
|
| - static LONGLONG startupQuadCount = 0;
|
| - static LONGLONG startupQuadFreq = 0;
|
| -
|
| - ok = QueryPerformanceCounter(&performanceCount);
|
| - if (!ok)
|
| - return 0;
|
| - quadCount = performanceCount.QuadPart;
|
| - if (calibration < 0) {
|
| - calibration = 0;
|
| - ok = QueryPerformanceFrequency(&performanceFrequency);
|
| - if (!ok)
|
| - return 0;
|
| - startupQuadFreq = performanceFrequency.QuadPart;
|
| - startupQuadCount = quadCount;
|
| - return (0);
|
| - }
|
| - if (startupQuadFreq == 0)
|
| - return 0;
|
| - seconds = (quadCount - startupQuadCount) / (double) startupQuadFreq;
|
| - return (long) (seconds * XSLT_TIMESTAMP_TICS_PER_SEC);
|
| -
|
| -#else /* XSLT_WIN32_PERFORMANCE_COUNTER */
|
| -#ifdef HAVE_CLOCK_GETTIME
|
| -# if defined(CLOCK_MONOTONIC)
|
| -# define XSLT_CLOCK CLOCK_MONOTONIC
|
| -# elif defined(CLOCK_HIGHRES)
|
| -# define XSLT_CLOCK CLOCK_HIGHRES
|
| -# else
|
| -# define XSLT_CLOCK CLOCK_REALTIME
|
| -# endif
|
| - static struct timespec startup;
|
| - struct timespec cur;
|
| - long tics;
|
| -
|
| - if (calibration < 0) {
|
| - clock_gettime(XSLT_CLOCK, &startup);
|
| - calibration = 0;
|
| - calibration = xsltCalibrateTimestamps();
|
| - clock_gettime(XSLT_CLOCK, &startup);
|
| - return (0);
|
| - }
|
| -
|
| - clock_gettime(XSLT_CLOCK, &cur);
|
| - tics = (cur.tv_sec - startup.tv_sec) * XSLT_TIMESTAMP_TICS_PER_SEC;
|
| - tics += (cur.tv_nsec - startup.tv_nsec) /
|
| - (1000000000l / XSLT_TIMESTAMP_TICS_PER_SEC);
|
| -
|
| - tics -= calibration;
|
| - return(tics);
|
| -
|
| -#elif HAVE_GETTIMEOFDAY
|
| - static struct timeval startup;
|
| - struct timeval cur;
|
| - long tics;
|
| -
|
| - if (calibration < 0) {
|
| - gettimeofday(&startup, NULL);
|
| - calibration = 0;
|
| - calibration = xsltCalibrateTimestamps();
|
| - gettimeofday(&startup, NULL);
|
| - return (0);
|
| - }
|
| -
|
| - gettimeofday(&cur, NULL);
|
| - tics = (cur.tv_sec - startup.tv_sec) * XSLT_TIMESTAMP_TICS_PER_SEC;
|
| - tics += (cur.tv_usec - startup.tv_usec) /
|
| - (1000000l / XSLT_TIMESTAMP_TICS_PER_SEC);
|
| -
|
| - tics -= calibration;
|
| - return(tics);
|
| -#else
|
| -
|
| - /* Neither gettimeofday() nor Win32 performance counter available */
|
| -
|
| - return (0);
|
| -
|
| -#endif /* HAVE_GETTIMEOFDAY */
|
| -#endif /* XSLT_WIN32_PERFORMANCE_COUNTER */
|
| -}
|
| -
|
| -static char *
|
| -pretty_templ_match(xsltTemplatePtr templ) {
|
| - static char dst[1001];
|
| - char *src = (char *)templ->match;
|
| - int i=0,j;
|
| -
|
| - /* strip white spaces */
|
| - for (j=0; i<1000 && src[j]; i++,j++) {
|
| - for(;src[j]==' ';j++);
|
| - dst[i]=src[j];
|
| - }
|
| - if(i<998 && templ->mode) {
|
| - /* append [mode] */
|
| - dst[i++]='[';
|
| - src=(char *)templ->mode;
|
| - for (j=0; i<999 && src[j]; i++,j++) {
|
| - dst[i]=src[j];
|
| - }
|
| - dst[i++]=']';
|
| - }
|
| - dst[i]='\0';
|
| - return dst;
|
| -}
|
| -
|
| -#define MAX_TEMPLATES 10000
|
| -
|
| -/**
|
| - * xsltSaveProfiling:
|
| - * @ctxt: an XSLT context
|
| - * @output: a FILE * for saving the informations
|
| - *
|
| - * Save the profiling informations on @output
|
| - */
|
| -void
|
| -xsltSaveProfiling(xsltTransformContextPtr ctxt, FILE *output) {
|
| - int nb, i,j,k,l;
|
| - int max;
|
| - int total;
|
| - unsigned long totalt;
|
| - xsltTemplatePtr *templates;
|
| - xsltStylesheetPtr style;
|
| - xsltTemplatePtr templ1,templ2;
|
| - int *childt;
|
| -
|
| - if ((output == NULL) || (ctxt == NULL))
|
| - return;
|
| - if (ctxt->profile == 0)
|
| - return;
|
| -
|
| - nb = 0;
|
| - max = MAX_TEMPLATES;
|
| - templates = xmlMalloc(max * sizeof(xsltTemplatePtr));
|
| - if (templates == NULL)
|
| - return;
|
| -
|
| - style = ctxt->style;
|
| - while (style != NULL) {
|
| - templ1 = style->templates;
|
| - while (templ1 != NULL) {
|
| - if (nb >= max)
|
| - break;
|
| -
|
| - if (templ1->nbCalls > 0)
|
| - templates[nb++] = templ1;
|
| - templ1 = templ1->next;
|
| - }
|
| -
|
| - style = xsltNextImport(style);
|
| - }
|
| -
|
| - for (i = 0;i < nb -1;i++) {
|
| - for (j = i + 1; j < nb; j++) {
|
| - if ((templates[i]->time <= templates[j]->time) ||
|
| - ((templates[i]->time == templates[j]->time) &&
|
| - (templates[i]->nbCalls <= templates[j]->nbCalls))) {
|
| - templ1 = templates[j];
|
| - templates[j] = templates[i];
|
| - templates[i] = templ1;
|
| - }
|
| - }
|
| - }
|
| -
|
| -
|
| - /* print flat profile */
|
| -
|
| - fprintf(output, "%6s%20s%20s%10s Calls Tot 100us Avg\n\n",
|
| - "number", "match", "name", "mode");
|
| - total = 0;
|
| - totalt = 0;
|
| - for (i = 0;i < nb;i++) {
|
| - templ1 = templates[i];
|
| - fprintf(output, "%5d ", i);
|
| - if (templ1->match != NULL) {
|
| - if (xmlStrlen(templ1->match) > 20)
|
| - fprintf(output, "%s\n%26s", templ1->match, "");
|
| - else
|
| - fprintf(output, "%20s", templ1->match);
|
| - } else {
|
| - fprintf(output, "%20s", "");
|
| - }
|
| - if (templ1->name != NULL) {
|
| - if (xmlStrlen(templ1->name) > 20)
|
| - fprintf(output, "%s\n%46s", templ1->name, "");
|
| - else
|
| - fprintf(output, "%20s", templ1->name);
|
| - } else {
|
| - fprintf(output, "%20s", "");
|
| - }
|
| - if (templ1->mode != NULL) {
|
| - if (xmlStrlen(templ1->mode) > 10)
|
| - fprintf(output, "%s\n%56s", templ1->mode, "");
|
| - else
|
| - fprintf(output, "%10s", templ1->mode);
|
| - } else {
|
| - fprintf(output, "%10s", "");
|
| - }
|
| - fprintf(output, " %6d", templ1->nbCalls);
|
| - fprintf(output, " %6ld %6ld\n", templ1->time,
|
| - templ1->time / templ1->nbCalls);
|
| - total += templ1->nbCalls;
|
| - totalt += templ1->time;
|
| - }
|
| - fprintf(output, "\n%30s%26s %6d %6ld\n", "Total", "", total, totalt);
|
| -
|
| -
|
| - /* print call graph */
|
| -
|
| - childt = xmlMalloc((nb + 1) * sizeof(int));
|
| - if (childt == NULL)
|
| - return;
|
| -
|
| - /* precalculate children times */
|
| - for (i = 0; i < nb; i++) {
|
| - templ1 = templates[i];
|
| -
|
| - childt[i] = 0;
|
| - for (k = 0; k < nb; k++) {
|
| - templ2 = templates[k];
|
| - for (l = 0; l < templ2->templNr; l++) {
|
| - if (templ2->templCalledTab[l] == templ1) {
|
| - childt[i] +=templ2->time;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - childt[i] = 0;
|
| -
|
| - fprintf(output, "\nindex %% time self children called name\n");
|
| -
|
| - for (i = 0; i < nb; i++) {
|
| - char ix_str[20], timep_str[20], times_str[20], timec_str[20], called_str[20];
|
| - unsigned long t;
|
| -
|
| - templ1 = templates[i];
|
| - /* callers */
|
| - for (j = 0; j < templ1->templNr; j++) {
|
| - templ2 = templ1->templCalledTab[j];
|
| - for (k = 0; k < nb; k++) {
|
| - if (templates[k] == templ2)
|
| - break;
|
| - }
|
| - t=templ2?templ2->time:totalt;
|
| - snprintf(times_str,sizeof(times_str),"%8.3f",(float)t/XSLT_TIMESTAMP_TICS_PER_SEC);
|
| - snprintf(timec_str,sizeof(timec_str),"%8.3f",(float)childt[k]/XSLT_TIMESTAMP_TICS_PER_SEC);
|
| - snprintf(called_str,sizeof(called_str),"%6d/%d",
|
| - templ1->templCountTab[j], /* number of times caller calls 'this' */
|
| - templ1->nbCalls); /* total number of calls to 'this' */
|
| -
|
| - fprintf(output, " %-8s %-8s %-12s %s [%d]\n",
|
| - times_str,timec_str,called_str,
|
| - (templ2?(templ2->name?(char *)templ2->name:pretty_templ_match(templ2)):"-"),k);
|
| - }
|
| - /* this */
|
| - snprintf(ix_str,sizeof(ix_str),"[%d]",i);
|
| - snprintf(timep_str,sizeof(timep_str),"%6.2f",(float)templ1->time*100.0/totalt);
|
| - snprintf(times_str,sizeof(times_str),"%8.3f",(float)templ1->time/XSLT_TIMESTAMP_TICS_PER_SEC);
|
| - snprintf(timec_str,sizeof(timec_str),"%8.3f",(float)childt[i]/XSLT_TIMESTAMP_TICS_PER_SEC);
|
| - fprintf(output, "%-5s %-6s %-8s %-8s %6d %s [%d]\n",
|
| - ix_str, timep_str,times_str,timec_str,
|
| - templ1->nbCalls,
|
| - templ1->name?(char *)templ1->name:pretty_templ_match(templ1),i);
|
| - /* callees
|
| - * - go over templates[0..nb] and their templCalledTab[]
|
| - * - print those where we in the the call-stack
|
| - */
|
| - total = 0;
|
| - for (k = 0; k < nb; k++) {
|
| - templ2 = templates[k];
|
| - for (l = 0; l < templ2->templNr; l++) {
|
| - if (templ2->templCalledTab[l] == templ1) {
|
| - total+=templ2->templCountTab[l];
|
| - }
|
| - }
|
| - }
|
| - for (k = 0; k < nb; k++) {
|
| - templ2 = templates[k];
|
| - for (l = 0; l < templ2->templNr; l++) {
|
| - if (templ2->templCalledTab[l] == templ1) {
|
| - snprintf(times_str,sizeof(times_str),"%8.3f",(float)templ2->time/XSLT_TIMESTAMP_TICS_PER_SEC);
|
| - snprintf(timec_str,sizeof(timec_str),"%8.3f",(float)childt[k]/XSLT_TIMESTAMP_TICS_PER_SEC);
|
| - snprintf(called_str,sizeof(called_str),"%6d/%d",
|
| - templ2->templCountTab[l], /* number of times 'this' calls callee */
|
| - total); /* total number of calls from 'this' */
|
| - fprintf(output, " %-8s %-8s %-12s %s [%d]\n",
|
| - times_str,timec_str,called_str,
|
| - templ2->name?(char *)templ2->name:pretty_templ_match(templ2),k);
|
| - }
|
| - }
|
| - }
|
| - fprintf(output, "-----------------------------------------------\n");
|
| - }
|
| -
|
| - fprintf(output, "\f\nIndex by function name\n");
|
| - for (i = 0; i < nb; i++) {
|
| - templ1 = templates[i];
|
| - fprintf(output, "[%d] %s (%s:%d)\n",
|
| - i, templ1->name?(char *)templ1->name:pretty_templ_match(templ1),
|
| - templ1->style->doc->URL,templ1->elem->line);
|
| - }
|
| -
|
| - fprintf(output, "\f\n");
|
| - xmlFree(childt);
|
| -
|
| - xmlFree(templates);
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Fetching profiling informations *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/**
|
| - * xsltGetProfileInformation:
|
| - * @ctxt: a transformation context
|
| - *
|
| - * This function should be called after the transformation completed
|
| - * to extract template processing profiling informations if availble.
|
| - * The informations are returned as an XML document tree like
|
| - * <?xml version="1.0"?>
|
| - * <profile>
|
| - * <template rank="1" match="*" name=""
|
| - * mode="" calls="6" time="48" average="8"/>
|
| - * <template rank="2" match="item2|item3" name=""
|
| - * mode="" calls="10" time="30" average="3"/>
|
| - * <template rank="3" match="item1" name=""
|
| - * mode="" calls="5" time="17" average="3"/>
|
| - * </profile>
|
| - * The caller will need to free up the returned tree with xmlFreeDoc()
|
| - *
|
| - * Returns the xmlDocPtr corresponding to the result or NULL if not available.
|
| - */
|
| -
|
| -xmlDocPtr
|
| -xsltGetProfileInformation(xsltTransformContextPtr ctxt)
|
| -{
|
| - xmlDocPtr ret = NULL;
|
| - xmlNodePtr root, child;
|
| - char buf[100];
|
| -
|
| - xsltStylesheetPtr style;
|
| - xsltTemplatePtr *templates;
|
| - xsltTemplatePtr templ;
|
| - int nb = 0, max = 0, i, j;
|
| -
|
| - if (!ctxt)
|
| - return NULL;
|
| -
|
| - if (!ctxt->profile)
|
| - return NULL;
|
| -
|
| - nb = 0;
|
| - max = 10000;
|
| - templates =
|
| - (xsltTemplatePtr *) xmlMalloc(max * sizeof(xsltTemplatePtr));
|
| - if (templates == NULL)
|
| - return NULL;
|
| -
|
| - /*
|
| - * collect all the templates in an array
|
| - */
|
| - style = ctxt->style;
|
| - while (style != NULL) {
|
| - templ = style->templates;
|
| - while (templ != NULL) {
|
| - if (nb >= max)
|
| - break;
|
| -
|
| - if (templ->nbCalls > 0)
|
| - templates[nb++] = templ;
|
| - templ = templ->next;
|
| - }
|
| -
|
| - style = (xsltStylesheetPtr) xsltNextImport(style);
|
| - }
|
| -
|
| - /*
|
| - * Sort the array by time spent
|
| - */
|
| - for (i = 0; i < nb - 1; i++) {
|
| - for (j = i + 1; j < nb; j++) {
|
| - if ((templates[i]->time <= templates[j]->time) ||
|
| - ((templates[i]->time == templates[j]->time) &&
|
| - (templates[i]->nbCalls <= templates[j]->nbCalls))) {
|
| - templ = templates[j];
|
| - templates[j] = templates[i];
|
| - templates[i] = templ;
|
| - }
|
| - }
|
| - }
|
| -
|
| - /*
|
| - * Generate a document corresponding to the results.
|
| - */
|
| - ret = xmlNewDoc(BAD_CAST "1.0");
|
| - root = xmlNewDocNode(ret, NULL, BAD_CAST "profile", NULL);
|
| - xmlDocSetRootElement(ret, root);
|
| -
|
| - for (i = 0; i < nb; i++) {
|
| - child = xmlNewChild(root, NULL, BAD_CAST "template", NULL);
|
| - snprintf(buf, sizeof(buf), "%d", i + 1);
|
| - xmlSetProp(child, BAD_CAST "rank", BAD_CAST buf);
|
| - xmlSetProp(child, BAD_CAST "match", BAD_CAST templates[i]->match);
|
| - xmlSetProp(child, BAD_CAST "name", BAD_CAST templates[i]->name);
|
| - xmlSetProp(child, BAD_CAST "mode", BAD_CAST templates[i]->mode);
|
| -
|
| - snprintf(buf, sizeof(buf), "%d", templates[i]->nbCalls);
|
| - xmlSetProp(child, BAD_CAST "calls", BAD_CAST buf);
|
| -
|
| - snprintf(buf, sizeof(buf), "%ld", templates[i]->time);
|
| - xmlSetProp(child, BAD_CAST "time", BAD_CAST buf);
|
| -
|
| - snprintf(buf, sizeof(buf), "%ld", templates[i]->time / templates[i]->nbCalls);
|
| - xmlSetProp(child, BAD_CAST "average", BAD_CAST buf);
|
| - };
|
| -
|
| - xmlFree(templates);
|
| -
|
| - return ret;
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Hooks for libxml2 XPath *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/**
|
| - * xsltXPathCompileFlags:
|
| - * @style: the stylesheet
|
| - * @str: the XPath expression
|
| - * @flags: extra compilation flags to pass down to libxml2 XPath
|
| - *
|
| - * Compile an XPath expression
|
| - *
|
| - * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
|
| - * the caller has to free the object.
|
| - */
|
| -xmlXPathCompExprPtr
|
| -xsltXPathCompileFlags(xsltStylesheetPtr style, const xmlChar *str, int flags) {
|
| - xmlXPathContextPtr xpathCtxt;
|
| - xmlXPathCompExprPtr ret;
|
| -
|
| - if (style != NULL) {
|
| -#ifdef XSLT_REFACTORED_XPATHCOMP
|
| - if (XSLT_CCTXT(style)) {
|
| - /*
|
| - * Proposed by Jerome Pesenti
|
| - * --------------------------
|
| - * For better efficiency we'll reuse the compilation
|
| - * context's XPath context. For the common stylesheet using
|
| - * XPath expressions this will reduce compilation time to
|
| - * about 50%.
|
| - *
|
| - * See http://mail.gnome.org/archives/xslt/2006-April/msg00037.html
|
| - */
|
| - xpathCtxt = XSLT_CCTXT(style)->xpathCtxt;
|
| - xpathCtxt->doc = style->doc;
|
| - } else
|
| - xpathCtxt = xmlXPathNewContext(style->doc);
|
| -#else
|
| - xpathCtxt = xmlXPathNewContext(style->doc);
|
| -#endif
|
| - if (xpathCtxt == NULL)
|
| - return NULL;
|
| - xpathCtxt->dict = style->dict;
|
| - } else {
|
| - xpathCtxt = xmlXPathNewContext(NULL);
|
| - if (xpathCtxt == NULL)
|
| - return NULL;
|
| - }
|
| - xpathCtxt->flags = flags;
|
| -
|
| - /*
|
| - * Compile the expression.
|
| - */
|
| - ret = xmlXPathCtxtCompile(xpathCtxt, str);
|
| -
|
| -#ifdef XSLT_REFACTORED_XPATHCOMP
|
| - if ((style == NULL) || (! XSLT_CCTXT(style))) {
|
| - xmlXPathFreeContext(xpathCtxt);
|
| - }
|
| -#else
|
| - xmlXPathFreeContext(xpathCtxt);
|
| -#endif
|
| - /*
|
| - * TODO: there is a lot of optimizations which should be possible
|
| - * like variable slot precomputations, function precomputations, etc.
|
| - */
|
| -
|
| - return(ret);
|
| -}
|
| -
|
| -/**
|
| - * xsltXPathCompile:
|
| - * @style: the stylesheet
|
| - * @str: the XPath expression
|
| - *
|
| - * Compile an XPath expression
|
| - *
|
| - * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
|
| - * the caller has to free the object.
|
| - */
|
| -xmlXPathCompExprPtr
|
| -xsltXPathCompile(xsltStylesheetPtr style, const xmlChar *str) {
|
| - return(xsltXPathCompileFlags(style, str, 0));
|
| -}
|
| -
|
| -/************************************************************************
|
| - * *
|
| - * Hooks for the debugger *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -/*
|
| - * There is currently only 3 debugging callback defined
|
| - * Debugger callbacks are disabled by default
|
| - */
|
| -#define XSLT_CALLBACK_NUMBER 3
|
| -
|
| -typedef struct _xsltDebuggerCallbacks xsltDebuggerCallbacks;
|
| -typedef xsltDebuggerCallbacks *xsltDebuggerCallbacksPtr;
|
| -struct _xsltDebuggerCallbacks {
|
| - xsltHandleDebuggerCallback handler;
|
| - xsltAddCallCallback add;
|
| - xsltDropCallCallback drop;
|
| -};
|
| -
|
| -static xsltDebuggerCallbacks xsltDebuggerCurrentCallbacks = {
|
| - NULL, /* handler */
|
| - NULL, /* add */
|
| - NULL /* drop */
|
| -};
|
| -
|
| -int xslDebugStatus;
|
| -
|
| -/**
|
| - * xsltSetDebuggerStatus:
|
| - * @value : the value to be set
|
| - *
|
| - * This function sets the value of xslDebugStatus.
|
| - */
|
| -void
|
| -xsltSetDebuggerStatus(int value)
|
| -{
|
| - xslDebugStatus = value;
|
| -}
|
| -
|
| -/**
|
| - * xsltGetDebuggerStatus:
|
| - *
|
| - * Get xslDebugStatus.
|
| - *
|
| - * Returns the value of xslDebugStatus.
|
| - */
|
| -int
|
| -xsltGetDebuggerStatus(void)
|
| -{
|
| - return(xslDebugStatus);
|
| -}
|
| -
|
| -/**
|
| - * xsltSetDebuggerCallbacks:
|
| - * @no : number of callbacks
|
| - * @block : the block of callbacks
|
| - *
|
| - * This function allow to plug a debugger into the XSLT library
|
| - * @block points to a block of memory containing the address of @no
|
| - * callback routines.
|
| - *
|
| - * Returns 0 in case of success and -1 in case of error
|
| - */
|
| -int
|
| -xsltSetDebuggerCallbacks(int no, void *block)
|
| -{
|
| - xsltDebuggerCallbacksPtr callbacks;
|
| -
|
| - if ((block == NULL) || (no != XSLT_CALLBACK_NUMBER))
|
| - return(-1);
|
| -
|
| - callbacks = (xsltDebuggerCallbacksPtr) block;
|
| - xsltDebuggerCurrentCallbacks.handler = callbacks->handler;
|
| - xsltDebuggerCurrentCallbacks.add = callbacks->add;
|
| - xsltDebuggerCurrentCallbacks.drop = callbacks->drop;
|
| - return(0);
|
| -}
|
| -
|
| -/**
|
| - * xslHandleDebugger:
|
| - * @cur : source node being executed
|
| - * @node : data node being processed
|
| - * @templ : temlate that applies to node
|
| - * @ctxt : the xslt transform context
|
| - *
|
| - * If either cur or node are a breakpoint, or xslDebugStatus in state
|
| - * where debugging must occcur at this time then transfer control
|
| - * to the xslDebugBreak function
|
| - */
|
| -void
|
| -xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ,
|
| - xsltTransformContextPtr ctxt)
|
| -{
|
| - if (xsltDebuggerCurrentCallbacks.handler != NULL)
|
| - xsltDebuggerCurrentCallbacks.handler(cur, node, templ, ctxt);
|
| -}
|
| -
|
| -/**
|
| - * xslAddCall:
|
| - * @templ : current template being applied
|
| - * @source : the source node being processed
|
| - *
|
| - * Add template "call" to call stack
|
| - * Returns : 1 on sucess 0 otherwise an error may be printed if
|
| - * WITH_XSLT_DEBUG_BREAKPOINTS is defined
|
| - */
|
| -int
|
| -xslAddCall(xsltTemplatePtr templ, xmlNodePtr source)
|
| -{
|
| - if (xsltDebuggerCurrentCallbacks.add != NULL)
|
| - return(xsltDebuggerCurrentCallbacks.add(templ, source));
|
| - return(0);
|
| -}
|
| -
|
| -/**
|
| - * xslDropCall:
|
| - *
|
| - * Drop the topmost item off the call stack
|
| - */
|
| -void
|
| -xslDropCall(void)
|
| -{
|
| - if (xsltDebuggerCurrentCallbacks.drop != NULL)
|
| - xsltDebuggerCurrentCallbacks.drop();
|
| -}
|
| -
|
|
|