core/expat-2.0.1/xmlwf/xmlwf.c
changeset 300 b6d834208d33
parent 296 ea3dbc023c80
equal deleted inserted replaced
299:f06c5eba524d 300:b6d834208d33
       
     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 }