updating Makefiles to fix the prelinking. Daniel
[platform/upstream/libxslt.git] / xsltproc / xsltproc.c
1 /*
2  * xsltproc.c: user program for the XSL Transformation 1.0 engine
3  *
4  * See Copyright for the status of this software.
5  *
6  * daniel@veillard.com
7  */
8
9 #include "libxslt/libxslt.h"
10 #include "libexslt/exslt.h"
11 #ifdef HAVE_STRING_H
12 #include <string.h>
13 #endif
14 #ifdef HAVE_SYS_TIME_H
15 #include <sys/time.h>
16 #endif
17 #ifdef HAVE_SYS_STAT_H
18 #include <sys/stat.h>
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26 #ifdef HAVE_STDARG_H
27 #include <stdarg.h>
28 #endif
29 #include <libxml/xmlmemory.h>
30 #include <libxml/debugXML.h>
31 #include <libxml/HTMLtree.h>
32 #include <libxml/xmlIO.h>
33 #ifdef LIBXML_DOCB_ENABLED
34 #include <libxml/DOCBparser.h>
35 #endif
36 #ifdef LIBXML_XINCLUDE_ENABLED
37 #include <libxml/xinclude.h>
38 #endif
39 #ifdef LIBXML_CATALOG_ENABLED
40 #include <libxml/catalog.h>
41 #endif
42 #include <libxml/parserInternals.h>
43
44 #include <libxslt/xslt.h>
45 #include <libxslt/xsltInternals.h>
46 #include <libxslt/transform.h>
47 #include <libxslt/xsltutils.h>
48 #include <libxslt/extensions.h>
49
50 #include <libexslt/exsltconfig.h>
51
52 #ifdef WIN32
53 #ifdef _MSC_VER
54 #include <winsock2.h>
55 #pragma comment(lib, "ws2_32.lib")
56 #define gettimeofday(p1,p2)
57 #define HAVE_TIME_H
58 #include <time.h>
59 #define HAVE_STDARG_H
60 #include <stdarg.h>
61 #endif /* _MS_VER */
62 #else /* WIN32 */
63 #if defined(HAVE_SYS_TIME_H)
64 #include <sys/time.h>
65 #elif defined(HAVE_TIME_H)
66 #include <time.h>
67 #endif
68 #endif /* WIN32 */
69
70 #ifndef HAVE_STAT
71 #  ifdef HAVE__STAT
72      /* MS C library seems to define stat and _stat. The definition
73       *         is identical. Still, mapping them to each other causes a warning. */
74 #    ifndef _MSC_VER
75 #      define stat(x,y) _stat(x,y)
76 #    endif
77 #    define HAVE_STAT
78 #  endif
79 #endif
80
81 xmlParserInputPtr xmlNoNetExternalEntityLoader(const char *URL,
82                                                const char *ID,
83                                                xmlParserCtxtPtr ctxt);
84
85 static int debug = 0;
86 static int repeat = 0;
87 static int timing = 0;
88 static int novalid = 0;
89 static int noout = 0;
90 #ifdef LIBXML_DOCB_ENABLED
91 static int docbook = 0;
92 #endif
93 #ifdef LIBXML_HTML_ENABLED
94 static int html = 0;
95 #endif
96 #ifdef LIBXML_XINCLUDE_ENABLED
97 static int xinclude = 0;
98 #endif
99 static int profile = 0;
100
101 static const char *params[16 + 1];
102 static int nbparams = 0;
103 static const char *output = NULL;
104
105 /*
106  * Internal timing routines to remove the necessity to have unix-specific
107  * function calls
108  */
109
110 #if defined(HAVE_GETTIMEOFDAY)
111 static struct timeval begin, end;
112 /*
113  * startTimer: call where you want to start timing
114  */
115 static void startTimer(void)
116 {
117     gettimeofday(&begin,NULL);
118 }
119 /*
120  * endTimer: call where you want to stop timing and to print out a
121  *           message about the timing performed; format is a printf
122  *           type argument
123  */
124 static void endTimer(const char *format, ...)
125 {
126     long msec;
127     va_list ap;
128
129     gettimeofday(&end, NULL);
130     msec = end.tv_sec - begin.tv_sec;
131     msec *= 1000;
132     msec += (end.tv_usec - begin.tv_usec) / 1000;
133
134 #ifndef HAVE_STDARG_H
135 #error "endTimer required stdarg functions"
136 #endif
137     va_start(ap, format);
138     vfprintf(stderr,format,ap);
139     va_end(ap);
140
141     fprintf(stderr, " took %ld ms\n", msec);
142 }
143 #elif defined(HAVE_TIME_H)
144 /*
145  * No gettimeofday function, so we have to make do with calling clock.
146  * This is obviously less accurate, but there's little we can do about
147  * that.
148  */
149
150 clock_t begin, end;
151 static void startTimer(void)
152 {
153     begin=clock();
154 }
155 static void endTimer(char *format, ...)
156 {
157     long msec;
158     va_list ap;
159
160     end=clock();
161     msec = ((end-begin) * 1000) / CLOCKS_PER_SEC;
162
163 #ifndef HAVE_STDARG_H
164 #error "endTimer required stdarg functions"
165 #endif
166     va_start(ap, format);
167     vfprintf(stderr,format,ap);
168     va_end(ap);
169     fprintf(stderr, " took %ld ms\n", msec);
170 }
171 #else
172 /*
173  * We don't have a gettimeofday or time.h, so we just don't do timing
174  */
175 static void startTimer(void)
176 {
177   /*
178    * Do nothing
179    */
180 }
181 static void endTimer(char *format, ...)
182 {
183   /*
184    * We cannot do anything because we don't have a timing function
185    */
186 #ifdef HAVE_STDARG_H
187     va_start(ap, format);
188     vfprintf(stderr,format,ap);
189     va_end(ap);
190     fprintf(stderr, " was not timed\n", msec);
191 #else
192   /* We don't have gettimeofday, time or stdarg.h, what crazy world is
193    * this ?!
194    */
195 #endif
196 }
197 #endif
198
199 static void
200 xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur, const char *filename) {
201     xmlDocPtr res;
202
203 #ifdef LIBXML_XINCLUDE_ENABLED
204     if (xinclude) {
205         if (timing)
206             startTimer();
207         xmlXIncludeProcess(doc);
208         if (timing) {
209             endTimer("XInclude processing %s", filename);
210         }
211     }
212 #endif
213     if (timing)
214         startTimer();
215     if (output == NULL) {
216         if (repeat) {
217             int j;
218
219             for (j = 1; j < repeat; j++) {
220                 res = xsltApplyStylesheet(cur, doc, params);
221                 xmlFreeDoc(res);
222                 xmlFreeDoc(doc);
223 #ifdef LIBXML_HTML_ENABLED
224                 if (html)
225                     doc = htmlParseFile(filename, NULL);
226                 else
227 #endif
228 #ifdef LIBXML_DOCB_ENABLED
229                 if (docbook)
230                     doc = docbParseFile(filename, NULL);
231                 else
232 #endif
233                     doc = xmlParseFile(filename);
234             }
235         }
236         if (profile) {
237             res = xsltProfileStylesheet(cur, doc, params, stderr);
238         } else {
239             res = xsltApplyStylesheet(cur, doc, params);
240         }
241         if (timing) {
242             if (repeat)
243                 endTimer("Applying stylesheet %d times", repeat);
244             else
245                 endTimer("Applying stylesheet");
246         }
247         xmlFreeDoc(doc);
248         if (res == NULL) {
249             fprintf(stderr, "no result for %s\n", filename);
250             return;
251         }
252         if (noout) {
253             xmlFreeDoc(res);
254             return;
255         }
256 #ifdef LIBXML_DEBUG_ENABLED
257         if (debug)
258             xmlDebugDumpDocument(stdout, res);
259         else {
260 #endif
261             if (cur->methodURI == NULL) {
262                 if (timing)
263                     startTimer();
264                 xsltSaveResultToFile(stdout, res, cur);
265                 if (timing)
266                     endTimer("Saving result");
267             } else {
268                 if (xmlStrEqual
269                     (cur->method, (const xmlChar *) "xhtml")) {
270                     fprintf(stderr, "non standard output xhtml\n");
271                     if (timing)
272                         startTimer();
273                     xsltSaveResultToFile(stdout, res, cur);
274                     if (timing)
275                         endTimer("Saving result");
276                 } else {
277                     fprintf(stderr,
278                             "Unsupported non standard output %s\n",
279                             cur->method);
280                 }
281             }
282 #ifdef LIBXML_DEBUG_ENABLED
283         }
284 #endif
285
286         xmlFreeDoc(res);
287     } else {
288         xsltRunStylesheet(cur, doc, params, output, NULL, NULL);
289         if (timing)
290             endTimer("Running stylesheet and saving result");
291         xmlFreeDoc(doc);
292     }
293 }
294
295 static void usage(const char *name) {
296     printf("Usage: %s [options] stylesheet file [file ...]\n", name);
297     printf("   Options:\n");
298     printf("\t--version or -V: show the version of libxml and libxslt used\n");
299     printf("\t--verbose or -v: show logs of what's happening\n");
300     printf("\t--output file or -o file: save to a given file\n");
301     printf("\t--timing: display the time used\n");
302     printf("\t--repeat: run the transformation 20 times\n");
303     printf("\t--debug: dump the tree of the result instead\n");
304     printf("\t--novalid: skip the Dtd loading phase\n");
305     printf("\t--noout: do not dump the result\n");
306     printf("\t--maxdepth val : increase the maximum depth\n");
307 #ifdef LIBXML_HTML_ENABLED
308     printf("\t--html: the input document is(are) an HTML file(s)\n");
309 #endif
310 #ifdef LIBXML_DOCB_ENABLED
311     printf("\t--docbook: the input document is SGML docbook\n");
312 #endif
313     printf("\t--param name value : pass a (parameter,value) pair\n");
314     printf("\t      string values must be quoted like \"'string'\"\n");
315     printf("\t--nonet refuse to fetch DTDs or entities over network\n");
316 #ifdef LIBXML_CATALOG_ENABLED
317     printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
318     printf("\t             otherwise XML Catalogs starting from \n");
319     printf("\t         file:///etc/xml/catalog are activated by default\n");
320 #endif
321 #ifdef LIBXML_XINCLUDE_ENABLED
322     printf("\t--xinclude : do XInclude processing on document intput\n");
323 #endif
324     printf("\t--profile or --norman : dump profiling informations \n");
325 }
326
327 int
328 main(int argc, char **argv)
329 {
330     int i;
331     xsltStylesheetPtr cur = NULL;
332     xmlDocPtr doc, style;
333
334     if (argc <= 1) {
335         usage(argv[0]);
336         return (1);
337     }
338
339     xmlInitMemory();
340
341     LIBXML_TEST_VERSION
342
343     xmlLineNumbersDefault(1);
344
345     if (novalid == 0)
346         xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
347     else
348         xmlLoadExtDtdDefaultValue = 0;
349     for (i = 1; i < argc; i++) {
350         if (!strcmp(argv[i], "-"))
351             break;
352
353         if (argv[i][0] != '-')
354             continue;
355 #ifdef LIBXML_DEBUG_ENABLED
356         if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
357             debug++;
358         } else
359 #endif
360         if ((!strcmp(argv[i], "-v")) ||
361                 (!strcmp(argv[i], "-verbose")) ||
362                 (!strcmp(argv[i], "--verbose"))) {
363             xsltSetGenericDebugFunc(stderr, NULL);
364         } else if ((!strcmp(argv[i], "-o")) ||
365                    (!strcmp(argv[i], "-output")) ||
366                    (!strcmp(argv[i], "--output"))) {
367             i++;
368             output = argv[i++];
369         } else if ((!strcmp(argv[i], "-V")) ||
370                    (!strcmp(argv[i], "-version")) ||
371                    (!strcmp(argv[i], "--version"))) {
372             printf("Using libxml %s, libxslt %s and libexslt %s\n",
373                    xmlParserVersion, xsltEngineVersion, exsltLibraryVersion);
374             printf
375     ("xsltproc was compiled against libxml %d, libxslt %d and libexslt %d\n",
376                  LIBXML_VERSION, LIBXSLT_VERSION, LIBEXSLT_VERSION);
377             printf("libxslt %d was compiled against libxml %d\n",
378                    xsltLibxsltVersion, xsltLibxmlVersion);
379             printf("libexslt %d was compiled against libxml %d\n",
380                    exsltLibexsltVersion, exsltLibxmlVersion);
381         } else if ((!strcmp(argv[i], "-repeat"))
382                    || (!strcmp(argv[i], "--repeat"))) {
383             if (repeat == 0)
384                 repeat = 20;
385             else
386                 repeat = 100;
387         } else if ((!strcmp(argv[i], "-novalid")) ||
388                    (!strcmp(argv[i], "--novalid"))) {
389             novalid++;
390         } else if ((!strcmp(argv[i], "-noout")) ||
391                    (!strcmp(argv[i], "--noout"))) {
392             noout++;
393 #ifdef LIBXML_DOCB_ENABLED
394         } else if ((!strcmp(argv[i], "-docbook")) ||
395                    (!strcmp(argv[i], "--docbook"))) {
396             docbook++;
397 #endif
398 #ifdef LIBXML_HTML_ENABLED
399         } else if ((!strcmp(argv[i], "-html")) ||
400                    (!strcmp(argv[i], "--html"))) {
401             html++;
402 #endif
403         } else if ((!strcmp(argv[i], "-timing")) ||
404                    (!strcmp(argv[i], "--timing"))) {
405             timing++;
406         } else if ((!strcmp(argv[i], "-profile")) ||
407                    (!strcmp(argv[i], "--profile"))) {
408             profile++;
409         } else if ((!strcmp(argv[i], "-norman")) ||
410                    (!strcmp(argv[i], "--norman"))) {
411             profile++;
412         } else if ((!strcmp(argv[i], "-nonet")) ||
413                    (!strcmp(argv[i], "--nonet"))) {
414             xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
415 #ifdef LIBXML_CATALOG_ENABLED
416         } else if ((!strcmp(argv[i], "-catalogs")) ||
417                    (!strcmp(argv[i], "--catalogs"))) {
418             const char *catalogs;
419
420             catalogs = getenv("SGML_CATALOG_FILES");
421             if (catalogs == NULL) {
422                 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
423             } else {
424                 xmlLoadCatalogs(catalogs);
425             }
426 #endif
427 #ifdef LIBXML_XINCLUDE_ENABLED
428         } else if ((!strcmp(argv[i], "-xinclude")) ||
429                    (!strcmp(argv[i], "--xinclude"))) {
430             xinclude++;
431             xsltSetXIncludeDefault(1);
432 #endif
433         } else if ((!strcmp(argv[i], "-param")) ||
434                    (!strcmp(argv[i], "--param"))) {
435             i++;
436             params[nbparams++] = argv[i++];
437             params[nbparams++] = argv[i];
438             if (nbparams >= 16) {
439                 fprintf(stderr, "too many params\n");
440                 return (1);
441             }
442         } else if ((!strcmp(argv[i], "-maxdepth")) ||
443                    (!strcmp(argv[i], "--maxdepth"))) {
444             int value;
445
446             i++;
447             if (sscanf(argv[i], "%d", &value) == 1) {
448                 if (value > 0)
449                     xsltMaxDepth = value;
450             }
451         } else {
452             fprintf(stderr, "Unknown option %s\n", argv[i]);
453             usage(argv[0]);
454             return (1);
455         }
456     }
457     params[nbparams] = NULL;
458
459     /*
460      * Replace entities with their content.
461      */
462     xmlSubstituteEntitiesDefault(1);
463
464     /*
465      * Register the EXSLT extensions and the test module
466      */
467     exsltRegisterAll();
468     xsltRegisterTestModule();
469
470     for (i = 1; i < argc; i++) {
471         if ((!strcmp(argv[i], "-maxdepth")) ||
472             (!strcmp(argv[i], "--maxdepth"))) {
473             i++;
474             continue;
475         } else if ((!strcmp(argv[i], "-o")) ||
476                    (!strcmp(argv[i], "-output")) ||
477                    (!strcmp(argv[i], "--output"))) {
478             i++;
479             continue;
480         }
481         if ((!strcmp(argv[i], "-param")) || (!strcmp(argv[i], "--param"))) {
482             i += 2;
483             continue;
484         }
485         if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
486             if (timing)
487                 startTimer();
488             style = xmlParseFile((const char *) argv[i]);
489             if (timing) 
490                 endTimer("Parsing stylesheet %s", argv[i]);
491             if (style == NULL) {
492                 fprintf(stderr,  "cannot parse %s\n", argv[i]);
493                 cur = NULL;
494             } else {
495                 cur = xsltLoadStylesheetPI(style);
496                 if (cur != NULL) {
497                     /* it is an embedded stylesheet */
498                     xsltProcess(style, cur, argv[i]);
499                     xsltFreeStylesheet(cur);
500                     goto done;
501                 }
502                 cur = xsltParseStylesheetDoc(style);
503                 if (cur != NULL) {
504                     if (cur->indent == 1)
505                         xmlIndentTreeOutput = 1;
506                     else
507                         xmlIndentTreeOutput = 0;
508                     i++;
509                 } else {
510                     xmlFreeDoc(style);
511                     goto done;
512                 }
513             }
514             break;
515
516         }
517     }
518
519     /*
520      * disable CDATA from being built in the document tree
521      */
522     xmlDefaultSAXHandlerInit();
523     xmlDefaultSAXHandler.cdataBlock = NULL;
524
525     if ((cur != NULL) && (cur->errors == 0)) {
526         for (; i < argc; i++) {
527             doc = NULL;
528             if (timing)
529                 startTimer();
530 #ifdef LIBXML_HTML_ENABLED
531             if (html)
532                 doc = htmlParseFile(argv[i], NULL);
533             else
534 #endif
535 #ifdef LIBXML_DOCB_ENABLED
536             if (docbook)
537                 doc = docbParseFile(argv[i], NULL);
538             else
539 #endif
540                 doc = xmlParseFile(argv[i]);
541             if (doc == NULL) {
542                 fprintf(stderr, "unable to parse %s\n", argv[i]);
543                 continue;
544             }
545             if (timing)
546                 endTimer("Parsing document %s", argv[i]);
547             xsltProcess(doc, cur, argv[i]);
548         }
549     }
550     if (cur != NULL)
551         xsltFreeStylesheet(cur);
552 done:
553     xsltCleanupGlobals();
554     xmlCleanupParser();
555     xmlMemoryDump();
556     return (0);
557 }
558