- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / libxslt / libxslt / extra.c
1 /*
2  * extra.c: Implementation of non-standard features
3  *
4  * Reference:
5  *   Michael Kay "XSLT Programmer's Reference" pp 637-643
6  *   The node-set() extension function
7  *
8  * See Copyright for the status of this software.
9  *
10  * daniel@veillard.com
11  */
12
13 #define IN_LIBXSLT
14 #include "libxslt.h"
15
16 #include <string.h>
17 #ifdef HAVE_TIME_H
18 #include <time.h>
19 #endif
20 #ifdef HAVE_STDLIB_H
21 #include <stdlib.h>
22 #endif
23
24 #include <libxml/xmlmemory.h>
25 #include <libxml/tree.h>
26 #include <libxml/hash.h>
27 #include <libxml/xmlerror.h>
28 #include <libxml/parserInternals.h>
29 #include "xslt.h"
30 #include "xsltInternals.h"
31 #include "xsltutils.h"
32 #include "extensions.h"
33 #include "variables.h"
34 #include "transform.h"
35 #include "extra.h"
36 #include "preproc.h"
37
38 #ifdef WITH_XSLT_DEBUG
39 #define WITH_XSLT_DEBUG_EXTRA
40 #endif
41
42 /************************************************************************
43  *                                                                      *
44  *              Handling of XSLT debugging                              *
45  *                                                                      *
46  ************************************************************************/
47
48 /**
49  * xsltDebug:
50  * @ctxt:  an XSLT processing context
51  * @node:  The current node
52  * @inst:  the instruction in the stylesheet
53  * @comp:  precomputed informations
54  *
55  * Process an debug node
56  */
57 void
58 xsltDebug(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,
59           xmlNodePtr inst ATTRIBUTE_UNUSED,
60           xsltStylePreCompPtr comp ATTRIBUTE_UNUSED)
61 {
62     int i, j;
63
64     xsltGenericError(xsltGenericErrorContext, "Templates:\n");
65     for (i = 0, j = ctxt->templNr - 1; ((i < 15) && (j >= 0)); i++, j--) {
66         xsltGenericError(xsltGenericErrorContext, "#%d ", i);
67         if (ctxt->templTab[j]->name != NULL)
68             xsltGenericError(xsltGenericErrorContext, "name %s ",
69                              ctxt->templTab[j]->name);
70         if (ctxt->templTab[j]->match != NULL)
71             xsltGenericError(xsltGenericErrorContext, "name %s ",
72                              ctxt->templTab[j]->match);
73         if (ctxt->templTab[j]->mode != NULL)
74             xsltGenericError(xsltGenericErrorContext, "name %s ",
75                              ctxt->templTab[j]->mode);
76         xsltGenericError(xsltGenericErrorContext, "\n");
77     }
78     xsltGenericError(xsltGenericErrorContext, "Variables:\n");
79     for (i = 0, j = ctxt->varsNr - 1; ((i < 15) && (j >= 0)); i++, j--) {
80         xsltStackElemPtr cur;
81
82         if (ctxt->varsTab[j] == NULL)
83             continue;
84         xsltGenericError(xsltGenericErrorContext, "#%d\n", i);
85         cur = ctxt->varsTab[j];
86         while (cur != NULL) {
87             if (cur->comp == NULL) {
88                 xsltGenericError(xsltGenericErrorContext,
89                                  "corrupted !!!\n");
90             } else if (cur->comp->type == XSLT_FUNC_PARAM) {
91                 xsltGenericError(xsltGenericErrorContext, "param ");
92             } else if (cur->comp->type == XSLT_FUNC_VARIABLE) {
93                 xsltGenericError(xsltGenericErrorContext, "var ");
94             }
95             if (cur->name != NULL)
96                 xsltGenericError(xsltGenericErrorContext, "%s ",
97                                  cur->name);
98             else
99                 xsltGenericError(xsltGenericErrorContext, "noname !!!!");
100 #ifdef LIBXML_DEBUG_ENABLED
101             if (cur->value != NULL) {
102                 xmlXPathDebugDumpObject(stdout, cur->value, 1);
103             } else {
104                 xsltGenericError(xsltGenericErrorContext, "NULL !!!!");
105             }
106 #endif
107             xsltGenericError(xsltGenericErrorContext, "\n");
108             cur = cur->next;
109         }
110
111     }
112 }
113
114 /************************************************************************
115  *                                                                      *
116  *              Classic extensions as described by M. Kay               *
117  *                                                                      *
118  ************************************************************************/
119
120 /**
121  * xsltFunctionNodeSet:
122  * @ctxt:  the XPath Parser context
123  * @nargs:  the number of arguments
124  *
125  * Implement the node-set() XSLT function
126  *   node-set node-set(result-tree)
127  *
128  * This function is available in libxslt, saxon or xt namespace.
129  */
130 void
131 xsltFunctionNodeSet(xmlXPathParserContextPtr ctxt, int nargs){
132     if (nargs != 1) {
133         xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
134                 "node-set() : expects one result-tree arg\n");
135         ctxt->error = XPATH_INVALID_ARITY;
136         return;
137     }
138     if ((ctxt->value == NULL) ||
139         ((ctxt->value->type != XPATH_XSLT_TREE) &&
140          (ctxt->value->type != XPATH_NODESET))) {
141         xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
142             "node-set() invalid arg expecting a result tree\n");
143         ctxt->error = XPATH_INVALID_TYPE;
144         return;
145     }
146     if (ctxt->value->type == XPATH_XSLT_TREE) {
147         ctxt->value->type = XPATH_NODESET;
148     }
149 }
150
151
152 /*
153  * Okay the following really seems unportable and since it's not
154  * part of any standard I'm not too ashamed to do this
155  */
156 #if defined(linux) || defined(__sun)
157 #if defined(HAVE_MKTIME) && defined(HAVE_LOCALTIME) && defined(HAVE_ASCTIME)
158 #define WITH_LOCALTIME
159
160 /**
161  * xsltFunctionLocalTime:
162  * @ctxt:  the XPath Parser context
163  * @nargs:  the number of arguments
164  *
165  * Implement the localTime XSLT function used by NORM
166  *   string localTime(???)
167  *
168  * This function is available in Norm's extension namespace
169  * Code (and comments) contributed by Norm
170  */
171 static void
172 xsltFunctionLocalTime(xmlXPathParserContextPtr ctxt, int nargs) {
173     xmlXPathObjectPtr obj;
174     char *str;
175     char digits[5];
176     char result[29];
177     long int field;
178     time_t gmt, lmt;
179     struct tm gmt_tm;
180     struct tm *local_tm;
181  
182     if (nargs != 1) {
183        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
184                       "localTime() : invalid number of args %d\n", nargs);
185        ctxt->error = XPATH_INVALID_ARITY;
186        return;
187     }
188  
189     obj = valuePop(ctxt);
190
191     if (obj->type != XPATH_STRING) {
192         obj = xmlXPathConvertString(obj);
193     }
194     if (obj == NULL) {
195         valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
196         return;
197     }
198     
199     str = (char *) obj->stringval;
200
201     /* str = "$Date$" */
202     memset(digits, 0, sizeof(digits));
203     strncpy(digits, str+7, 4);
204     field = strtol(digits, NULL, 10);
205     gmt_tm.tm_year = field - 1900;
206
207     memset(digits, 0, sizeof(digits));
208     strncpy(digits, str+12, 2);
209     field = strtol(digits, NULL, 10);
210     gmt_tm.tm_mon = field - 1;
211
212     memset(digits, 0, sizeof(digits));
213     strncpy(digits, str+15, 2);
214     field = strtol(digits, NULL, 10);
215     gmt_tm.tm_mday = field;
216
217     memset(digits, 0, sizeof(digits));
218     strncpy(digits, str+18, 2);
219     field = strtol(digits, NULL, 10);
220     gmt_tm.tm_hour = field;
221
222     memset(digits, 0, sizeof(digits));
223     strncpy(digits, str+21, 2);
224     field = strtol(digits, NULL, 10);
225     gmt_tm.tm_min = field;
226
227     memset(digits, 0, sizeof(digits));
228     strncpy(digits, str+24, 2);
229     field = strtol(digits, NULL, 10);
230     gmt_tm.tm_sec = field;
231
232     /* Now turn gmt_tm into a time. */
233     gmt = mktime(&gmt_tm);
234
235
236     /*
237      * FIXME: it's been too long since I did manual memory management.
238      * (I swore never to do it again.) Does this introduce a memory leak?
239      */
240     local_tm = localtime(&gmt);
241
242     /*
243      * Calling localtime() has the side-effect of setting timezone.
244      * After we know the timezone, we can adjust for it
245      */
246     lmt = gmt - timezone;
247
248     /*
249      * FIXME: it's been too long since I did manual memory management.
250      * (I swore never to do it again.) Does this introduce a memory leak?
251      */
252     local_tm = localtime(&lmt);
253
254     /*
255      * Now convert local_tm back into a string. This doesn't introduce
256      * a memory leak, so says asctime(3).
257      */
258
259     str = asctime(local_tm);           /* "Tue Jun 26 05:02:16 2001" */
260                                        /*  0123456789 123456789 123 */
261
262     memset(result, 0, sizeof(result)); /* "Thu, 26 Jun 2001" */
263                                        /*  0123456789 12345 */
264
265     strncpy(result, str, 20);
266     strcpy(result+20, "???");          /* tzname doesn't work, fake it */
267     strncpy(result+23, str+19, 5);
268
269     /* Ok, now result contains the string I want to send back. */
270     valuePush(ctxt, xmlXPathNewString((xmlChar *)result));
271 }
272 #endif
273 #endif /* linux or sun */
274
275
276 /**
277  * xsltRegisterExtras:
278  * @ctxt:  a XSLT process context
279  *
280  * Registers the built-in extensions. This function is deprecated, use
281  * xsltRegisterAllExtras instead.
282  */
283 void
284 xsltRegisterExtras(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED) {
285     xsltRegisterAllExtras();
286 }
287
288 /**
289  * xsltRegisterAllExtras:
290  *
291  * Registers the built-in extensions
292  */
293 void
294 xsltRegisterAllExtras (void) {
295     xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
296                                   XSLT_LIBXSLT_NAMESPACE,
297                                   xsltFunctionNodeSet);
298     xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
299                                   XSLT_SAXON_NAMESPACE,
300                                   xsltFunctionNodeSet);
301     xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
302                                   XSLT_XT_NAMESPACE,
303                                   xsltFunctionNodeSet);
304 #ifdef WITH_LOCALTIME
305     xsltRegisterExtModuleFunction((const xmlChar *) "localTime",
306                                   XSLT_NORM_SAXON_NAMESPACE,
307                                   xsltFunctionLocalTime);
308 #endif
309     xsltRegisterExtModuleElement((const xmlChar *) "debug",
310                                  XSLT_LIBXSLT_NAMESPACE,
311                                  NULL,
312                                  (xsltTransformFunction) xsltDebug);
313     xsltRegisterExtModuleElement((const xmlChar *) "output",
314                                  XSLT_SAXON_NAMESPACE,
315                                  xsltDocumentComp,
316                                  (xsltTransformFunction) xsltDocumentElem);
317     xsltRegisterExtModuleElement((const xmlChar *) "write",
318                                  XSLT_XALAN_NAMESPACE,
319                                  xsltDocumentComp,
320                                  (xsltTransformFunction) xsltDocumentElem);
321     xsltRegisterExtModuleElement((const xmlChar *) "document",
322                                  XSLT_XT_NAMESPACE,
323                                  xsltDocumentComp,
324                                  (xsltTransformFunction) xsltDocumentElem);
325     xsltRegisterExtModuleElement((const xmlChar *) "document",
326                                  XSLT_NAMESPACE,
327                                  xsltDocumentComp,
328                                  (xsltTransformFunction) xsltDocumentElem);
329 }