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