more info about --output from Daniel Leidert c.f. #344654 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 #include <stdio.h>
12 #ifdef HAVE_STRING_H
13 #include <string.h>
14 #endif
15 #ifdef HAVE_SYS_TIME_H
16 #include <sys/time.h>
17 #endif
18 #ifdef HAVE_TIME_H
19 #include <time.h>
20 #endif
21 #ifdef HAVE_SYS_STAT_H
22 #include <sys/stat.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30 #ifdef HAVE_STDARG_H
31 #include <stdarg.h>
32 #endif
33 #include <libxml/xmlmemory.h>
34 #include <libxml/debugXML.h>
35 #include <libxml/HTMLtree.h>
36 #include <libxml/xmlIO.h>
37 #ifdef LIBXML_XINCLUDE_ENABLED
38 #include <libxml/xinclude.h>
39 #endif
40 #ifdef LIBXML_CATALOG_ENABLED
41 #include <libxml/catalog.h>
42 #endif
43 #include <libxml/parser.h>
44 #include <libxml/parserInternals.h>
45 #include <libxml/uri.h>
46
47 #include <libxslt/xslt.h>
48 #include <libxslt/xsltInternals.h>
49 #include <libxslt/transform.h>
50 #include <libxslt/xsltutils.h>
51 #include <libxslt/extensions.h>
52 #include <libxslt/security.h>
53
54 #include <libexslt/exsltconfig.h>
55
56 #if defined(WIN32) && !defined (__CYGWIN__)
57 #if defined(_MSC_VER) || defined(__MINGW32__)
58 #include <winsock2.h>
59 #define gettimeofday(p1,p2)
60 #define snprintf _snprintf
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 #ifdef HAVE_SYS_TIMEB_H
71 #include <sys/timeb.h>
72 #endif
73
74 static int debug = 0;
75 static int repeat = 0;
76 static int timing = 0;
77 static int dumpextensions = 0;
78 static int novalid = 0;
79 static int nodtdattr = 0;
80 static int noout = 0;
81 static int nodict = 0;
82 #ifdef LIBXML_HTML_ENABLED
83 static int html = 0;
84 #endif
85 static int load_trace = 0;
86 #ifdef LIBXML_XINCLUDE_ENABLED
87 static int xinclude = 0;
88 #endif
89 static int profile = 0;
90
91 #define MAX_PARAMETERS 64
92 #define MAX_PATHS 64
93
94 static int options = XSLT_PARSE_OPTIONS;
95 static const char *params[MAX_PARAMETERS + 1];
96 static int nbparams = 0;
97 static xmlChar *strparams[MAX_PARAMETERS + 1];
98 static int nbstrparams = 0;
99 static xmlChar *paths[MAX_PATHS + 1];
100 static int nbpaths = 0;
101 static char *output = NULL;
102 static int errorno = 0;
103 static const char *writesubtree = NULL;
104
105 /*
106  * Entity loading control and customization.
107  */
108 static
109 void parsePath(const xmlChar *path) {
110     const xmlChar *cur;
111
112     if (path == NULL)
113         return;
114     while (*path != 0) {
115         if (nbpaths >= MAX_PATHS) {
116             fprintf(stderr, "MAX_PATHS reached: too many paths\n");
117             return;
118         }
119         cur = path;
120         while ((*cur == ' ') || (*cur == ':'))
121             cur++;
122         path = cur;
123         while ((*cur != 0) && (*cur != ' ') && (*cur != ':'))
124             cur++;
125         if (cur != path) {
126             paths[nbpaths] = xmlStrndup(path, cur - path);
127             if (paths[nbpaths] != NULL)
128                 nbpaths++;
129             path = cur;
130         }
131     }
132 }
133
134 xmlExternalEntityLoader defaultEntityLoader = NULL;
135
136 static xmlParserInputPtr 
137 xsltprocExternalEntityLoader(const char *URL, const char *ID,
138                              xmlParserCtxtPtr ctxt) {
139     xmlParserInputPtr ret;
140     warningSAXFunc warning = NULL;
141
142     int i;
143     const char *lastsegment = URL;
144     const char *iter = URL;
145
146     if (nbpaths > 0) {
147         while (*iter != 0) {
148             if (*iter == '/')
149                 lastsegment = iter + 1;
150             iter++;
151         }
152     }
153
154     if ((ctxt != NULL) && (ctxt->sax != NULL)) {
155         warning = ctxt->sax->warning;
156         ctxt->sax->warning = NULL;
157     }
158
159     if (defaultEntityLoader != NULL) {
160         ret = defaultEntityLoader(URL, ID, ctxt);
161         if (ret != NULL) {
162             if (warning != NULL)
163                 ctxt->sax->warning = warning;
164             if (load_trace) {
165                 fprintf \
166                         (stderr,
167                          "Loaded URL=\"%s\" ID=\"%s\"\n",
168                          URL ? URL : "(null)",
169                          ID ? ID : "(null)");
170             }
171             return(ret);
172         }
173     }
174     for (i = 0;i < nbpaths;i++) {
175         xmlChar *newURL;
176
177         newURL = xmlStrdup((const xmlChar *) paths[i]);
178         newURL = xmlStrcat(newURL, (const xmlChar *) "/");
179         newURL = xmlStrcat(newURL, (const xmlChar *) lastsegment);
180         if (newURL != NULL) {
181             ret = defaultEntityLoader((const char *)newURL, ID, ctxt);
182             if (ret != NULL) {
183                 if (warning != NULL)
184                     ctxt->sax->warning = warning;
185                 if (load_trace) {
186                     fprintf \
187                         (stderr,
188                          "Loaded URL=\"%s\" ID=\"%s\"\n",
189                          newURL,
190                          ID ? ID : "(null)");
191                 }
192                 xmlFree(newURL);
193                 return(ret);
194             }
195             xmlFree(newURL);
196         }
197     }
198     if (warning != NULL) {
199         ctxt->sax->warning = warning;
200         if (URL != NULL)
201             warning(ctxt, "failed to load external entity \"%s\"\n", URL);
202         else if (ID != NULL)
203             warning(ctxt, "failed to load external entity \"%s\"\n", ID);
204     }
205     return(NULL);
206 }
207
208 /*
209  * Internal timing routines to remove the necessity to have unix-specific
210  * function calls
211  */
212 #ifndef HAVE_GETTIMEOFDAY 
213 #ifdef HAVE_SYS_TIMEB_H
214 #ifdef HAVE_SYS_TIME_H
215 #ifdef HAVE_FTIME
216
217 int
218 my_gettimeofday(struct timeval *tvp, void *tzp)
219 {
220         struct timeb timebuffer;
221
222         ftime(&timebuffer);
223         if (tvp) {
224                 tvp->tv_sec = timebuffer.time;
225                 tvp->tv_usec = timebuffer.millitm * 1000L;
226         }
227         return (0);
228 }
229 #define HAVE_GETTIMEOFDAY 1
230 #define gettimeofday my_gettimeofday
231
232 #endif /* HAVE_FTIME */
233 #endif /* HAVE_SYS_TIME_H */
234 #endif /* HAVE_SYS_TIMEB_H */
235 #endif /* !HAVE_GETTIMEOFDAY */
236
237 #if defined(HAVE_GETTIMEOFDAY)
238 static struct timeval begin, endtime;
239 /*
240  * startTimer: call where you want to start timing
241  */
242 static void startTimer(void)
243 {
244     gettimeofday(&begin,NULL);
245 }
246 /*
247  * endTimer: call where you want to stop timing and to print out a
248  *           message about the timing performed; format is a printf
249  *           type argument
250  */
251 static void endTimer(const char *format, ...)
252 {
253     long msec;
254     va_list ap;
255
256     gettimeofday(&endtime, NULL);
257     msec = endtime.tv_sec - begin.tv_sec;
258     msec *= 1000;
259     msec += (endtime.tv_usec - begin.tv_usec) / 1000;
260
261 #ifndef HAVE_STDARG_H
262 #error "endTimer required stdarg functions"
263 #endif
264     va_start(ap, format);
265     vfprintf(stderr,format,ap);
266     va_end(ap);
267
268     fprintf(stderr, " took %ld ms\n", msec);
269 }
270 #elif defined(HAVE_TIME_H)
271 /*
272  * No gettimeofday function, so we have to make do with calling clock.
273  * This is obviously less accurate, but there's little we can do about
274  * that.
275  */
276 #ifndef CLOCKS_PER_SEC
277 #define CLOCKS_PER_SEC 100
278 #endif
279
280 clock_t begin, endtime;
281 static void startTimer(void)
282 {
283     begin=clock();
284 }
285 static void endTimer(char *format, ...)
286 {
287     long msec;
288     va_list ap;
289
290     endtime=clock();
291     msec = ((endtime-begin) * 1000) / CLOCKS_PER_SEC;
292
293 #ifndef HAVE_STDARG_H
294 #error "endTimer required stdarg functions"
295 #endif
296     va_start(ap, format);
297     vfprintf(stderr,format,ap);
298     va_end(ap);
299     fprintf(stderr, " took %ld ms\n", msec);
300 }
301 #else
302 /*
303  * We don't have a gettimeofday or time.h, so we just don't do timing
304  */
305 static void startTimer(void)
306 {
307   /*
308    * Do nothing
309    */
310 }
311 static void endTimer(char *format, ...)
312 {
313   /*
314    * We cannot do anything because we don't have a timing function
315    */
316 #ifdef HAVE_STDARG_H
317     va_start(ap, format);
318     vfprintf(stderr,format,ap);
319     va_end(ap);
320     fprintf(stderr, " was not timed\n", msec);
321 #else
322   /* We don't have gettimeofday, time or stdarg.h, what crazy world is
323    * this ?!
324    */
325 #endif
326 }
327 #endif
328
329 /*
330  * xsltSubtreeCheck:
331  *
332  * allow writes only on a subtree specified on the command line
333  */
334 static int
335 xsltSubtreeCheck(xsltSecurityPrefsPtr sec ATTRIBUTE_UNUSED,
336                   xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
337                   const char *value ATTRIBUTE_UNUSED) {
338     int len, ret;
339
340     if (writesubtree == NULL)
341         return(0);
342     if (value == NULL)
343         return(-1);
344
345     len = xmlStrlen(BAD_CAST writesubtree);
346     ret = xmlStrncmp(BAD_CAST writesubtree, BAD_CAST value, len);
347     if (ret == 0)
348         return(1);
349     return(0);
350 }
351
352 static void
353 xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur, const char *filename) {
354     xmlDocPtr res;
355     xsltTransformContextPtr ctxt;
356    
357
358 #ifdef LIBXML_XINCLUDE_ENABLED
359     if (xinclude) {
360         if (timing)
361             startTimer();
362 #if LIBXML_VERSION >= 20603
363         xmlXIncludeProcessFlags(doc, XSLT_PARSE_OPTIONS);
364 #else
365         xmlXIncludeProcess(doc);
366 #endif
367         if (timing) {
368             endTimer("XInclude processing %s", filename);
369         }
370     }
371 #endif
372     if (timing)
373         startTimer();
374     if (output == NULL) {
375         if (repeat) {
376             int j;
377
378             for (j = 1; j < repeat; j++) {
379                 res = xsltApplyStylesheet(cur, doc, params);
380                 xmlFreeDoc(res);
381                 xmlFreeDoc(doc);
382 #ifdef LIBXML_HTML_ENABLED
383                 if (html)
384                     doc = htmlReadFile(filename, NULL, options);
385                 else
386 #endif
387                     doc = xmlReadFile(filename, NULL, options);
388             }
389         }
390         ctxt = xsltNewTransformContext(cur, doc);
391         if (ctxt == NULL)
392             return;
393         xsltSetCtxtParseOptions(ctxt, options);
394         if (xinclude)
395             ctxt->xinclude = 1;
396         if (profile) {
397             res = xsltApplyStylesheetUser(cur, doc, params, NULL,
398                                           stderr, ctxt);
399         } else {
400             res = xsltApplyStylesheetUser(cur, doc, params, NULL,
401                                           NULL, ctxt);
402         }
403         if (ctxt->state == XSLT_STATE_ERROR)
404             errorno = 9;
405         else if (ctxt->state == XSLT_STATE_STOPPED)
406             errorno = 10;
407         xsltFreeTransformContext(ctxt);
408         if (timing) {
409             if (repeat)
410                 endTimer("Applying stylesheet %d times", repeat);
411             else
412                 endTimer("Applying stylesheet");
413         }
414         xmlFreeDoc(doc);
415         if (res == NULL) {
416             fprintf(stderr, "no result for %s\n", filename);
417             return;
418         }
419         if (noout) {
420             xmlFreeDoc(res);
421             return;
422         }
423 #ifdef LIBXML_DEBUG_ENABLED
424         if (debug)
425             xmlDebugDumpDocument(stdout, res);
426         else {
427 #endif
428             if (cur->methodURI == NULL) {
429                 if (timing)
430                     startTimer();
431                 xsltSaveResultToFile(stdout, res, cur);
432                 if (timing)
433                     endTimer("Saving result");
434             } else {
435                 if (xmlStrEqual
436                     (cur->method, (const xmlChar *) "xhtml")) {
437                     fprintf(stderr, "non standard output xhtml\n");
438                     if (timing)
439                         startTimer();
440                     xsltSaveResultToFile(stdout, res, cur);
441                     if (timing)
442                         endTimer("Saving result");
443                 } else {
444                     fprintf(stderr,
445                             "Unsupported non standard output %s\n",
446                             cur->method);
447                     errorno = 7;
448                 }
449             }
450 #ifdef LIBXML_DEBUG_ENABLED
451         }
452 #endif
453
454         xmlFreeDoc(res);
455     } else {
456
457         ctxt = xsltNewTransformContext(cur, doc);
458         if (ctxt == NULL)
459             return;
460         if (profile) {
461             xsltRunStylesheetUser(cur, doc, params, output,
462                                         NULL, NULL, stderr, ctxt);
463         } else {
464             xsltRunStylesheetUser(cur, doc, params, output,
465                                         NULL, NULL, NULL, ctxt);
466         }
467         if (ctxt->state == XSLT_STATE_ERROR)
468             errorno = 9;
469         else if (ctxt->state == XSLT_STATE_STOPPED)
470             errorno = 10;
471         xsltFreeTransformContext(ctxt);
472         if (timing)
473             endTimer("Running stylesheet and saving result");
474         xmlFreeDoc(doc);
475     }
476 }
477
478 static void usage(const char *name) {
479     printf("Usage: %s [options] stylesheet file [file ...]\n", name);
480     printf("   Options:\n");
481     printf("\t--version or -V: show the version of libxml and libxslt used\n");
482     printf("\t--verbose or -v: show logs of what's happening\n");
483     printf("\t--output file or -o file: save to a given file\n");
484     printf("\t--timing: display the time used\n");
485     printf("\t--repeat: run the transformation 20 times\n");
486 #ifdef LIBXML_DEBUG_ENABLED
487     printf("\t--debug: dump the tree of the result instead\n");
488 #endif
489     printf("\t--dumpextensions: dump the registered extension elements and functions to stdout\n");
490     printf("\t--novalid skip the Dtd loading phase\n");
491     printf("\t--nodtdattr do not default attributes from the DTD\n");
492     printf("\t--noout: do not dump the result\n");
493     printf("\t--maxdepth val : increase the maximum depth\n");
494     printf("\t--maxparserdepth val : increase the maximum parser depth\n");
495 #ifdef LIBXML_HTML_ENABLED
496     printf("\t--html: the input document is(are) an HTML file(s)\n");
497 #endif
498     printf("\t--param name value : pass a (parameter,value) pair\n");
499     printf("\t       value is an UTF8 XPath expression.\n");
500     printf("\t       string values must be quoted like \"'string'\"\n or");
501     printf("\t       use stringparam to avoid it\n");
502     printf("\t--stringparam name value : pass a (parameter, UTF8 string value) pair\n");
503     printf("\t--path 'paths': provide a set of paths for resources\n");
504     printf("\t--nonet : refuse to fetch DTDs or entities over network\n");
505     printf("\t--nowrite : refuse to write to any file or resource\n");
506     printf("\t--nomkdir : refuse to create directories\n");
507     printf("\t--writesubtree path : allow file write only with the path subtree\n");
508 #ifdef LIBXML_CATALOG_ENABLED
509     printf("\t--catalogs : use SGML catalogs from $SGML_CATALOG_FILES\n");
510     printf("\t             otherwise XML Catalogs starting from \n");
511     printf("\t         file:///etc/xml/catalog are activated by default\n");
512 #endif
513 #ifdef LIBXML_XINCLUDE_ENABLED
514     printf("\t--xinclude : do XInclude processing on document intput\n");
515 #endif
516     printf("\t--load-trace : print trace of all external entites loaded\n");
517     printf("\t--profile or --norman : dump profiling informations \n");
518     printf("\nProject libxslt home page: http://xmlsoft.org/XSLT/\n");
519     printf("To report bugs and get help: http://xmlsoft.org/XSLT/bugs.html\n");
520 }
521
522 int
523 main(int argc, char **argv)
524 {
525     int i;
526     xsltStylesheetPtr cur = NULL;
527     xmlDocPtr doc, style;
528     xsltSecurityPrefsPtr sec = NULL;
529
530     if (argc <= 1) {
531         usage(argv[0]);
532         return (1);
533     }
534
535     xmlInitMemory();
536
537     LIBXML_TEST_VERSION
538
539     sec = xsltNewSecurityPrefs();
540     xsltSetDefaultSecurityPrefs(sec);
541     defaultEntityLoader = xmlGetExternalEntityLoader();
542     xmlSetExternalEntityLoader(xsltprocExternalEntityLoader);
543
544     for (i = 1; i < argc; i++) {
545         if (!strcmp(argv[i], "-"))
546             break;
547
548         if (argv[i][0] != '-')
549             continue;
550 #ifdef LIBXML_DEBUG_ENABLED
551         if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
552             debug++;
553         } else
554 #endif
555         if ((!strcmp(argv[i], "-v")) ||
556                 (!strcmp(argv[i], "-verbose")) ||
557                 (!strcmp(argv[i], "--verbose"))) {
558             xsltSetGenericDebugFunc(stderr, NULL);
559         } else if ((!strcmp(argv[i], "-o")) ||
560                    (!strcmp(argv[i], "-output")) ||
561                    (!strcmp(argv[i], "--output"))) {
562             i++;
563 #if defined(WIN32) || defined (__CYGWIN__)
564             output = xmlCanonicPath(argv[i]);
565             if (output == NULL)
566 #endif
567                 output = (char *) xmlStrdup((xmlChar *) argv[i]);
568         } else if ((!strcmp(argv[i], "-V")) ||
569                    (!strcmp(argv[i], "-version")) ||
570                    (!strcmp(argv[i], "--version"))) {
571             printf("Using libxml %s, libxslt %s and libexslt %s\n",
572                    xmlParserVersion, xsltEngineVersion, exsltLibraryVersion);
573             printf
574     ("xsltproc was compiled against libxml %d, libxslt %d and libexslt %d\n",
575                  LIBXML_VERSION, LIBXSLT_VERSION, LIBEXSLT_VERSION);
576             printf("libxslt %d was compiled against libxml %d\n",
577                    xsltLibxsltVersion, xsltLibxmlVersion);
578             printf("libexslt %d was compiled against libxml %d\n",
579                    exsltLibexsltVersion, exsltLibxmlVersion);
580         } else if ((!strcmp(argv[i], "-repeat"))
581                    || (!strcmp(argv[i], "--repeat"))) {
582             if (repeat == 0)
583                 repeat = 20;
584             else
585                 repeat = 100;
586         } else if ((!strcmp(argv[i], "-novalid")) ||
587                    (!strcmp(argv[i], "--novalid"))) {
588             novalid++;
589         } else if ((!strcmp(argv[i], "-nodtdattr")) ||
590                    (!strcmp(argv[i], "--nodtdattr"))) {
591             nodtdattr++;
592         } else if ((!strcmp(argv[i], "-noout")) ||
593                    (!strcmp(argv[i], "--noout"))) {
594             noout++;
595 #ifdef LIBXML_HTML_ENABLED
596         } else if ((!strcmp(argv[i], "-html")) ||
597                    (!strcmp(argv[i], "--html"))) {
598             html++;
599 #endif
600         } else if ((!strcmp(argv[i], "-timing")) ||
601                    (!strcmp(argv[i], "--timing"))) {
602             timing++;
603         } else if ((!strcmp(argv[i], "-profile")) ||
604                    (!strcmp(argv[i], "--profile"))) {
605             profile++;
606         } else if ((!strcmp(argv[i], "-nodict")) ||
607                    (!strcmp(argv[i], "--nodict"))) {
608             nodict++;
609         } else if ((!strcmp(argv[i], "-norman")) ||
610                    (!strcmp(argv[i], "--norman"))) {
611             profile++;
612         } else if ((!strcmp(argv[i], "-nonet")) ||
613                    (!strcmp(argv[i], "--nonet"))) {
614             defaultEntityLoader = xmlNoNetExternalEntityLoader;
615         } else if ((!strcmp(argv[i], "-nowrite")) ||
616                    (!strcmp(argv[i], "--nowrite"))) {
617             xsltSetSecurityPrefs(sec, XSLT_SECPREF_WRITE_FILE,
618                                  xsltSecurityForbid);
619             xsltSetSecurityPrefs(sec, XSLT_SECPREF_CREATE_DIRECTORY,
620                                  xsltSecurityForbid);
621             xsltSetSecurityPrefs(sec, XSLT_SECPREF_WRITE_NETWORK,
622                                  xsltSecurityForbid);
623         } else if ((!strcmp(argv[i], "-nomkdir")) ||
624                    (!strcmp(argv[i], "--nomkdir"))) {
625             xsltSetSecurityPrefs(sec, XSLT_SECPREF_CREATE_DIRECTORY,
626                                  xsltSecurityForbid);
627         } else if ((!strcmp(argv[i], "-writesubtree")) ||
628                    (!strcmp(argv[i], "--writesubtree"))) {
629             i++;
630             writesubtree = argv[i];
631             xsltSetSecurityPrefs(sec, XSLT_SECPREF_WRITE_FILE,
632                                  xsltSubtreeCheck);
633         } else if ((!strcmp(argv[i], "-path")) ||
634                    (!strcmp(argv[i], "--path"))) {
635             i++;
636             parsePath(BAD_CAST argv[i]);
637 #ifdef LIBXML_CATALOG_ENABLED
638         } else if ((!strcmp(argv[i], "-catalogs")) ||
639                    (!strcmp(argv[i], "--catalogs"))) {
640             const char *catalogs;
641
642             catalogs = getenv("SGML_CATALOG_FILES");
643             if (catalogs == NULL) {
644                 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
645             } else {
646                 xmlLoadCatalogs(catalogs);
647             }
648 #endif
649 #ifdef LIBXML_XINCLUDE_ENABLED
650         } else if ((!strcmp(argv[i], "-xinclude")) ||
651                    (!strcmp(argv[i], "--xinclude"))) {
652             xinclude++;
653             xsltSetXIncludeDefault(1);
654 #endif
655         } else if ((!strcmp(argv[i], "-load-trace")) ||
656                    (!strcmp(argv[i], "--load-trace"))) {
657             load_trace++;
658         } else if ((!strcmp(argv[i], "-param")) ||
659                    (!strcmp(argv[i], "--param"))) {
660             i++;
661             params[nbparams++] = argv[i++];
662             params[nbparams++] = argv[i];
663             if (nbparams >= MAX_PARAMETERS) {
664                 fprintf(stderr, "too many params increase MAX_PARAMETERS \n");
665                 return (2);
666             }
667         } else if ((!strcmp(argv[i], "-stringparam")) ||
668                    (!strcmp(argv[i], "--stringparam"))) {
669             const xmlChar *string;
670             xmlChar *value;
671
672             i++;
673             params[nbparams++] = argv[i++];
674             string = (const xmlChar *) argv[i];
675             if (xmlStrchr(string, '"')) {
676                 if (xmlStrchr(string, '\'')) {
677                     fprintf(stderr,
678                     "stringparam contains both quote and double-quotes !\n");
679                     return(8);
680                 }
681                 value = xmlStrdup((const xmlChar *)"'");
682                 value = xmlStrcat(value, string);
683                 value = xmlStrcat(value, (const xmlChar *)"'");
684             } else {
685                 value = xmlStrdup((const xmlChar *)"\"");
686                 value = xmlStrcat(value, string);
687                 value = xmlStrcat(value, (const xmlChar *)"\"");
688             }
689
690             params[nbparams++] = (const char *) value;
691             strparams[nbstrparams++] = value;
692             if (nbparams >= MAX_PARAMETERS) {
693                 fprintf(stderr, "too many params increase MAX_PARAMETERS \n");
694                 return (2);
695             }
696         } else if ((!strcmp(argv[i], "-maxdepth")) ||
697                    (!strcmp(argv[i], "--maxdepth"))) {
698             int value;
699
700             i++;
701             if (sscanf(argv[i], "%d", &value) == 1) {
702                 if (value > 0)
703                     xsltMaxDepth = value;
704             }
705         } else if ((!strcmp(argv[i], "-maxparserdepth")) ||
706                    (!strcmp(argv[i], "--maxparserdepth"))) {
707             int value;
708
709             i++;
710             if (sscanf(argv[i], "%d", &value) == 1) {
711                 if (value > 0)
712                     xmlParserMaxDepth = value;
713             }
714         } else if ((!strcmp(argv[i],"-dumpextensions"))||
715                         (!strcmp(argv[i],"--dumpextensions"))) {
716                 dumpextensions++;
717                 
718         } else {
719             fprintf(stderr, "Unknown option %s\n", argv[i]);
720             usage(argv[0]);
721             return (3);
722         }
723     }
724     params[nbparams] = NULL;
725
726     if (novalid != 0)
727         options = XML_PARSE_NOENT | XML_PARSE_NOCDATA;
728     else if (nodtdattr)
729         options = XML_PARSE_NOENT | XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA;
730     if (nodict != 0)
731         options |= XML_PARSE_NODICT;
732
733     /*
734      * Register the EXSLT extensions and the test module
735      */
736     exsltRegisterAll();
737     xsltRegisterTestModule();
738
739     if (dumpextensions) 
740         xsltDebugDumpExtensions(NULL);
741
742     for (i = 1; i < argc; i++) {
743         if ((!strcmp(argv[i], "-maxdepth")) ||
744             (!strcmp(argv[i], "--maxdepth"))) {
745             i++;
746             continue;
747         } else if ((!strcmp(argv[i], "-maxparserdepth")) ||
748             (!strcmp(argv[i], "--maxparserdepth"))) {
749             i++;
750             continue;
751         } else if ((!strcmp(argv[i], "-o")) ||
752                    (!strcmp(argv[i], "-output")) ||
753                    (!strcmp(argv[i], "--output"))) {
754             i++;
755             continue;
756         } else if ((!strcmp(argv[i], "-writesubtree")) ||
757                    (!strcmp(argv[i], "--writesubtree"))) {
758             i++;
759             continue;
760         } else if ((!strcmp(argv[i], "-path")) ||
761                    (!strcmp(argv[i], "--path"))) {
762             i++;
763             continue;
764         }
765         if ((!strcmp(argv[i], "-param")) || (!strcmp(argv[i], "--param"))) {
766             i += 2;
767             continue;
768         }
769         if ((!strcmp(argv[i], "-stringparam")) ||
770             (!strcmp(argv[i], "--stringparam"))) {
771             i += 2;
772             continue;
773         }
774         if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
775             if (timing)
776                 startTimer();
777             style = xmlReadFile((const char *) argv[i], NULL, options);
778             if (timing) 
779                 endTimer("Parsing stylesheet %s", argv[i]);
780             if (style == NULL) {
781                 fprintf(stderr,  "cannot parse %s\n", argv[i]);
782                 cur = NULL;
783                 errorno = 4;
784             } else {
785                 cur = xsltLoadStylesheetPI(style);
786                 if (cur != NULL) {
787                     /* it is an embedded stylesheet */
788                     xsltProcess(style, cur, argv[i]);
789                     xsltFreeStylesheet(cur);
790                     cur = NULL;
791                     goto done;
792                 }
793                 cur = xsltParseStylesheetDoc(style);
794                 if (cur != NULL) {
795                     if (cur->errors != 0) {
796                         errorno = 5;
797                         goto done;
798                     }
799                     i++;
800                 } else {
801                     xmlFreeDoc(style);
802                     errorno = 5;
803                     goto done;
804                 }
805             }
806             break;
807
808         }
809     }
810
811
812     if ((cur != NULL) && (cur->errors == 0)) {
813         for (; i < argc; i++) {
814             doc = NULL;
815             if (timing)
816                 startTimer();
817 #ifdef LIBXML_HTML_ENABLED
818             if (html)
819                 doc = htmlReadFile(argv[i], NULL, options);
820             else
821 #endif
822                 doc = xmlReadFile(argv[i], NULL, options);
823             if (doc == NULL) {
824                 fprintf(stderr, "unable to parse %s\n", argv[i]);
825                 errorno = 6;
826                 continue;
827             }
828             if (timing)
829                 endTimer("Parsing document %s", argv[i]);
830             xsltProcess(doc, cur, argv[i]);
831         }
832     }
833 done:
834     if (cur != NULL)
835         xsltFreeStylesheet(cur);
836     for (i = 0;i < nbstrparams;i++)
837         xmlFree(strparams[i]);
838     if (output != NULL)
839         xmlFree(output);
840     xsltFreeSecurityPrefs(sec);
841     xsltCleanupGlobals();
842     xmlCleanupParser();
843     xmlMemoryDump();
844     return(errorno);
845 }
846