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