Home | History | Annotate | Line # | Download | only in xmlwf
xmlwf.c revision 1.1.1.3.4.1
      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