Home | History | Annotate | Download | only in xmlwf
      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 #if defined(__amigaos__) && defined(__USE_INLINE__)
     20 #include <proto/expat.h>
     21 #endif
     22 
     23 /* This ensures proper sorting. */
     24 
     25 #define NSSEP T('\001')
     26 
     27 static void XMLCALL
     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
     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
    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
    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 = (int)((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
    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
    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
    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 = (int)((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
    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
    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
    251 defaultCharacterData(void *userData, const XML_Char *s, int len)
    252 {
    253   XML_DefaultCurrent((XML_Parser) userData);
    254 }
    255 
    256 static void XMLCALL
    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
    264 defaultEndElement(void *userData, const XML_Char *name)
    265 {
    266   XML_DefaultCurrent((XML_Parser) userData);
    267 }
    268 
    269 static void XMLCALL
    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
    277 nopCharacterData(void *userData, const XML_Char *s, int len)
    278 {
    279 }
    280 
    281 static void XMLCALL
    282 nopStartElement(void *userData, const XML_Char *name, const XML_Char **atts)
    283 {
    284 }
    285 
    286 static void XMLCALL
    287 nopEndElement(void *userData, const XML_Char *name)
    288 {
    289 }
    290 
    291 static void XMLCALL
    292 nopProcessingInstruction(void *userData, const XML_Char *target,
    293                          const XML_Char *data)
    294 {
    295 }
    296 
    297 static void XMLCALL
    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
    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
    321 metaStartDocument(void *userData)
    322 {
    323   fputts(T("<document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
    324 }
    325 
    326 static void
    327 metaEndDocument(void *userData)
    328 {
    329   fputts(T("</document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
    330 }
    331 
    332 static void XMLCALL
    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], (int)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
    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
    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, (int)tcslen(data));
    385   puttc(T('"'), fp);
    386   metaLocation(parser);
    387   fputts(T("/>\n"), fp);
    388 }
    389 
    390 static void XMLCALL
    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, (int)tcslen(data));
    397   puttc(T('"'), fp);
    398   metaLocation(parser);
    399   fputts(T("/>\n"), fp);
    400 }
    401 
    402 static void XMLCALL
    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
    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
    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
    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
    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
    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, (int)tcslen(systemId));
    473     puttc(T('"'), fp);
    474   }
    475   metaLocation(parser);
    476   fputts(T("/>\n"), fp);
    477 }
    478 
    479 
    480 static void XMLCALL
    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, (int)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, (int)tcslen(systemId));
    518     puttc(T('"'), fp);
    519     metaLocation(parser);
    520     fputts(T("/>\n"), fp);
    521   }
    522 }
    523 
    524 static void XMLCALL
    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, (int)tcslen(uri));
    537     fputts(T("\"/>\n"), fp);
    538   }
    539   else
    540     fputts(T("/>\n"), fp);
    541 }
    542 
    543 static void XMLCALL
    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
    555 unknownEncodingConvert(void *data, const char *p)
    556 {
    557   return codepageConvert(*(int *)data, p);
    558 }
    559 
    560 static int XMLCALL
    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 += (int)(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
    597 notStandalone(void *userData)
    598 {
    599   return 0;
    600 }
    601 
    602 static void
    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 #if (defined(WIN32) || defined(__WATCOMC__))
    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
    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 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     if (requireStandalone)
    764       XML_SetNotStandaloneHandler(parser, notStandalone);
    765     XML_SetParamEntityParsing(parser, paramEntityParsing);
    766     if (outputType == 't') {
    767       /* This is for doing timings; this gives a more realistic estimate of
    768          the parsing time. */
    769       outputDir = 0;
    770       XML_SetElementHandler(parser, nopStartElement, nopEndElement);
    771       XML_SetCharacterDataHandler(parser, nopCharacterData);
    772       XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
    773     }
    774     else if (outputDir) {
    775       const XML_Char * delim = T("/");
    776       const XML_Char *file = useStdin ? T("STDIN") : argv[i];
    777       if (!useStdin) {
    778         /* Jump after last (back)slash */
    779         const XML_Char * lastDelim = tcsrchr(file, delim[0]);
    780         if (lastDelim)
    781           file = lastDelim + 1;
    782 #if (defined(WIN32) || defined(__WATCOMC__))
    783         else {
    784           const XML_Char * winDelim = T("\\");
    785           lastDelim = tcsrchr(file, winDelim[0]);
    786           if (lastDelim) {
    787             file = lastDelim + 1;
    788             delim = winDelim;
    789           }
    790         }
    791 #endif
    792       }
    793       outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2)
    794                        * sizeof(XML_Char));
    795       tcscpy(outName, outputDir);
    796       tcscat(outName, delim);
    797       tcscat(outName, file);
    798       fp = tfopen(outName, T("wb"));
    799       if (!fp) {
    800         tperror(outName);
    801         exit(1);
    802       }
    803       setvbuf(fp, NULL, _IOFBF, 16384);
    804 #ifdef XML_UNICODE
    805       puttc(0xFEFF, fp);
    806 #endif
    807       XML_SetUserData(parser, fp);
    808       switch (outputType) {
    809       case 'm':
    810         XML_UseParserAsHandlerArg(parser);
    811         XML_SetElementHandler(parser, metaStartElement, metaEndElement);
    812         XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
    813         XML_SetCommentHandler(parser, metaComment);
    814         XML_SetCdataSectionHandler(parser, metaStartCdataSection,
    815                                    metaEndCdataSection);
    816         XML_SetCharacterDataHandler(parser, metaCharacterData);
    817         XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
    818                                   metaEndDoctypeDecl);
    819         XML_SetEntityDeclHandler(parser, metaEntityDecl);
    820         XML_SetNotationDeclHandler(parser, metaNotationDecl);
    821         XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
    822                                     metaEndNamespaceDecl);
    823         metaStartDocument(parser);
    824         break;
    825       case 'c':
    826         XML_UseParserAsHandlerArg(parser);
    827         XML_SetDefaultHandler(parser, markup);
    828         XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
    829         XML_SetCharacterDataHandler(parser, defaultCharacterData);
    830         XML_SetProcessingInstructionHandler(parser,
    831                                             defaultProcessingInstruction);
    832         break;
    833       default:
    834         if (useNamespaces)
    835           XML_SetElementHandler(parser, startElementNS, endElementNS);
    836         else
    837           XML_SetElementHandler(parser, startElement, endElement);
    838         XML_SetCharacterDataHandler(parser, characterData);
    839 #ifndef W3C14N
    840         XML_SetProcessingInstructionHandler(parser, processingInstruction);
    841 #endif /* not W3C14N */
    842         break;
    843       }
    844     }
    845     if (windowsCodePages)
    846       XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
    847     result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
    848     if (outputDir) {
    849       if (outputType == 'm')
    850         metaEndDocument(parser);
    851       fclose(fp);
    852       if (!result)
    853         tremove(outName);
    854       free(outName);
    855     }
    856     XML_ParserFree(parser);
    857   }
    858   return 0;
    859 }
    860