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