mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
309 lines
9.2 KiB
C
309 lines
9.2 KiB
C
/*
|
|
* extra.c: Implementation of non-standard features
|
|
*
|
|
* Reference:
|
|
* Michael Kay "XSLT Programmer's Reference" pp 637-643
|
|
* The node-set() extension function
|
|
*
|
|
* See Copyright for the status of this software.
|
|
*
|
|
* daniel@veillard.com
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#ifdef WITH_XSLT_DEBUG
|
|
#define WITH_XSLT_DEBUG_EXTRA
|
|
#endif
|
|
|
|
/************************************************************************
|
|
* *
|
|
* Handling of XSLT debugging *
|
|
* *
|
|
************************************************************************/
|
|
|
|
/**
|
|
* xsltDebug:
|
|
* @ctxt: an XSLT processing context
|
|
* @node: The current node
|
|
* @inst: the instruction in the stylesheet
|
|
* @comp: precomputed informations
|
|
*
|
|
* Process an debug node
|
|
*/
|
|
void
|
|
xsltDebug(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,
|
|
xmlNodePtr inst ATTRIBUTE_UNUSED,
|
|
xsltStylePreCompPtr comp ATTRIBUTE_UNUSED)
|
|
{
|
|
int i, j;
|
|
|
|
xsltGenericError(xsltGenericErrorContext, "Templates:\n");
|
|
for (i = 0, j = ctxt->templNr - 1; ((i < 15) && (j >= 0)); i++, j--) {
|
|
xsltGenericError(xsltGenericErrorContext, "#%d ", i);
|
|
if (ctxt->templTab[j]->name != NULL)
|
|
xsltGenericError(xsltGenericErrorContext, "name %s ",
|
|
ctxt->templTab[j]->name);
|
|
if (ctxt->templTab[j]->match != NULL)
|
|
xsltGenericError(xsltGenericErrorContext, "name %s ",
|
|
ctxt->templTab[j]->match);
|
|
if (ctxt->templTab[j]->mode != NULL)
|
|
xsltGenericError(xsltGenericErrorContext, "name %s ",
|
|
ctxt->templTab[j]->mode);
|
|
xsltGenericError(xsltGenericErrorContext, "\n");
|
|
}
|
|
xsltGenericError(xsltGenericErrorContext, "Variables:\n");
|
|
for (i = 0, j = ctxt->varsNr - 1; ((i < 15) && (j >= 0)); i++, j--) {
|
|
xsltStackElemPtr cur;
|
|
|
|
if (ctxt->varsTab[j] == NULL)
|
|
continue;
|
|
xsltGenericError(xsltGenericErrorContext, "#%d\n", i);
|
|
cur = ctxt->varsTab[j];
|
|
while (cur != NULL) {
|
|
if (cur->comp == NULL) {
|
|
xsltGenericError(xsltGenericErrorContext,
|
|
"corrupted !!!\n");
|
|
} else if (cur->comp->type == XSLT_FUNC_PARAM) {
|
|
xsltGenericError(xsltGenericErrorContext, "param ");
|
|
} else if (cur->comp->type == XSLT_FUNC_VARIABLE) {
|
|
xsltGenericError(xsltGenericErrorContext, "var ");
|
|
}
|
|
if (cur->name != NULL)
|
|
xsltGenericError(xsltGenericErrorContext, "%s ",
|
|
cur->name);
|
|
else
|
|
xsltGenericError(xsltGenericErrorContext, "noname !!!!");
|
|
#ifdef LIBXML_DEBUG_ENABLED
|
|
if (cur->value != NULL) {
|
|
xmlXPathDebugDumpObject(stdout, cur->value, 1);
|
|
} else {
|
|
xsltGenericError(xsltGenericErrorContext, "NULL !!!!");
|
|
}
|
|
#endif
|
|
xsltGenericError(xsltGenericErrorContext, "\n");
|
|
cur = cur->next;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/************************************************************************
|
|
* *
|
|
* Classic extensions as described by M. Kay *
|
|
* *
|
|
************************************************************************/
|
|
|
|
/**
|
|
* xsltFunctionNodeSet:
|
|
* @ctxt: the XPath Parser context
|
|
* @nargs: the number of arguments
|
|
*
|
|
* Implement the node-set() XSLT function
|
|
* node-set node-set(result-tree)
|
|
*
|
|
* This function is available in libxslt, saxon or xt namespace.
|
|
*/
|
|
void
|
|
xsltFunctionNodeSet(xmlXPathParserContextPtr ctxt, int nargs){
|
|
if (nargs != 1) {
|
|
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
|
"node-set() : expects one result-tree arg\n");
|
|
ctxt->error = XPATH_INVALID_ARITY;
|
|
return;
|
|
}
|
|
if ((ctxt->value == NULL) ||
|
|
((ctxt->value->type != XPATH_XSLT_TREE) &&
|
|
(ctxt->value->type != XPATH_NODESET))) {
|
|
xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
|
|
"node-set() invalid arg expecting a result tree\n");
|
|
ctxt->error = XPATH_INVALID_TYPE;
|
|
return;
|
|
}
|
|
if (ctxt->value->type == XPATH_XSLT_TREE) {
|
|
ctxt->value->type = XPATH_NODESET;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* 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
|
|
*
|
|
* Registers the built-in extensions. This function is deprecated, use
|
|
* xsltRegisterAllExtras instead.
|
|
*/
|
|
void
|
|
xsltRegisterExtras(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED) {
|
|
xsltRegisterAllExtras();
|
|
}
|
|
|
|
/**
|
|
* xsltRegisterAllExtras:
|
|
*
|
|
* Registers the built-in extensions
|
|
*/
|
|
void
|
|
xsltRegisterAllExtras (void) {
|
|
xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
|
|
XSLT_LIBXSLT_NAMESPACE,
|
|
xsltFunctionNodeSet);
|
|
xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
|
|
XSLT_SAXON_NAMESPACE,
|
|
xsltFunctionNodeSet);
|
|
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,
|
|
(xsltTransformFunction) xsltDebug);
|
|
xsltRegisterExtModuleElement((const xmlChar *) "output",
|
|
XSLT_SAXON_NAMESPACE,
|
|
xsltDocumentComp,
|
|
(xsltTransformFunction) xsltDocumentElem);
|
|
xsltRegisterExtModuleElement((const xmlChar *) "write",
|
|
XSLT_XALAN_NAMESPACE,
|
|
xsltDocumentComp,
|
|
(xsltTransformFunction) xsltDocumentElem);
|
|
xsltRegisterExtModuleElement((const xmlChar *) "document",
|
|
XSLT_XT_NAMESPACE,
|
|
xsltDocumentComp,
|
|
(xsltTransformFunction) xsltDocumentElem);
|
|
xsltRegisterExtModuleElement((const xmlChar *) "document",
|
|
XSLT_NAMESPACE,
|
|
xsltDocumentComp,
|
|
(xsltTransformFunction) xsltDocumentElem);
|
|
}
|