Imported Upstream version 2.2.4
[platform/upstream/expat.git] / xmlwf / xmlwf.c
1 /*
2                             __  __            _
3                          ___\ \/ /_ __   __ _| |_
4                         / _ \\  /| '_ \ / _` | __|
5                        |  __//  \| |_) | (_| | |_
6                         \___/_/\_\ .__/ \__,_|\__|
7                                  |_| XML parser
8
9    Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10    Copyright (c) 2000-2017 Expat development team
11    Licensed under the MIT license:
12
13    Permission is  hereby granted,  free of charge,  to any  person obtaining
14    a  copy  of  this  software   and  associated  documentation  files  (the
15    "Software"),  to  deal in  the  Software  without restriction,  including
16    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
17    distribute, sublicense, and/or sell copies of the Software, and to permit
18    persons  to whom  the Software  is  furnished to  do so,  subject to  the
19    following conditions:
20
21    The above copyright  notice and this permission notice  shall be included
22    in all copies or substantial portions of the Software.
23
24    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
25    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
26    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
29    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30    USE OR OTHER DEALINGS IN THE SOFTWARE.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stddef.h>
36 #include <string.h>
37
38 #include "expat.h"
39 #include "codepage.h"
40 #include "internal.h"  /* for UNUSED_P only */
41 #include "xmlfile.h"
42 #include "xmltchar.h"
43
44 #ifdef _MSC_VER
45 #include <crtdbg.h>
46 #endif
47
48 /* This ensures proper sorting. */
49
50 #define NSSEP T('\001')
51
52 static void XMLCALL
53 characterData(void *userData, const XML_Char *s, int len)
54 {
55   FILE *fp = (FILE *)userData;
56   for (; len > 0; --len, ++s) {
57     switch (*s) {
58     case T('&'):
59       fputts(T("&amp;"), fp);
60       break;
61     case T('<'):
62       fputts(T("&lt;"), fp);
63       break;
64     case T('>'):
65       fputts(T("&gt;"), fp);
66       break;
67 #ifdef W3C14N
68     case 13:
69       fputts(T("&#xD;"), fp);
70       break;
71 #else
72     case T('"'):
73       fputts(T("&quot;"), fp);
74       break;
75     case 9:
76     case 10:
77     case 13:
78       ftprintf(fp, T("&#%d;"), *s);
79       break;
80 #endif
81     default:
82       puttc(*s, fp);
83       break;
84     }
85   }
86 }
87
88 static void
89 attributeValue(FILE *fp, const XML_Char *s)
90 {
91   puttc(T('='), fp);
92   puttc(T('"'), fp);
93   for (;;) {
94     switch (*s) {
95     case 0:
96     case NSSEP:
97       puttc(T('"'), fp);
98       return;
99     case T('&'):
100       fputts(T("&amp;"), fp);
101       break;
102     case T('<'):
103       fputts(T("&lt;"), fp);
104       break;
105     case T('"'):
106       fputts(T("&quot;"), fp);
107       break;
108 #ifdef W3C14N
109     case 9:
110       fputts(T("&#x9;"), fp);
111       break;
112     case 10:
113       fputts(T("&#xA;"), fp);
114       break;
115     case 13:
116       fputts(T("&#xD;"), fp);
117       break;
118 #else
119     case T('>'):
120       fputts(T("&gt;"), fp);
121       break;
122     case 9:
123     case 10:
124     case 13:
125       ftprintf(fp, T("&#%d;"), *s);
126       break;
127 #endif
128     default:
129       puttc(*s, fp);
130       break;
131     }
132     s++;
133   }
134 }
135
136 /* Lexicographically comparing UTF-8 encoded attribute values,
137 is equivalent to lexicographically comparing based on the character number. */
138
139 static int
140 attcmp(const void *att1, const void *att2)
141 {
142   return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
143 }
144
145 static void XMLCALL
146 startElement(void *userData, const XML_Char *name, const XML_Char **atts)
147 {
148   int nAtts;
149   const XML_Char **p;
150   FILE *fp = (FILE *)userData;
151   puttc(T('<'), fp);
152   fputts(name, fp);
153
154   p = atts;
155   while (*p)
156     ++p;
157   nAtts = (int)((p - atts) >> 1);
158   if (nAtts > 1)
159     qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
160   while (*atts) {
161     puttc(T(' '), fp);
162     fputts(*atts++, fp);
163     attributeValue(fp, *atts);
164     atts++;
165   }
166   puttc(T('>'), fp);
167 }
168
169 static void XMLCALL
170 endElement(void *userData, const XML_Char *name)
171 {
172   FILE *fp = (FILE *)userData;
173   puttc(T('<'), fp);
174   puttc(T('/'), fp);
175   fputts(name, fp);
176   puttc(T('>'), fp);
177 }
178
179 static int
180 nsattcmp(const void *p1, const void *p2)
181 {
182   const XML_Char *att1 = *(const XML_Char **)p1;
183   const XML_Char *att2 = *(const XML_Char **)p2;
184   int sep1 = (tcsrchr(att1, NSSEP) != 0);
185   int sep2 = (tcsrchr(att1, NSSEP) != 0);
186   if (sep1 != sep2)
187     return sep1 - sep2;
188   return tcscmp(att1, att2);
189 }
190
191 static void XMLCALL
192 startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
193 {
194   int nAtts;
195   int nsi;
196   const XML_Char **p;
197   FILE *fp = (FILE *)userData;
198   const XML_Char *sep;
199   puttc(T('<'), fp);
200
201   sep = tcsrchr(name, NSSEP);
202   if (sep) {
203     fputts(T("n1:"), fp);
204     fputts(sep + 1, fp);
205     fputts(T(" xmlns:n1"), fp);
206     attributeValue(fp, name);
207     nsi = 2;
208   }
209   else {
210     fputts(name, fp);
211     nsi = 1;
212   }
213
214   p = atts;
215   while (*p)
216     ++p;
217   nAtts = (int)((p - atts) >> 1);
218   if (nAtts > 1)
219     qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
220   while (*atts) {
221     name = *atts++;
222     sep = tcsrchr(name, NSSEP);
223     puttc(T(' '), fp);
224     if (sep) {
225       ftprintf(fp, T("n%d:"), nsi);
226       fputts(sep + 1, fp);
227     }
228     else
229       fputts(name, fp);
230     attributeValue(fp, *atts);
231     if (sep) {
232       ftprintf(fp, T(" xmlns:n%d"), nsi++);
233       attributeValue(fp, name);
234     }
235     atts++;
236   }
237   puttc(T('>'), fp);
238 }
239
240 static void XMLCALL
241 endElementNS(void *userData, const XML_Char *name)
242 {
243   FILE *fp = (FILE *)userData;
244   const XML_Char *sep;
245   puttc(T('<'), fp);
246   puttc(T('/'), fp);
247   sep = tcsrchr(name, NSSEP);
248   if (sep) {
249     fputts(T("n1:"), fp);
250     fputts(sep + 1, fp);
251   }
252   else
253     fputts(name, fp);
254   puttc(T('>'), fp);
255 }
256
257 #ifndef W3C14N
258
259 static void XMLCALL
260 processingInstruction(void *userData, const XML_Char *target,
261                       const XML_Char *data)
262 {
263   FILE *fp = (FILE *)userData;
264   puttc(T('<'), fp);
265   puttc(T('?'), fp);
266   fputts(target, fp);
267   puttc(T(' '), fp);
268   fputts(data, fp);
269   puttc(T('?'), fp);
270   puttc(T('>'), fp);
271 }
272
273 #endif /* not W3C14N */
274
275 static void XMLCALL
276 defaultCharacterData(void *userData, const XML_Char *UNUSED_P(s), int UNUSED_P(len))
277 {
278   XML_DefaultCurrent((XML_Parser) userData);
279 }
280
281 static void XMLCALL
282 defaultStartElement(void *userData, const XML_Char *UNUSED_P(name),
283                     const XML_Char **UNUSED_P(atts))
284 {
285   XML_DefaultCurrent((XML_Parser) userData);
286 }
287
288 static void XMLCALL
289 defaultEndElement(void *userData, const XML_Char *UNUSED_P(name))
290 {
291   XML_DefaultCurrent((XML_Parser) userData);
292 }
293
294 static void XMLCALL
295 defaultProcessingInstruction(void *userData, const XML_Char *UNUSED_P(target),
296                              const XML_Char *UNUSED_P(data))
297 {
298   XML_DefaultCurrent((XML_Parser) userData);
299 }
300
301 static void XMLCALL
302 nopCharacterData(void *UNUSED_P(userData), const XML_Char *UNUSED_P(s), int UNUSED_P(len))
303 {
304 }
305
306 static void XMLCALL
307 nopStartElement(void *UNUSED_P(userData), const XML_Char *UNUSED_P(name), const XML_Char **UNUSED_P(atts))
308 {
309 }
310
311 static void XMLCALL
312 nopEndElement(void *UNUSED_P(userData), const XML_Char *UNUSED_P(name))
313 {
314 }
315
316 static void XMLCALL
317 nopProcessingInstruction(void *UNUSED_P(userData), const XML_Char *UNUSED_P(target),
318                          const XML_Char *UNUSED_P(data))
319 {
320 }
321
322 static void XMLCALL
323 markup(void *userData, const XML_Char *s, int len)
324 {
325   FILE *fp = (FILE *)XML_GetUserData((XML_Parser) userData);
326   for (; len > 0; --len, ++s)
327     puttc(*s, fp);
328 }
329
330 static void
331 metaLocation(XML_Parser parser)
332 {
333   const XML_Char *uri = XML_GetBase(parser);
334   if (uri)
335     ftprintf((FILE *)XML_GetUserData(parser), T(" uri=\"%s\""), uri);
336   ftprintf((FILE *)XML_GetUserData(parser),
337            T(" byte=\"%" XML_FMT_INT_MOD "d\" nbytes=\"%d\" \
338                          line=\"%" XML_FMT_INT_MOD "u\" col=\"%" XML_FMT_INT_MOD "u\""),
339            XML_GetCurrentByteIndex(parser),
340            XML_GetCurrentByteCount(parser),
341            XML_GetCurrentLineNumber(parser),
342            XML_GetCurrentColumnNumber(parser));
343 }
344
345 static void
346 metaStartDocument(void *userData)
347 {
348   fputts(T("<document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
349 }
350
351 static void
352 metaEndDocument(void *userData)
353 {
354   fputts(T("</document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
355 }
356
357 static void XMLCALL
358 metaStartElement(void *userData, const XML_Char *name,
359                  const XML_Char **atts)
360 {
361   XML_Parser parser = (XML_Parser) userData;
362   FILE *fp = (FILE *)XML_GetUserData(parser);
363   const XML_Char **specifiedAttsEnd
364     = atts + XML_GetSpecifiedAttributeCount(parser);
365   const XML_Char **idAttPtr;
366   int idAttIndex = XML_GetIdAttributeIndex(parser);
367   if (idAttIndex < 0)
368     idAttPtr = 0;
369   else
370     idAttPtr = atts + idAttIndex;
371     
372   ftprintf(fp, T("<starttag name=\"%s\""), name);
373   metaLocation(parser);
374   if (*atts) {
375     fputts(T(">\n"), fp);
376     do {
377       ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
378       characterData(fp, atts[1], (int)tcslen(atts[1]));
379       if (atts >= specifiedAttsEnd)
380         fputts(T("\" defaulted=\"yes\"/>\n"), fp);
381       else if (atts == idAttPtr)
382         fputts(T("\" id=\"yes\"/>\n"), fp);
383       else
384         fputts(T("\"/>\n"), fp);
385     } while (*(atts += 2));
386     fputts(T("</starttag>\n"), fp);
387   }
388   else
389     fputts(T("/>\n"), fp);
390 }
391
392 static void XMLCALL
393 metaEndElement(void *userData, const XML_Char *name)
394 {
395   XML_Parser parser = (XML_Parser) userData;
396   FILE *fp = (FILE *)XML_GetUserData(parser);
397   ftprintf(fp, T("<endtag name=\"%s\""), name);
398   metaLocation(parser);
399   fputts(T("/>\n"), fp);
400 }
401
402 static void XMLCALL
403 metaProcessingInstruction(void *userData, const XML_Char *target,
404                           const XML_Char *data)
405 {
406   XML_Parser parser = (XML_Parser) userData;
407   FILE *fp = (FILE *)XML_GetUserData(parser);
408   ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
409   characterData(fp, data, (int)tcslen(data));
410   puttc(T('"'), fp);
411   metaLocation(parser);
412   fputts(T("/>\n"), fp);
413 }
414
415 static void XMLCALL
416 metaComment(void *userData, const XML_Char *data)
417 {
418   XML_Parser parser = (XML_Parser) userData;
419   FILE *fp = (FILE *)XML_GetUserData(parser);
420   fputts(T("<comment data=\""), fp);
421   characterData(fp, data, (int)tcslen(data));
422   puttc(T('"'), fp);
423   metaLocation(parser);
424   fputts(T("/>\n"), fp);
425 }
426
427 static void XMLCALL
428 metaStartCdataSection(void *userData)
429 {
430   XML_Parser parser = (XML_Parser) userData;
431   FILE *fp = (FILE *)XML_GetUserData(parser);
432   fputts(T("<startcdata"), fp);
433   metaLocation(parser);
434   fputts(T("/>\n"), fp);
435 }
436
437 static void XMLCALL
438 metaEndCdataSection(void *userData)
439 {
440   XML_Parser parser = (XML_Parser) userData;
441   FILE *fp = (FILE *)XML_GetUserData(parser);
442   fputts(T("<endcdata"), fp);
443   metaLocation(parser);
444   fputts(T("/>\n"), fp);
445 }
446
447 static void XMLCALL
448 metaCharacterData(void *userData, const XML_Char *s, int len)
449 {
450   XML_Parser parser = (XML_Parser) userData;
451   FILE *fp = (FILE *)XML_GetUserData(parser);
452   fputts(T("<chars str=\""), fp);
453   characterData(fp, s, len);
454   puttc(T('"'), fp);
455   metaLocation(parser);
456   fputts(T("/>\n"), fp);
457 }
458
459 static void XMLCALL
460 metaStartDoctypeDecl(void *userData,
461                      const XML_Char *doctypeName,
462                      const XML_Char *UNUSED_P(sysid),
463                      const XML_Char *UNUSED_P(pubid),
464                      int UNUSED_P(has_internal_subset))
465 {
466   XML_Parser parser = (XML_Parser) userData;
467   FILE *fp = (FILE *)XML_GetUserData(parser);
468   ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
469   metaLocation(parser);
470   fputts(T("/>\n"), fp);
471 }
472
473 static void XMLCALL
474 metaEndDoctypeDecl(void *userData)
475 {
476   XML_Parser parser = (XML_Parser) userData;
477   FILE *fp = (FILE *)XML_GetUserData(parser);
478   fputts(T("<enddoctype"), fp);
479   metaLocation(parser);
480   fputts(T("/>\n"), fp);
481 }
482
483 static void XMLCALL
484 metaNotationDecl(void *userData,
485                  const XML_Char *notationName,
486                  const XML_Char *UNUSED_P(base),
487                  const XML_Char *systemId,
488                  const XML_Char *publicId)
489 {
490   XML_Parser parser = (XML_Parser) userData;
491   FILE *fp = (FILE *)XML_GetUserData(parser);
492   ftprintf(fp, T("<notation name=\"%s\""), notationName);
493   if (publicId)
494     ftprintf(fp, T(" public=\"%s\""), publicId);
495   if (systemId) {
496     fputts(T(" system=\""), fp);
497     characterData(fp, systemId, (int)tcslen(systemId));
498     puttc(T('"'), fp);
499   }
500   metaLocation(parser);
501   fputts(T("/>\n"), fp);
502 }
503
504
505 static void XMLCALL
506 metaEntityDecl(void *userData,
507                const XML_Char *entityName,
508                int  UNUSED_P(is_param),
509                const XML_Char *value,
510                int  value_length,
511                const XML_Char *UNUSED_P(base),
512                const XML_Char *systemId,
513                const XML_Char *publicId,
514                const XML_Char *notationName)
515 {
516   XML_Parser parser = (XML_Parser) userData;
517   FILE *fp = (FILE *)XML_GetUserData(parser);
518
519   if (value) {
520     ftprintf(fp, T("<entity name=\"%s\""), entityName);
521     metaLocation(parser);
522     puttc(T('>'), fp);
523     characterData(fp, value, value_length);
524     fputts(T("</entity/>\n"), fp);
525   }
526   else if (notationName) {
527     ftprintf(fp, T("<entity name=\"%s\""), entityName);
528     if (publicId)
529       ftprintf(fp, T(" public=\"%s\""), publicId);
530     fputts(T(" system=\""), fp);
531     characterData(fp, systemId, (int)tcslen(systemId));
532     puttc(T('"'), fp);
533     ftprintf(fp, T(" notation=\"%s\""), notationName);
534     metaLocation(parser);
535     fputts(T("/>\n"), fp);
536   }
537   else {
538     ftprintf(fp, T("<entity name=\"%s\""), entityName);
539     if (publicId)
540       ftprintf(fp, T(" public=\"%s\""), publicId);
541     fputts(T(" system=\""), fp);
542     characterData(fp, systemId, (int)tcslen(systemId));
543     puttc(T('"'), fp);
544     metaLocation(parser);
545     fputts(T("/>\n"), fp);
546   }
547 }
548
549 static void XMLCALL
550 metaStartNamespaceDecl(void *userData,
551                        const XML_Char *prefix,
552                        const XML_Char *uri)
553 {
554   XML_Parser parser = (XML_Parser) userData;
555   FILE *fp = (FILE *)XML_GetUserData(parser);
556   fputts(T("<startns"), fp);
557   if (prefix)
558     ftprintf(fp, T(" prefix=\"%s\""), prefix);
559   if (uri) {
560     fputts(T(" ns=\""), fp);
561     characterData(fp, uri, (int)tcslen(uri));
562     fputts(T("\"/>\n"), fp);
563   }
564   else
565     fputts(T("/>\n"), fp);
566 }
567
568 static void XMLCALL
569 metaEndNamespaceDecl(void *userData, const XML_Char *prefix)
570 {
571   XML_Parser parser = (XML_Parser) userData;
572   FILE *fp = (FILE *)XML_GetUserData(parser);
573   if (!prefix)
574     fputts(T("<endns/>\n"), fp);
575   else
576     ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
577 }
578
579 static int XMLCALL
580 unknownEncodingConvert(void *data, const char *p)
581 {
582   return codepageConvert(*(int *)data, p);
583 }
584
585 static int XMLCALL
586 unknownEncoding(void *UNUSED_P(userData), const XML_Char *name, XML_Encoding *info)
587 {
588   int cp;
589   static const XML_Char prefixL[] = T("windows-");
590   static const XML_Char prefixU[] = T("WINDOWS-");
591   int i;
592
593   for (i = 0; prefixU[i]; i++)
594     if (name[i] != prefixU[i] && name[i] != prefixL[i])
595       return 0;
596   
597   cp = 0;
598   for (; name[i]; i++) {
599     static const XML_Char digits[] = T("0123456789");
600     const XML_Char *s = tcschr(digits, name[i]);
601     if (!s)
602       return 0;
603     cp *= 10;
604     cp += (int)(s - digits);
605     if (cp >= 0x10000)
606       return 0;
607   }
608   if (!codepageMap(cp, info->map))
609     return 0;
610   info->convert = unknownEncodingConvert;
611   /* We could just cast the code page integer to a void *,
612   and avoid the use of release. */
613   info->release = free;
614   info->data = malloc(sizeof(int));
615   if (!info->data)
616     return 0;
617   *(int *)info->data = cp;
618   return 1;
619 }
620
621 static int XMLCALL
622 notStandalone(void *UNUSED_P(userData))
623 {
624   return 0;
625 }
626
627 static void
628 showVersion(XML_Char *prog)
629 {
630   XML_Char *s = prog;
631   XML_Char ch;
632   const XML_Feature *features = XML_GetFeatureList();
633   while ((ch = *s) != 0) {
634     if (ch == '/'
635 #if defined(_WIN32)
636         || ch == '\\'
637 #endif
638         )
639       prog = s + 1;
640     ++s;
641   }
642   ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion());
643   if (features != NULL && features[0].feature != XML_FEATURE_END) {
644     int i = 1;
645     ftprintf(stdout, T("%s"), features[0].name);
646     if (features[0].value)
647       ftprintf(stdout, T("=%ld"), features[0].value);
648     while (features[i].feature != XML_FEATURE_END) {
649       ftprintf(stdout, T(", %s"), features[i].name);
650       if (features[i].value)
651         ftprintf(stdout, T("=%ld"), features[i].value);
652       ++i;
653     }
654     ftprintf(stdout, T("\n"));
655   }
656 }
657
658 static void
659 usage(const XML_Char *prog, int rc)
660 {
661   ftprintf(stderr,
662            T("usage: %s [-s] [-n] [-p] [-x] [-e encoding] [-w] [-d output-dir] [-c] [-m] [-r] [-t] [file ...]\n"), prog);
663   exit(rc);
664 }
665
666 int
667 tmain(int argc, XML_Char **argv)
668 {
669   int i, j;
670   const XML_Char *outputDir = NULL;
671   const XML_Char *encoding = NULL;
672   unsigned processFlags = XML_MAP_FILE;
673   int windowsCodePages = 0;
674   int outputType = 0;
675   int useNamespaces = 0;
676   int requireStandalone = 0;
677   enum XML_ParamEntityParsing paramEntityParsing = 
678     XML_PARAM_ENTITY_PARSING_NEVER;
679   int useStdin = 0;
680
681 #ifdef _MSC_VER
682   _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
683 #endif
684
685   i = 1;
686   j = 0;
687   while (i < argc) {
688     if (j == 0) {
689       if (argv[i][0] != T('-'))
690         break;
691       if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
692         i++;
693         break;
694       }
695       j++;
696     }
697     switch (argv[i][j]) {
698     case T('r'):
699       processFlags &= ~XML_MAP_FILE;
700       j++;
701       break;
702     case T('s'):
703       requireStandalone = 1;
704       j++;
705       break;
706     case T('n'):
707       useNamespaces = 1;
708       j++;
709       break;
710     case T('p'):
711       paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
712       /* fall through */
713     case T('x'):
714       processFlags |= XML_EXTERNAL_ENTITIES;
715       j++;
716       break;
717     case T('w'):
718       windowsCodePages = 1;
719       j++;
720       break;
721     case T('m'):
722       outputType = 'm';
723       j++;
724       break;
725     case T('c'):
726       outputType = 'c';
727       useNamespaces = 0;
728       j++;
729       break;
730     case T('t'):
731       outputType = 't';
732       j++;
733       break;
734     case T('d'):
735       if (argv[i][j + 1] == T('\0')) {
736         if (++i == argc)
737           usage(argv[0], 2);
738         outputDir = argv[i];
739       }
740       else
741         outputDir = argv[i] + j + 1;
742       i++;
743       j = 0;
744       break;
745     case T('e'):
746       if (argv[i][j + 1] == T('\0')) {
747         if (++i == argc)
748           usage(argv[0], 2);
749         encoding = argv[i];
750       }
751       else
752         encoding = argv[i] + j + 1;
753       i++;
754       j = 0;
755       break;
756     case T('h'):
757       usage(argv[0], 0);
758       return 0;
759     case T('v'):
760       showVersion(argv[0]);
761       return 0;
762     case T('\0'):
763       if (j > 1) {
764         i++;
765         j = 0;
766         break;
767       }
768       /* fall through */
769     default:
770       usage(argv[0], 2);
771     }
772   }
773   if (i == argc) {
774     useStdin = 1;
775     processFlags &= ~XML_MAP_FILE;
776     i--;
777   }
778   for (; i < argc; i++) {
779     FILE *fp = 0;
780     XML_Char *outName = 0;
781     int result;
782     XML_Parser parser;
783     if (useNamespaces)
784       parser = XML_ParserCreateNS(encoding, NSSEP);
785     else
786       parser = XML_ParserCreate(encoding);
787
788     if (! parser) {
789       tperror("Could not instantiate parser");
790       exit(1);
791     }
792
793     if (requireStandalone)
794       XML_SetNotStandaloneHandler(parser, notStandalone);
795     XML_SetParamEntityParsing(parser, paramEntityParsing);
796     if (outputType == 't') {
797       /* This is for doing timings; this gives a more realistic estimate of
798          the parsing time. */
799       outputDir = 0;
800       XML_SetElementHandler(parser, nopStartElement, nopEndElement);
801       XML_SetCharacterDataHandler(parser, nopCharacterData);
802       XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
803     }
804     else if (outputDir) {
805       const XML_Char * delim = T("/");
806       const XML_Char *file = useStdin ? T("STDIN") : argv[i];
807       if (!useStdin) {
808         /* Jump after last (back)slash */
809         const XML_Char * lastDelim = tcsrchr(file, delim[0]);
810         if (lastDelim)
811           file = lastDelim + 1;
812 #if defined(_WIN32)
813         else {
814           const XML_Char * winDelim = T("\\");
815           lastDelim = tcsrchr(file, winDelim[0]);
816           if (lastDelim) {
817             file = lastDelim + 1;
818             delim = winDelim;
819           }
820         }
821 #endif
822       }
823       outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2)
824                        * sizeof(XML_Char));
825       tcscpy(outName, outputDir);
826       tcscat(outName, delim);
827       tcscat(outName, file);
828       fp = tfopen(outName, T("wb"));
829       if (!fp) {
830         tperror(outName);
831         exit(1);
832       }
833       setvbuf(fp, NULL, _IOFBF, 16384);
834 #ifdef XML_UNICODE
835       puttc(0xFEFF, fp);
836 #endif
837       XML_SetUserData(parser, fp);
838       switch (outputType) {
839       case 'm':
840         XML_UseParserAsHandlerArg(parser);
841         XML_SetElementHandler(parser, metaStartElement, metaEndElement);
842         XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
843         XML_SetCommentHandler(parser, metaComment);
844         XML_SetCdataSectionHandler(parser, metaStartCdataSection,
845                                    metaEndCdataSection);
846         XML_SetCharacterDataHandler(parser, metaCharacterData);
847         XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
848                                   metaEndDoctypeDecl);
849         XML_SetEntityDeclHandler(parser, metaEntityDecl);
850         XML_SetNotationDeclHandler(parser, metaNotationDecl);
851         XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
852                                     metaEndNamespaceDecl);
853         metaStartDocument(parser);
854         break;
855       case 'c':
856         XML_UseParserAsHandlerArg(parser);
857         XML_SetDefaultHandler(parser, markup);
858         XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
859         XML_SetCharacterDataHandler(parser, defaultCharacterData);
860         XML_SetProcessingInstructionHandler(parser,
861                                             defaultProcessingInstruction);
862         break;
863       default:
864         if (useNamespaces)
865           XML_SetElementHandler(parser, startElementNS, endElementNS);
866         else
867           XML_SetElementHandler(parser, startElement, endElement);
868         XML_SetCharacterDataHandler(parser, characterData);
869 #ifndef W3C14N
870         XML_SetProcessingInstructionHandler(parser, processingInstruction);
871 #endif /* not W3C14N */
872         break;
873       }
874     }
875     if (windowsCodePages)
876       XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
877     result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
878     if (outputDir) {
879       if (outputType == 'm')
880         metaEndDocument(parser);
881       fclose(fp);
882       if (!result) {
883         tremove(outName);
884         exit(2);
885       }
886       free(outName);
887     }
888     XML_ParserFree(parser);
889   }
890   return 0;
891 }