Home | History | Annotate | Line # | Download | only in xmlwf
xmlwf.c revision 1.1.1.5.6.1
      1  1.1.1.5.6.1    martin /*
      2  1.1.1.5.6.1    martin                             __  __            _
      3  1.1.1.5.6.1    martin                          ___\ \/ /_ __   __ _| |_
      4  1.1.1.5.6.1    martin                         / _ \\  /| '_ \ / _` | __|
      5  1.1.1.5.6.1    martin                        |  __//  \| |_) | (_| | |_
      6  1.1.1.5.6.1    martin                         \___/_/\_\ .__/ \__,_|\__|
      7  1.1.1.5.6.1    martin                                  |_| XML parser
      8  1.1.1.5.6.1    martin 
      9  1.1.1.5.6.1    martin    Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
     10  1.1.1.5.6.1    martin    Copyright (c) 2000-2017 Expat development team
     11  1.1.1.5.6.1    martin    Licensed under the MIT license:
     12  1.1.1.5.6.1    martin 
     13  1.1.1.5.6.1    martin    Permission is  hereby granted,  free of charge,  to any  person obtaining
     14  1.1.1.5.6.1    martin    a  copy  of  this  software   and  associated  documentation  files  (the
     15  1.1.1.5.6.1    martin    "Software"),  to  deal in  the  Software  without restriction,  including
     16  1.1.1.5.6.1    martin    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
     17  1.1.1.5.6.1    martin    distribute, sublicense, and/or sell copies of the Software, and to permit
     18  1.1.1.5.6.1    martin    persons  to whom  the Software  is  furnished to  do so,  subject to  the
     19  1.1.1.5.6.1    martin    following conditions:
     20  1.1.1.5.6.1    martin 
     21  1.1.1.5.6.1    martin    The above copyright  notice and this permission notice  shall be included
     22  1.1.1.5.6.1    martin    in all copies or substantial portions of the Software.
     23  1.1.1.5.6.1    martin 
     24  1.1.1.5.6.1    martin    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
     25  1.1.1.5.6.1    martin    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
     26  1.1.1.5.6.1    martin    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
     27  1.1.1.5.6.1    martin    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
     28  1.1.1.5.6.1    martin    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
     29  1.1.1.5.6.1    martin    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     30  1.1.1.5.6.1    martin    USE OR OTHER DEALINGS IN THE SOFTWARE.
     31          1.1      tron */
     32          1.1      tron 
     33  1.1.1.5.6.1    martin #include <assert.h>
     34          1.1      tron #include <stdio.h>
     35          1.1      tron #include <stdlib.h>
     36          1.1      tron #include <stddef.h>
     37          1.1      tron #include <string.h>
     38          1.1      tron 
     39          1.1      tron #include "expat.h"
     40          1.1      tron #include "codepage.h"
     41  1.1.1.5.6.1    martin #include "internal.h" /* for UNUSED_P only */
     42          1.1      tron #include "xmlfile.h"
     43          1.1      tron #include "xmltchar.h"
     44          1.1      tron 
     45          1.1      tron #ifdef _MSC_VER
     46  1.1.1.5.6.1    martin #  include <crtdbg.h>
     47          1.1      tron #endif
     48          1.1      tron 
     49  1.1.1.5.6.1    martin #ifdef XML_UNICODE
     50  1.1.1.5.6.1    martin #  include <wchar.h>
     51  1.1.1.5.6.1    martin #endif
     52  1.1.1.5.6.1    martin 
     53  1.1.1.5.6.1    martin /* Structures for handler user data */
     54  1.1.1.5.6.1    martin typedef struct NotationList {
     55  1.1.1.5.6.1    martin   struct NotationList *next;
     56  1.1.1.5.6.1    martin   const XML_Char *notationName;
     57  1.1.1.5.6.1    martin   const XML_Char *systemId;
     58  1.1.1.5.6.1    martin   const XML_Char *publicId;
     59  1.1.1.5.6.1    martin } NotationList;
     60  1.1.1.5.6.1    martin 
     61  1.1.1.5.6.1    martin typedef struct xmlwfUserData {
     62  1.1.1.5.6.1    martin   FILE *fp;
     63  1.1.1.5.6.1    martin   NotationList *notationListHead;
     64  1.1.1.5.6.1    martin   const XML_Char *currentDoctypeName;
     65  1.1.1.5.6.1    martin } XmlwfUserData;
     66  1.1.1.5.6.1    martin 
     67          1.1      tron /* This ensures proper sorting. */
     68          1.1      tron 
     69          1.1      tron #define NSSEP T('\001')
     70          1.1      tron 
     71          1.1      tron static void XMLCALL
     72  1.1.1.5.6.1    martin characterData(void *userData, const XML_Char *s, int len) {
     73  1.1.1.5.6.1    martin   FILE *fp = ((XmlwfUserData *)userData)->fp;
     74          1.1      tron   for (; len > 0; --len, ++s) {
     75          1.1      tron     switch (*s) {
     76          1.1      tron     case T('&'):
     77          1.1      tron       fputts(T("&amp;"), fp);
     78          1.1      tron       break;
     79          1.1      tron     case T('<'):
     80          1.1      tron       fputts(T("&lt;"), fp);
     81          1.1      tron       break;
     82          1.1      tron     case T('>'):
     83          1.1      tron       fputts(T("&gt;"), fp);
     84          1.1      tron       break;
     85          1.1      tron #ifdef W3C14N
     86          1.1      tron     case 13:
     87          1.1      tron       fputts(T("&#xD;"), fp);
     88          1.1      tron       break;
     89          1.1      tron #else
     90          1.1      tron     case T('"'):
     91          1.1      tron       fputts(T("&quot;"), fp);
     92          1.1      tron       break;
     93          1.1      tron     case 9:
     94          1.1      tron     case 10:
     95          1.1      tron     case 13:
     96          1.1      tron       ftprintf(fp, T("&#%d;"), *s);
     97          1.1      tron       break;
     98          1.1      tron #endif
     99          1.1      tron     default:
    100          1.1      tron       puttc(*s, fp);
    101          1.1      tron       break;
    102          1.1      tron     }
    103          1.1      tron   }
    104          1.1      tron }
    105          1.1      tron 
    106          1.1      tron static void
    107  1.1.1.5.6.1    martin attributeValue(FILE *fp, const XML_Char *s) {
    108          1.1      tron   puttc(T('='), fp);
    109          1.1      tron   puttc(T('"'), fp);
    110  1.1.1.5.6.1    martin   assert(s);
    111          1.1      tron   for (;;) {
    112          1.1      tron     switch (*s) {
    113          1.1      tron     case 0:
    114          1.1      tron     case NSSEP:
    115          1.1      tron       puttc(T('"'), fp);
    116          1.1      tron       return;
    117          1.1      tron     case T('&'):
    118          1.1      tron       fputts(T("&amp;"), fp);
    119          1.1      tron       break;
    120          1.1      tron     case T('<'):
    121          1.1      tron       fputts(T("&lt;"), fp);
    122          1.1      tron       break;
    123          1.1      tron     case T('"'):
    124          1.1      tron       fputts(T("&quot;"), fp);
    125          1.1      tron       break;
    126          1.1      tron #ifdef W3C14N
    127          1.1      tron     case 9:
    128          1.1      tron       fputts(T("&#x9;"), fp);
    129          1.1      tron       break;
    130          1.1      tron     case 10:
    131          1.1      tron       fputts(T("&#xA;"), fp);
    132          1.1      tron       break;
    133          1.1      tron     case 13:
    134          1.1      tron       fputts(T("&#xD;"), fp);
    135          1.1      tron       break;
    136          1.1      tron #else
    137          1.1      tron     case T('>'):
    138          1.1      tron       fputts(T("&gt;"), fp);
    139          1.1      tron       break;
    140          1.1      tron     case 9:
    141          1.1      tron     case 10:
    142          1.1      tron     case 13:
    143          1.1      tron       ftprintf(fp, T("&#%d;"), *s);
    144          1.1      tron       break;
    145          1.1      tron #endif
    146          1.1      tron     default:
    147          1.1      tron       puttc(*s, fp);
    148          1.1      tron       break;
    149          1.1      tron     }
    150          1.1      tron     s++;
    151          1.1      tron   }
    152          1.1      tron }
    153          1.1      tron 
    154          1.1      tron /* Lexicographically comparing UTF-8 encoded attribute values,
    155          1.1      tron is equivalent to lexicographically comparing based on the character number. */
    156          1.1      tron 
    157          1.1      tron static int
    158  1.1.1.5.6.1    martin attcmp(const void *att1, const void *att2) {
    159          1.1      tron   return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
    160          1.1      tron }
    161          1.1      tron 
    162          1.1      tron static void XMLCALL
    163  1.1.1.5.6.1    martin startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
    164          1.1      tron   int nAtts;
    165          1.1      tron   const XML_Char **p;
    166  1.1.1.5.6.1    martin   FILE *fp = ((XmlwfUserData *)userData)->fp;
    167          1.1      tron   puttc(T('<'), fp);
    168          1.1      tron   fputts(name, fp);
    169          1.1      tron 
    170          1.1      tron   p = atts;
    171          1.1      tron   while (*p)
    172          1.1      tron     ++p;
    173          1.1      tron   nAtts = (int)((p - atts) >> 1);
    174          1.1      tron   if (nAtts > 1)
    175          1.1      tron     qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
    176          1.1      tron   while (*atts) {
    177          1.1      tron     puttc(T(' '), fp);
    178          1.1      tron     fputts(*atts++, fp);
    179          1.1      tron     attributeValue(fp, *atts);
    180          1.1      tron     atts++;
    181          1.1      tron   }
    182          1.1      tron   puttc(T('>'), fp);
    183          1.1      tron }
    184          1.1      tron 
    185          1.1      tron static void XMLCALL
    186  1.1.1.5.6.1    martin endElement(void *userData, const XML_Char *name) {
    187  1.1.1.5.6.1    martin   FILE *fp = ((XmlwfUserData *)userData)->fp;
    188          1.1      tron   puttc(T('<'), fp);
    189          1.1      tron   puttc(T('/'), fp);
    190          1.1      tron   fputts(name, fp);
    191          1.1      tron   puttc(T('>'), fp);
    192          1.1      tron }
    193          1.1      tron 
    194          1.1      tron static int
    195  1.1.1.5.6.1    martin nsattcmp(const void *p1, const void *p2) {
    196          1.1      tron   const XML_Char *att1 = *(const XML_Char **)p1;
    197          1.1      tron   const XML_Char *att2 = *(const XML_Char **)p2;
    198          1.1      tron   int sep1 = (tcsrchr(att1, NSSEP) != 0);
    199          1.1      tron   int sep2 = (tcsrchr(att1, NSSEP) != 0);
    200          1.1      tron   if (sep1 != sep2)
    201          1.1      tron     return sep1 - sep2;
    202          1.1      tron   return tcscmp(att1, att2);
    203          1.1      tron }
    204          1.1      tron 
    205          1.1      tron static void XMLCALL
    206  1.1.1.5.6.1    martin startElementNS(void *userData, const XML_Char *name, const XML_Char **atts) {
    207          1.1      tron   int nAtts;
    208          1.1      tron   int nsi;
    209          1.1      tron   const XML_Char **p;
    210  1.1.1.5.6.1    martin   FILE *fp = ((XmlwfUserData *)userData)->fp;
    211          1.1      tron   const XML_Char *sep;
    212          1.1      tron   puttc(T('<'), fp);
    213          1.1      tron 
    214          1.1      tron   sep = tcsrchr(name, NSSEP);
    215          1.1      tron   if (sep) {
    216          1.1      tron     fputts(T("n1:"), fp);
    217          1.1      tron     fputts(sep + 1, fp);
    218          1.1      tron     fputts(T(" xmlns:n1"), fp);
    219          1.1      tron     attributeValue(fp, name);
    220          1.1      tron     nsi = 2;
    221  1.1.1.5.6.1    martin   } else {
    222          1.1      tron     fputts(name, fp);
    223          1.1      tron     nsi = 1;
    224          1.1      tron   }
    225          1.1      tron 
    226          1.1      tron   p = atts;
    227          1.1      tron   while (*p)
    228          1.1      tron     ++p;
    229          1.1      tron   nAtts = (int)((p - atts) >> 1);
    230          1.1      tron   if (nAtts > 1)
    231          1.1      tron     qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
    232          1.1      tron   while (*atts) {
    233          1.1      tron     name = *atts++;
    234          1.1      tron     sep = tcsrchr(name, NSSEP);
    235          1.1      tron     puttc(T(' '), fp);
    236          1.1      tron     if (sep) {
    237          1.1      tron       ftprintf(fp, T("n%d:"), nsi);
    238          1.1      tron       fputts(sep + 1, fp);
    239  1.1.1.5.6.1    martin     } else
    240          1.1      tron       fputts(name, fp);
    241          1.1      tron     attributeValue(fp, *atts);
    242          1.1      tron     if (sep) {
    243          1.1      tron       ftprintf(fp, T(" xmlns:n%d"), nsi++);
    244          1.1      tron       attributeValue(fp, name);
    245          1.1      tron     }
    246          1.1      tron     atts++;
    247          1.1      tron   }
    248          1.1      tron   puttc(T('>'), fp);
    249          1.1      tron }
    250          1.1      tron 
    251          1.1      tron static void XMLCALL
    252  1.1.1.5.6.1    martin endElementNS(void *userData, const XML_Char *name) {
    253  1.1.1.5.6.1    martin   FILE *fp = ((XmlwfUserData *)userData)->fp;
    254          1.1      tron   const XML_Char *sep;
    255          1.1      tron   puttc(T('<'), fp);
    256          1.1      tron   puttc(T('/'), fp);
    257          1.1      tron   sep = tcsrchr(name, NSSEP);
    258          1.1      tron   if (sep) {
    259          1.1      tron     fputts(T("n1:"), fp);
    260          1.1      tron     fputts(sep + 1, fp);
    261  1.1.1.5.6.1    martin   } else
    262          1.1      tron     fputts(name, fp);
    263          1.1      tron   puttc(T('>'), fp);
    264          1.1      tron }
    265          1.1      tron 
    266          1.1      tron #ifndef W3C14N
    267          1.1      tron 
    268          1.1      tron static void XMLCALL
    269          1.1      tron processingInstruction(void *userData, const XML_Char *target,
    270  1.1.1.5.6.1    martin                       const XML_Char *data) {
    271  1.1.1.5.6.1    martin   FILE *fp = ((XmlwfUserData *)userData)->fp;
    272          1.1      tron   puttc(T('<'), fp);
    273          1.1      tron   puttc(T('?'), fp);
    274          1.1      tron   fputts(target, fp);
    275          1.1      tron   puttc(T(' '), fp);
    276          1.1      tron   fputts(data, fp);
    277          1.1      tron   puttc(T('?'), fp);
    278          1.1      tron   puttc(T('>'), fp);
    279          1.1      tron }
    280          1.1      tron 
    281  1.1.1.5.6.1    martin static XML_Char *
    282  1.1.1.5.6.1    martin xcsdup(const XML_Char *s) {
    283  1.1.1.5.6.1    martin   XML_Char *result;
    284  1.1.1.5.6.1    martin   int count = 0;
    285  1.1.1.5.6.1    martin   int numBytes;
    286  1.1.1.5.6.1    martin 
    287  1.1.1.5.6.1    martin   /* Get the length of the string, including terminator */
    288  1.1.1.5.6.1    martin   while (s[count++] != 0) {
    289  1.1.1.5.6.1    martin     /* Do nothing */
    290  1.1.1.5.6.1    martin   }
    291  1.1.1.5.6.1    martin   numBytes = count * sizeof(XML_Char);
    292  1.1.1.5.6.1    martin   result = malloc(numBytes);
    293  1.1.1.5.6.1    martin   if (result == NULL)
    294  1.1.1.5.6.1    martin     return NULL;
    295  1.1.1.5.6.1    martin   memcpy(result, s, numBytes);
    296  1.1.1.5.6.1    martin   return result;
    297  1.1.1.5.6.1    martin }
    298  1.1.1.5.6.1    martin 
    299  1.1.1.5.6.1    martin static void XMLCALL
    300  1.1.1.5.6.1    martin startDoctypeDecl(void *userData, const XML_Char *doctypeName,
    301  1.1.1.5.6.1    martin                  const XML_Char *sysid, const XML_Char *publid,
    302  1.1.1.5.6.1    martin                  int has_internal_subset) {
    303  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)userData;
    304  1.1.1.5.6.1    martin   UNUSED_P(sysid);
    305  1.1.1.5.6.1    martin   UNUSED_P(publid);
    306  1.1.1.5.6.1    martin   UNUSED_P(has_internal_subset);
    307  1.1.1.5.6.1    martin   data->currentDoctypeName = xcsdup(doctypeName);
    308  1.1.1.5.6.1    martin }
    309  1.1.1.5.6.1    martin 
    310  1.1.1.5.6.1    martin static void
    311  1.1.1.5.6.1    martin freeNotations(XmlwfUserData *data) {
    312  1.1.1.5.6.1    martin   NotationList *notationListHead = data->notationListHead;
    313  1.1.1.5.6.1    martin 
    314  1.1.1.5.6.1    martin   while (notationListHead != NULL) {
    315  1.1.1.5.6.1    martin     NotationList *next = notationListHead->next;
    316  1.1.1.5.6.1    martin     free((void *)notationListHead->notationName);
    317  1.1.1.5.6.1    martin     free((void *)notationListHead->systemId);
    318  1.1.1.5.6.1    martin     free((void *)notationListHead->publicId);
    319  1.1.1.5.6.1    martin     free(notationListHead);
    320  1.1.1.5.6.1    martin     notationListHead = next;
    321  1.1.1.5.6.1    martin   }
    322  1.1.1.5.6.1    martin   data->notationListHead = NULL;
    323  1.1.1.5.6.1    martin }
    324  1.1.1.5.6.1    martin 
    325  1.1.1.5.6.1    martin static int
    326  1.1.1.5.6.1    martin xcscmp(const XML_Char *xs, const XML_Char *xt) {
    327  1.1.1.5.6.1    martin   while (*xs != 0 && *xt != 0) {
    328  1.1.1.5.6.1    martin     if (*xs < *xt)
    329  1.1.1.5.6.1    martin       return -1;
    330  1.1.1.5.6.1    martin     if (*xs > *xt)
    331  1.1.1.5.6.1    martin       return 1;
    332  1.1.1.5.6.1    martin     xs++;
    333  1.1.1.5.6.1    martin     xt++;
    334  1.1.1.5.6.1    martin   }
    335  1.1.1.5.6.1    martin   if (*xs < *xt)
    336  1.1.1.5.6.1    martin     return -1;
    337  1.1.1.5.6.1    martin   if (*xs > *xt)
    338  1.1.1.5.6.1    martin     return 1;
    339  1.1.1.5.6.1    martin   return 0;
    340  1.1.1.5.6.1    martin }
    341  1.1.1.5.6.1    martin 
    342  1.1.1.5.6.1    martin static int
    343  1.1.1.5.6.1    martin notationCmp(const void *a, const void *b) {
    344  1.1.1.5.6.1    martin   const NotationList *const n1 = *(NotationList **)a;
    345  1.1.1.5.6.1    martin   const NotationList *const n2 = *(NotationList **)b;
    346  1.1.1.5.6.1    martin 
    347  1.1.1.5.6.1    martin   return xcscmp(n1->notationName, n2->notationName);
    348  1.1.1.5.6.1    martin }
    349  1.1.1.5.6.1    martin 
    350  1.1.1.5.6.1    martin static void XMLCALL
    351  1.1.1.5.6.1    martin endDoctypeDecl(void *userData) {
    352  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)userData;
    353  1.1.1.5.6.1    martin   NotationList **notations;
    354  1.1.1.5.6.1    martin   int notationCount = 0;
    355  1.1.1.5.6.1    martin   NotationList *p;
    356  1.1.1.5.6.1    martin   int i;
    357  1.1.1.5.6.1    martin 
    358  1.1.1.5.6.1    martin   /* How many notations do we have? */
    359  1.1.1.5.6.1    martin   for (p = data->notationListHead; p != NULL; p = p->next)
    360  1.1.1.5.6.1    martin     notationCount++;
    361  1.1.1.5.6.1    martin   if (notationCount == 0) {
    362  1.1.1.5.6.1    martin     /* Nothing to report */
    363  1.1.1.5.6.1    martin     free((void *)data->currentDoctypeName);
    364  1.1.1.5.6.1    martin     data->currentDoctypeName = NULL;
    365  1.1.1.5.6.1    martin     return;
    366  1.1.1.5.6.1    martin   }
    367  1.1.1.5.6.1    martin 
    368  1.1.1.5.6.1    martin   notations = malloc(notationCount * sizeof(NotationList *));
    369  1.1.1.5.6.1    martin   if (notations == NULL) {
    370  1.1.1.5.6.1    martin     fprintf(stderr, "Unable to sort notations");
    371  1.1.1.5.6.1    martin     freeNotations(data);
    372  1.1.1.5.6.1    martin     return;
    373  1.1.1.5.6.1    martin   }
    374  1.1.1.5.6.1    martin 
    375  1.1.1.5.6.1    martin   for (p = data->notationListHead, i = 0; i < notationCount; p = p->next, i++) {
    376  1.1.1.5.6.1    martin     notations[i] = p;
    377  1.1.1.5.6.1    martin   }
    378  1.1.1.5.6.1    martin   qsort(notations, notationCount, sizeof(NotationList *), notationCmp);
    379  1.1.1.5.6.1    martin 
    380  1.1.1.5.6.1    martin   /* Output the DOCTYPE header */
    381  1.1.1.5.6.1    martin   fputts(T("<!DOCTYPE "), data->fp);
    382  1.1.1.5.6.1    martin   fputts(data->currentDoctypeName, data->fp);
    383  1.1.1.5.6.1    martin   fputts(T(" [\n"), data->fp);
    384  1.1.1.5.6.1    martin 
    385  1.1.1.5.6.1    martin   /* Now the NOTATIONs */
    386  1.1.1.5.6.1    martin   for (i = 0; i < notationCount; i++) {
    387  1.1.1.5.6.1    martin     fputts(T("<!NOTATION "), data->fp);
    388  1.1.1.5.6.1    martin     fputts(notations[i]->notationName, data->fp);
    389  1.1.1.5.6.1    martin     if (notations[i]->publicId != NULL) {
    390  1.1.1.5.6.1    martin       fputts(T(" PUBLIC '"), data->fp);
    391  1.1.1.5.6.1    martin       fputts(notations[i]->publicId, data->fp);
    392  1.1.1.5.6.1    martin       puttc(T('\''), data->fp);
    393  1.1.1.5.6.1    martin       if (notations[i]->systemId != NULL) {
    394  1.1.1.5.6.1    martin         puttc(T(' '), data->fp);
    395  1.1.1.5.6.1    martin         puttc(T('\''), data->fp);
    396  1.1.1.5.6.1    martin         fputts(notations[i]->systemId, data->fp);
    397  1.1.1.5.6.1    martin         puttc(T('\''), data->fp);
    398  1.1.1.5.6.1    martin       }
    399  1.1.1.5.6.1    martin     } else if (notations[i]->systemId != NULL) {
    400  1.1.1.5.6.1    martin       fputts(T(" SYSTEM '"), data->fp);
    401  1.1.1.5.6.1    martin       fputts(notations[i]->systemId, data->fp);
    402  1.1.1.5.6.1    martin       puttc(T('\''), data->fp);
    403  1.1.1.5.6.1    martin     }
    404  1.1.1.5.6.1    martin     puttc(T('>'), data->fp);
    405  1.1.1.5.6.1    martin     puttc(T('\n'), data->fp);
    406  1.1.1.5.6.1    martin   }
    407  1.1.1.5.6.1    martin 
    408  1.1.1.5.6.1    martin   /* Finally end the DOCTYPE */
    409  1.1.1.5.6.1    martin   fputts(T("]>\n"), data->fp);
    410  1.1.1.5.6.1    martin 
    411  1.1.1.5.6.1    martin   free(notations);
    412  1.1.1.5.6.1    martin   freeNotations(data);
    413  1.1.1.5.6.1    martin   free((void *)data->currentDoctypeName);
    414  1.1.1.5.6.1    martin   data->currentDoctypeName = NULL;
    415  1.1.1.5.6.1    martin }
    416  1.1.1.5.6.1    martin 
    417  1.1.1.5.6.1    martin static void XMLCALL
    418  1.1.1.5.6.1    martin notationDecl(void *userData, const XML_Char *notationName, const XML_Char *base,
    419  1.1.1.5.6.1    martin              const XML_Char *systemId, const XML_Char *publicId) {
    420  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)userData;
    421  1.1.1.5.6.1    martin   NotationList *entry = malloc(sizeof(NotationList));
    422  1.1.1.5.6.1    martin   const char *errorMessage = "Unable to store NOTATION for output\n";
    423  1.1.1.5.6.1    martin 
    424  1.1.1.5.6.1    martin   UNUSED_P(base);
    425  1.1.1.5.6.1    martin   if (entry == NULL) {
    426  1.1.1.5.6.1    martin     fputs(errorMessage, stderr);
    427  1.1.1.5.6.1    martin     return; /* Nothing we can really do about this */
    428  1.1.1.5.6.1    martin   }
    429  1.1.1.5.6.1    martin   entry->notationName = xcsdup(notationName);
    430  1.1.1.5.6.1    martin   if (entry->notationName == NULL) {
    431  1.1.1.5.6.1    martin     fputs(errorMessage, stderr);
    432  1.1.1.5.6.1    martin     free(entry);
    433  1.1.1.5.6.1    martin     return;
    434  1.1.1.5.6.1    martin   }
    435  1.1.1.5.6.1    martin   if (systemId != NULL) {
    436  1.1.1.5.6.1    martin     entry->systemId = xcsdup(systemId);
    437  1.1.1.5.6.1    martin     if (entry->systemId == NULL) {
    438  1.1.1.5.6.1    martin       fputs(errorMessage, stderr);
    439  1.1.1.5.6.1    martin       free((void *)entry->notationName);
    440  1.1.1.5.6.1    martin       free(entry);
    441  1.1.1.5.6.1    martin       return;
    442  1.1.1.5.6.1    martin     }
    443  1.1.1.5.6.1    martin   } else {
    444  1.1.1.5.6.1    martin     entry->systemId = NULL;
    445  1.1.1.5.6.1    martin   }
    446  1.1.1.5.6.1    martin   if (publicId != NULL) {
    447  1.1.1.5.6.1    martin     entry->publicId = xcsdup(publicId);
    448  1.1.1.5.6.1    martin     if (entry->publicId == NULL) {
    449  1.1.1.5.6.1    martin       fputs(errorMessage, stderr);
    450  1.1.1.5.6.1    martin       free((void *)entry->systemId); /* Safe if it's NULL */
    451  1.1.1.5.6.1    martin       free((void *)entry->notationName);
    452  1.1.1.5.6.1    martin       free(entry);
    453  1.1.1.5.6.1    martin       return;
    454  1.1.1.5.6.1    martin     }
    455  1.1.1.5.6.1    martin   } else {
    456  1.1.1.5.6.1    martin     entry->publicId = NULL;
    457  1.1.1.5.6.1    martin   }
    458  1.1.1.5.6.1    martin 
    459  1.1.1.5.6.1    martin   entry->next = data->notationListHead;
    460  1.1.1.5.6.1    martin   data->notationListHead = entry;
    461  1.1.1.5.6.1    martin }
    462  1.1.1.5.6.1    martin 
    463          1.1      tron #endif /* not W3C14N */
    464          1.1      tron 
    465          1.1      tron static void XMLCALL
    466  1.1.1.5.6.1    martin defaultCharacterData(void *userData, const XML_Char *s, int len) {
    467  1.1.1.5.6.1    martin   UNUSED_P(s);
    468  1.1.1.5.6.1    martin   UNUSED_P(len);
    469  1.1.1.5.6.1    martin   XML_DefaultCurrent((XML_Parser)userData);
    470          1.1      tron }
    471          1.1      tron 
    472          1.1      tron static void XMLCALL
    473  1.1.1.5.6.1    martin defaultStartElement(void *userData, const XML_Char *name,
    474  1.1.1.5.6.1    martin                     const XML_Char **atts) {
    475  1.1.1.5.6.1    martin   UNUSED_P(name);
    476  1.1.1.5.6.1    martin   UNUSED_P(atts);
    477  1.1.1.5.6.1    martin   XML_DefaultCurrent((XML_Parser)userData);
    478          1.1      tron }
    479          1.1      tron 
    480          1.1      tron static void XMLCALL
    481  1.1.1.5.6.1    martin defaultEndElement(void *userData, const XML_Char *name) {
    482  1.1.1.5.6.1    martin   UNUSED_P(name);
    483  1.1.1.5.6.1    martin   XML_DefaultCurrent((XML_Parser)userData);
    484          1.1      tron }
    485          1.1      tron 
    486          1.1      tron static void XMLCALL
    487  1.1.1.5.6.1    martin defaultProcessingInstruction(void *userData, const XML_Char *target,
    488  1.1.1.5.6.1    martin                              const XML_Char *data) {
    489  1.1.1.5.6.1    martin   UNUSED_P(target);
    490  1.1.1.5.6.1    martin   UNUSED_P(data);
    491  1.1.1.5.6.1    martin   XML_DefaultCurrent((XML_Parser)userData);
    492          1.1      tron }
    493          1.1      tron 
    494          1.1      tron static void XMLCALL
    495  1.1.1.5.6.1    martin nopCharacterData(void *userData, const XML_Char *s, int len) {
    496  1.1.1.5.6.1    martin   UNUSED_P(userData);
    497  1.1.1.5.6.1    martin   UNUSED_P(s);
    498  1.1.1.5.6.1    martin   UNUSED_P(len);
    499          1.1      tron }
    500          1.1      tron 
    501          1.1      tron static void XMLCALL
    502  1.1.1.5.6.1    martin nopStartElement(void *userData, const XML_Char *name, const XML_Char **atts) {
    503  1.1.1.5.6.1    martin   UNUSED_P(userData);
    504  1.1.1.5.6.1    martin   UNUSED_P(name);
    505  1.1.1.5.6.1    martin   UNUSED_P(atts);
    506          1.1      tron }
    507          1.1      tron 
    508          1.1      tron static void XMLCALL
    509  1.1.1.5.6.1    martin nopEndElement(void *userData, const XML_Char *name) {
    510  1.1.1.5.6.1    martin   UNUSED_P(userData);
    511  1.1.1.5.6.1    martin   UNUSED_P(name);
    512          1.1      tron }
    513          1.1      tron 
    514          1.1      tron static void XMLCALL
    515  1.1.1.5.6.1    martin nopProcessingInstruction(void *userData, const XML_Char *target,
    516  1.1.1.5.6.1    martin                          const XML_Char *data) {
    517  1.1.1.5.6.1    martin   UNUSED_P(userData);
    518  1.1.1.5.6.1    martin   UNUSED_P(target);
    519  1.1.1.5.6.1    martin   UNUSED_P(data);
    520          1.1      tron }
    521          1.1      tron 
    522          1.1      tron static void XMLCALL
    523  1.1.1.5.6.1    martin markup(void *userData, const XML_Char *s, int len) {
    524  1.1.1.5.6.1    martin   FILE *fp = ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp;
    525          1.1      tron   for (; len > 0; --len, ++s)
    526          1.1      tron     puttc(*s, fp);
    527          1.1      tron }
    528          1.1      tron 
    529          1.1      tron static void
    530  1.1.1.5.6.1    martin metaLocation(XML_Parser parser) {
    531          1.1      tron   const XML_Char *uri = XML_GetBase(parser);
    532  1.1.1.5.6.1    martin   FILE *fp = ((XmlwfUserData *)XML_GetUserData(parser))->fp;
    533          1.1      tron   if (uri)
    534  1.1.1.5.6.1    martin     ftprintf(fp, T(" uri=\"%s\""), uri);
    535  1.1.1.5.6.1    martin   ftprintf(fp,
    536  1.1.1.5.6.1    martin            T(" byte=\"%") T(XML_FMT_INT_MOD) T("d\"") T(" nbytes=\"%d\"")
    537  1.1.1.5.6.1    martin                T(" line=\"%") T(XML_FMT_INT_MOD) T("u\"") T(" col=\"%")
    538  1.1.1.5.6.1    martin                    T(XML_FMT_INT_MOD) T("u\""),
    539  1.1.1.5.6.1    martin            XML_GetCurrentByteIndex(parser), XML_GetCurrentByteCount(parser),
    540          1.1      tron            XML_GetCurrentLineNumber(parser),
    541          1.1      tron            XML_GetCurrentColumnNumber(parser));
    542          1.1      tron }
    543          1.1      tron 
    544          1.1      tron static void
    545  1.1.1.5.6.1    martin metaStartDocument(void *userData) {
    546  1.1.1.5.6.1    martin   fputts(T("<document>\n"),
    547  1.1.1.5.6.1    martin          ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp);
    548          1.1      tron }
    549          1.1      tron 
    550          1.1      tron static void
    551  1.1.1.5.6.1    martin metaEndDocument(void *userData) {
    552  1.1.1.5.6.1    martin   fputts(T("</document>\n"),
    553  1.1.1.5.6.1    martin          ((XmlwfUserData *)XML_GetUserData((XML_Parser)userData))->fp);
    554          1.1      tron }
    555          1.1      tron 
    556          1.1      tron static void XMLCALL
    557  1.1.1.5.6.1    martin metaStartElement(void *userData, const XML_Char *name, const XML_Char **atts) {
    558  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    559  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    560  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    561          1.1      tron   const XML_Char **specifiedAttsEnd
    562  1.1.1.5.6.1    martin       = atts + XML_GetSpecifiedAttributeCount(parser);
    563          1.1      tron   const XML_Char **idAttPtr;
    564          1.1      tron   int idAttIndex = XML_GetIdAttributeIndex(parser);
    565          1.1      tron   if (idAttIndex < 0)
    566          1.1      tron     idAttPtr = 0;
    567          1.1      tron   else
    568          1.1      tron     idAttPtr = atts + idAttIndex;
    569  1.1.1.5.6.1    martin 
    570          1.1      tron   ftprintf(fp, T("<starttag name=\"%s\""), name);
    571          1.1      tron   metaLocation(parser);
    572          1.1      tron   if (*atts) {
    573          1.1      tron     fputts(T(">\n"), fp);
    574          1.1      tron     do {
    575          1.1      tron       ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
    576  1.1.1.5.6.1    martin       characterData(data, atts[1], (int)tcslen(atts[1]));
    577          1.1      tron       if (atts >= specifiedAttsEnd)
    578          1.1      tron         fputts(T("\" defaulted=\"yes\"/>\n"), fp);
    579          1.1      tron       else if (atts == idAttPtr)
    580          1.1      tron         fputts(T("\" id=\"yes\"/>\n"), fp);
    581          1.1      tron       else
    582          1.1      tron         fputts(T("\"/>\n"), fp);
    583          1.1      tron     } while (*(atts += 2));
    584          1.1      tron     fputts(T("</starttag>\n"), fp);
    585  1.1.1.5.6.1    martin   } else
    586          1.1      tron     fputts(T("/>\n"), fp);
    587          1.1      tron }
    588          1.1      tron 
    589          1.1      tron static void XMLCALL
    590  1.1.1.5.6.1    martin metaEndElement(void *userData, const XML_Char *name) {
    591  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    592  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    593  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    594          1.1      tron   ftprintf(fp, T("<endtag name=\"%s\""), name);
    595          1.1      tron   metaLocation(parser);
    596          1.1      tron   fputts(T("/>\n"), fp);
    597          1.1      tron }
    598          1.1      tron 
    599          1.1      tron static void XMLCALL
    600          1.1      tron metaProcessingInstruction(void *userData, const XML_Char *target,
    601  1.1.1.5.6.1    martin                           const XML_Char *data) {
    602  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    603  1.1.1.5.6.1    martin   XmlwfUserData *usrData = (XmlwfUserData *)XML_GetUserData(parser);
    604  1.1.1.5.6.1    martin   FILE *fp = usrData->fp;
    605          1.1      tron   ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
    606  1.1.1.5.6.1    martin   characterData(usrData, data, (int)tcslen(data));
    607          1.1      tron   puttc(T('"'), fp);
    608          1.1      tron   metaLocation(parser);
    609          1.1      tron   fputts(T("/>\n"), fp);
    610          1.1      tron }
    611          1.1      tron 
    612          1.1      tron static void XMLCALL
    613  1.1.1.5.6.1    martin metaComment(void *userData, const XML_Char *data) {
    614  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    615  1.1.1.5.6.1    martin   XmlwfUserData *usrData = (XmlwfUserData *)XML_GetUserData(parser);
    616  1.1.1.5.6.1    martin   FILE *fp = usrData->fp;
    617          1.1      tron   fputts(T("<comment data=\""), fp);
    618  1.1.1.5.6.1    martin   characterData(usrData, data, (int)tcslen(data));
    619          1.1      tron   puttc(T('"'), fp);
    620          1.1      tron   metaLocation(parser);
    621          1.1      tron   fputts(T("/>\n"), fp);
    622          1.1      tron }
    623          1.1      tron 
    624          1.1      tron static void XMLCALL
    625  1.1.1.5.6.1    martin metaStartCdataSection(void *userData) {
    626  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    627  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    628  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    629          1.1      tron   fputts(T("<startcdata"), fp);
    630          1.1      tron   metaLocation(parser);
    631          1.1      tron   fputts(T("/>\n"), fp);
    632          1.1      tron }
    633          1.1      tron 
    634          1.1      tron static void XMLCALL
    635  1.1.1.5.6.1    martin metaEndCdataSection(void *userData) {
    636  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    637  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    638  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    639          1.1      tron   fputts(T("<endcdata"), fp);
    640          1.1      tron   metaLocation(parser);
    641          1.1      tron   fputts(T("/>\n"), fp);
    642          1.1      tron }
    643          1.1      tron 
    644          1.1      tron static void XMLCALL
    645  1.1.1.5.6.1    martin metaCharacterData(void *userData, const XML_Char *s, int len) {
    646  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    647  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    648  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    649          1.1      tron   fputts(T("<chars str=\""), fp);
    650  1.1.1.5.6.1    martin   characterData(data, s, len);
    651          1.1      tron   puttc(T('"'), fp);
    652          1.1      tron   metaLocation(parser);
    653          1.1      tron   fputts(T("/>\n"), fp);
    654          1.1      tron }
    655          1.1      tron 
    656          1.1      tron static void XMLCALL
    657  1.1.1.5.6.1    martin metaStartDoctypeDecl(void *userData, const XML_Char *doctypeName,
    658  1.1.1.5.6.1    martin                      const XML_Char *sysid, const XML_Char *pubid,
    659  1.1.1.5.6.1    martin                      int has_internal_subset) {
    660  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    661  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    662  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    663  1.1.1.5.6.1    martin   UNUSED_P(sysid);
    664  1.1.1.5.6.1    martin   UNUSED_P(pubid);
    665  1.1.1.5.6.1    martin   UNUSED_P(has_internal_subset);
    666          1.1      tron   ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
    667          1.1      tron   metaLocation(parser);
    668          1.1      tron   fputts(T("/>\n"), fp);
    669          1.1      tron }
    670          1.1      tron 
    671          1.1      tron static void XMLCALL
    672  1.1.1.5.6.1    martin metaEndDoctypeDecl(void *userData) {
    673  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    674  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    675  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    676          1.1      tron   fputts(T("<enddoctype"), fp);
    677          1.1      tron   metaLocation(parser);
    678          1.1      tron   fputts(T("/>\n"), fp);
    679          1.1      tron }
    680          1.1      tron 
    681          1.1      tron static void XMLCALL
    682  1.1.1.5.6.1    martin metaNotationDecl(void *userData, const XML_Char *notationName,
    683  1.1.1.5.6.1    martin                  const XML_Char *base, const XML_Char *systemId,
    684  1.1.1.5.6.1    martin                  const XML_Char *publicId) {
    685  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    686  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    687  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    688  1.1.1.5.6.1    martin   UNUSED_P(base);
    689          1.1      tron   ftprintf(fp, T("<notation name=\"%s\""), notationName);
    690          1.1      tron   if (publicId)
    691          1.1      tron     ftprintf(fp, T(" public=\"%s\""), publicId);
    692          1.1      tron   if (systemId) {
    693          1.1      tron     fputts(T(" system=\""), fp);
    694  1.1.1.5.6.1    martin     characterData(data, systemId, (int)tcslen(systemId));
    695          1.1      tron     puttc(T('"'), fp);
    696          1.1      tron   }
    697          1.1      tron   metaLocation(parser);
    698          1.1      tron   fputts(T("/>\n"), fp);
    699          1.1      tron }
    700          1.1      tron 
    701          1.1      tron static void XMLCALL
    702  1.1.1.5.6.1    martin metaEntityDecl(void *userData, const XML_Char *entityName, int is_param,
    703  1.1.1.5.6.1    martin                const XML_Char *value, int value_length, const XML_Char *base,
    704  1.1.1.5.6.1    martin                const XML_Char *systemId, const XML_Char *publicId,
    705  1.1.1.5.6.1    martin                const XML_Char *notationName) {
    706  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    707  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    708  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    709          1.1      tron 
    710  1.1.1.5.6.1    martin   UNUSED_P(is_param);
    711  1.1.1.5.6.1    martin   UNUSED_P(base);
    712          1.1      tron   if (value) {
    713          1.1      tron     ftprintf(fp, T("<entity name=\"%s\""), entityName);
    714          1.1      tron     metaLocation(parser);
    715          1.1      tron     puttc(T('>'), fp);
    716  1.1.1.5.6.1    martin     characterData(data, value, value_length);
    717          1.1      tron     fputts(T("</entity/>\n"), fp);
    718  1.1.1.5.6.1    martin   } else if (notationName) {
    719          1.1      tron     ftprintf(fp, T("<entity name=\"%s\""), entityName);
    720          1.1      tron     if (publicId)
    721          1.1      tron       ftprintf(fp, T(" public=\"%s\""), publicId);
    722          1.1      tron     fputts(T(" system=\""), fp);
    723  1.1.1.5.6.1    martin     characterData(data, systemId, (int)tcslen(systemId));
    724          1.1      tron     puttc(T('"'), fp);
    725          1.1      tron     ftprintf(fp, T(" notation=\"%s\""), notationName);
    726          1.1      tron     metaLocation(parser);
    727          1.1      tron     fputts(T("/>\n"), fp);
    728  1.1.1.5.6.1    martin   } else {
    729          1.1      tron     ftprintf(fp, T("<entity name=\"%s\""), entityName);
    730          1.1      tron     if (publicId)
    731          1.1      tron       ftprintf(fp, T(" public=\"%s\""), publicId);
    732          1.1      tron     fputts(T(" system=\""), fp);
    733  1.1.1.5.6.1    martin     characterData(data, systemId, (int)tcslen(systemId));
    734          1.1      tron     puttc(T('"'), fp);
    735          1.1      tron     metaLocation(parser);
    736          1.1      tron     fputts(T("/>\n"), fp);
    737          1.1      tron   }
    738          1.1      tron }
    739          1.1      tron 
    740          1.1      tron static void XMLCALL
    741  1.1.1.5.6.1    martin metaStartNamespaceDecl(void *userData, const XML_Char *prefix,
    742  1.1.1.5.6.1    martin                        const XML_Char *uri) {
    743  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    744  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    745  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    746          1.1      tron   fputts(T("<startns"), fp);
    747          1.1      tron   if (prefix)
    748          1.1      tron     ftprintf(fp, T(" prefix=\"%s\""), prefix);
    749          1.1      tron   if (uri) {
    750          1.1      tron     fputts(T(" ns=\""), fp);
    751  1.1.1.5.6.1    martin     characterData(data, uri, (int)tcslen(uri));
    752          1.1      tron     fputts(T("\"/>\n"), fp);
    753  1.1.1.5.6.1    martin   } else
    754          1.1      tron     fputts(T("/>\n"), fp);
    755          1.1      tron }
    756          1.1      tron 
    757          1.1      tron static void XMLCALL
    758  1.1.1.5.6.1    martin metaEndNamespaceDecl(void *userData, const XML_Char *prefix) {
    759  1.1.1.5.6.1    martin   XML_Parser parser = (XML_Parser)userData;
    760  1.1.1.5.6.1    martin   XmlwfUserData *data = (XmlwfUserData *)XML_GetUserData(parser);
    761  1.1.1.5.6.1    martin   FILE *fp = data->fp;
    762  1.1.1.5.6.1    martin   if (! prefix)
    763          1.1      tron     fputts(T("<endns/>\n"), fp);
    764          1.1      tron   else
    765          1.1      tron     ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
    766          1.1      tron }
    767          1.1      tron 
    768          1.1      tron static int XMLCALL
    769  1.1.1.5.6.1    martin unknownEncodingConvert(void *data, const char *p) {
    770          1.1      tron   return codepageConvert(*(int *)data, p);
    771          1.1      tron }
    772          1.1      tron 
    773          1.1      tron static int XMLCALL
    774  1.1.1.5.6.1    martin unknownEncoding(void *userData, const XML_Char *name, XML_Encoding *info) {
    775          1.1      tron   int cp;
    776          1.1      tron   static const XML_Char prefixL[] = T("windows-");
    777          1.1      tron   static const XML_Char prefixU[] = T("WINDOWS-");
    778          1.1      tron   int i;
    779          1.1      tron 
    780  1.1.1.5.6.1    martin   UNUSED_P(userData);
    781          1.1      tron   for (i = 0; prefixU[i]; i++)
    782          1.1      tron     if (name[i] != prefixU[i] && name[i] != prefixL[i])
    783          1.1      tron       return 0;
    784  1.1.1.5.6.1    martin 
    785          1.1      tron   cp = 0;
    786          1.1      tron   for (; name[i]; i++) {
    787          1.1      tron     static const XML_Char digits[] = T("0123456789");
    788          1.1      tron     const XML_Char *s = tcschr(digits, name[i]);
    789  1.1.1.5.6.1    martin     if (! s)
    790          1.1      tron       return 0;
    791          1.1      tron     cp *= 10;
    792          1.1      tron     cp += (int)(s - digits);
    793          1.1      tron     if (cp >= 0x10000)
    794          1.1      tron       return 0;
    795          1.1      tron   }
    796  1.1.1.5.6.1    martin   if (! codepageMap(cp, info->map))
    797          1.1      tron     return 0;
    798          1.1      tron   info->convert = unknownEncodingConvert;
    799          1.1      tron   /* We could just cast the code page integer to a void *,
    800          1.1      tron   and avoid the use of release. */
    801          1.1      tron   info->release = free;
    802          1.1      tron   info->data = malloc(sizeof(int));
    803  1.1.1.5.6.1    martin   if (! info->data)
    804          1.1      tron     return 0;
    805          1.1      tron   *(int *)info->data = cp;
    806          1.1      tron   return 1;
    807          1.1      tron }
    808          1.1      tron 
    809          1.1      tron static int XMLCALL
    810  1.1.1.5.6.1    martin notStandalone(void *userData) {
    811  1.1.1.5.6.1    martin   UNUSED_P(userData);
    812          1.1      tron   return 0;
    813          1.1      tron }
    814          1.1      tron 
    815          1.1      tron static void
    816  1.1.1.5.6.1    martin showVersion(XML_Char *prog) {
    817          1.1      tron   XML_Char *s = prog;
    818          1.1      tron   XML_Char ch;
    819          1.1      tron   const XML_Feature *features = XML_GetFeatureList();
    820          1.1      tron   while ((ch = *s) != 0) {
    821          1.1      tron     if (ch == '/'
    822      1.1.1.5  christos #if defined(_WIN32)
    823          1.1      tron         || ch == '\\'
    824          1.1      tron #endif
    825  1.1.1.5.6.1    martin     )
    826          1.1      tron       prog = s + 1;
    827          1.1      tron     ++s;
    828          1.1      tron   }
    829          1.1      tron   ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion());
    830          1.1      tron   if (features != NULL && features[0].feature != XML_FEATURE_END) {
    831          1.1      tron     int i = 1;
    832          1.1      tron     ftprintf(stdout, T("%s"), features[0].name);
    833          1.1      tron     if (features[0].value)
    834          1.1      tron       ftprintf(stdout, T("=%ld"), features[0].value);
    835          1.1      tron     while (features[i].feature != XML_FEATURE_END) {
    836          1.1      tron       ftprintf(stdout, T(", %s"), features[i].name);
    837          1.1      tron       if (features[i].value)
    838          1.1      tron         ftprintf(stdout, T("=%ld"), features[i].value);
    839          1.1      tron       ++i;
    840          1.1      tron     }
    841          1.1      tron     ftprintf(stdout, T("\n"));
    842          1.1      tron   }
    843          1.1      tron }
    844          1.1      tron 
    845          1.1      tron static void
    846  1.1.1.5.6.1    martin usage(const XML_Char *prog, int rc) {
    847  1.1.1.5.6.1    martin   ftprintf(
    848  1.1.1.5.6.1    martin       stderr,
    849  1.1.1.5.6.1    martin       /* Generated with:
    850  1.1.1.5.6.1    martin        * $ xmlwf/xmlwf_helpgen.sh
    851  1.1.1.5.6.1    martin        */
    852  1.1.1.5.6.1    martin       /* clang-format off */
    853  1.1.1.5.6.1    martin       T("usage: %s [-s] [-n] [-p] [-x] [-e ENCODING] [-w] [-r] [-d DIRECTORY]\n")
    854  1.1.1.5.6.1    martin       T("             [-c | -m | -t] [-N]\n")
    855  1.1.1.5.6.1    martin       T("             [FILE [FILE ...]]\n")
    856  1.1.1.5.6.1    martin       T("\n")
    857  1.1.1.5.6.1    martin       T("xmlwf - Determines if an XML document is well-formed\n")
    858  1.1.1.5.6.1    martin       T("\n")
    859  1.1.1.5.6.1    martin       T("positional arguments:\n")
    860  1.1.1.5.6.1    martin       T("  FILE          files to process (default: STDIN)\n")
    861  1.1.1.5.6.1    martin       T("\n")
    862  1.1.1.5.6.1    martin       T("input control arguments:\n")
    863  1.1.1.5.6.1    martin       T("  -s            print an error if the document is not [s]tandalone\n")
    864  1.1.1.5.6.1    martin       T("  -n            enable [n]amespace processing\n")
    865  1.1.1.5.6.1    martin       T("  -p            enable processing external DTDs and [p]arameter entities\n")
    866  1.1.1.5.6.1    martin       T("  -x            enable processing of e[x]ternal entities\n")
    867  1.1.1.5.6.1    martin       T("  -e ENCODING   override any in-document [e]ncoding declaration\n")
    868  1.1.1.5.6.1    martin       T("  -w            enable support for [W]indows code pages\n")
    869  1.1.1.5.6.1    martin       T("  -r            disable memory-mapping and use normal file [r]ead IO calls instead\n")
    870  1.1.1.5.6.1    martin       T("\n")
    871  1.1.1.5.6.1    martin       T("output control arguments:\n")
    872  1.1.1.5.6.1    martin       T("  -d DIRECTORY  output [d]estination directory\n")
    873  1.1.1.5.6.1    martin       T("  -c            write a [c]opy of input XML, not canonical XML\n")
    874  1.1.1.5.6.1    martin       T("  -m            write [m]eta XML, not canonical XML\n")
    875  1.1.1.5.6.1    martin       T("  -t            write no XML output for [t]iming of plain parsing\n")
    876  1.1.1.5.6.1    martin       T("  -N            enable adding doctype and [n]otation declarations\n")
    877  1.1.1.5.6.1    martin       T("\n")
    878  1.1.1.5.6.1    martin       T("info arguments:\n")
    879  1.1.1.5.6.1    martin       T("  -h            show this [h]elp message and exit\n")
    880  1.1.1.5.6.1    martin       T("  -v            show program's [v]ersion number and exit\n")
    881  1.1.1.5.6.1    martin       T("\n")
    882  1.1.1.5.6.1    martin       T("libexpat is software libre, licensed under the MIT license.\n")
    883  1.1.1.5.6.1    martin       T("Please report bugs at https://github.com/libexpat/libexpat/issues.  Thank you!\n")
    884  1.1.1.5.6.1    martin       , /* clang-format on */
    885  1.1.1.5.6.1    martin       prog);
    886          1.1      tron   exit(rc);
    887          1.1      tron }
    888          1.1      tron 
    889  1.1.1.5.6.1    martin #if defined(__MINGW32__) && defined(XML_UNICODE)
    890  1.1.1.5.6.1    martin /* Silence warning about missing prototype */
    891  1.1.1.5.6.1    martin int wmain(int argc, XML_Char **argv);
    892  1.1.1.5.6.1    martin #endif
    893  1.1.1.5.6.1    martin 
    894          1.1      tron int
    895  1.1.1.5.6.1    martin tmain(int argc, XML_Char **argv) {
    896          1.1      tron   int i, j;
    897          1.1      tron   const XML_Char *outputDir = NULL;
    898          1.1      tron   const XML_Char *encoding = NULL;
    899          1.1      tron   unsigned processFlags = XML_MAP_FILE;
    900          1.1      tron   int windowsCodePages = 0;
    901          1.1      tron   int outputType = 0;
    902          1.1      tron   int useNamespaces = 0;
    903          1.1      tron   int requireStandalone = 0;
    904  1.1.1.5.6.1    martin   int requiresNotations = 0;
    905  1.1.1.5.6.1    martin   enum XML_ParamEntityParsing paramEntityParsing
    906  1.1.1.5.6.1    martin       = XML_PARAM_ENTITY_PARSING_NEVER;
    907          1.1      tron   int useStdin = 0;
    908  1.1.1.5.6.1    martin   XmlwfUserData userData = {NULL, NULL, NULL};
    909          1.1      tron 
    910          1.1      tron #ifdef _MSC_VER
    911  1.1.1.5.6.1    martin   _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    912          1.1      tron #endif
    913          1.1      tron 
    914          1.1      tron   i = 1;
    915          1.1      tron   j = 0;
    916          1.1      tron   while (i < argc) {
    917          1.1      tron     if (j == 0) {
    918          1.1      tron       if (argv[i][0] != T('-'))
    919          1.1      tron         break;
    920          1.1      tron       if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
    921          1.1      tron         i++;
    922          1.1      tron         break;
    923          1.1      tron       }
    924          1.1      tron       j++;
    925          1.1      tron     }
    926          1.1      tron     switch (argv[i][j]) {
    927          1.1      tron     case T('r'):
    928          1.1      tron       processFlags &= ~XML_MAP_FILE;
    929          1.1      tron       j++;
    930          1.1      tron       break;
    931          1.1      tron     case T('s'):
    932          1.1      tron       requireStandalone = 1;
    933          1.1      tron       j++;
    934          1.1      tron       break;
    935          1.1      tron     case T('n'):
    936          1.1      tron       useNamespaces = 1;
    937          1.1      tron       j++;
    938          1.1      tron       break;
    939          1.1      tron     case T('p'):
    940          1.1      tron       paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
    941          1.1      tron       /* fall through */
    942          1.1      tron     case T('x'):
    943          1.1      tron       processFlags |= XML_EXTERNAL_ENTITIES;
    944          1.1      tron       j++;
    945          1.1      tron       break;
    946          1.1      tron     case T('w'):
    947          1.1      tron       windowsCodePages = 1;
    948          1.1      tron       j++;
    949          1.1      tron       break;
    950          1.1      tron     case T('m'):
    951          1.1      tron       outputType = 'm';
    952          1.1      tron       j++;
    953          1.1      tron       break;
    954          1.1      tron     case T('c'):
    955          1.1      tron       outputType = 'c';
    956          1.1      tron       useNamespaces = 0;
    957          1.1      tron       j++;
    958          1.1      tron       break;
    959          1.1      tron     case T('t'):
    960          1.1      tron       outputType = 't';
    961          1.1      tron       j++;
    962          1.1      tron       break;
    963  1.1.1.5.6.1    martin     case T('N'):
    964  1.1.1.5.6.1    martin       requiresNotations = 1;
    965  1.1.1.5.6.1    martin       j++;
    966  1.1.1.5.6.1    martin       break;
    967          1.1      tron     case T('d'):
    968          1.1      tron       if (argv[i][j + 1] == T('\0')) {
    969          1.1      tron         if (++i == argc)
    970          1.1      tron           usage(argv[0], 2);
    971          1.1      tron         outputDir = argv[i];
    972  1.1.1.5.6.1    martin       } else
    973          1.1      tron         outputDir = argv[i] + j + 1;
    974          1.1      tron       i++;
    975          1.1      tron       j = 0;
    976          1.1      tron       break;
    977          1.1      tron     case T('e'):
    978          1.1      tron       if (argv[i][j + 1] == T('\0')) {
    979          1.1      tron         if (++i == argc)
    980          1.1      tron           usage(argv[0], 2);
    981          1.1      tron         encoding = argv[i];
    982  1.1.1.5.6.1    martin       } else
    983          1.1      tron         encoding = argv[i] + j + 1;
    984          1.1      tron       i++;
    985          1.1      tron       j = 0;
    986          1.1      tron       break;
    987          1.1      tron     case T('h'):
    988          1.1      tron       usage(argv[0], 0);
    989          1.1      tron       return 0;
    990          1.1      tron     case T('v'):
    991          1.1      tron       showVersion(argv[0]);
    992          1.1      tron       return 0;
    993          1.1      tron     case T('\0'):
    994          1.1      tron       if (j > 1) {
    995          1.1      tron         i++;
    996          1.1      tron         j = 0;
    997          1.1      tron         break;
    998          1.1      tron       }
    999          1.1      tron       /* fall through */
   1000          1.1      tron     default:
   1001          1.1      tron       usage(argv[0], 2);
   1002          1.1      tron     }
   1003          1.1      tron   }
   1004          1.1      tron   if (i == argc) {
   1005          1.1      tron     useStdin = 1;
   1006          1.1      tron     processFlags &= ~XML_MAP_FILE;
   1007          1.1      tron     i--;
   1008          1.1      tron   }
   1009          1.1      tron   for (; i < argc; i++) {
   1010          1.1      tron     XML_Char *outName = 0;
   1011          1.1      tron     int result;
   1012          1.1      tron     XML_Parser parser;
   1013          1.1      tron     if (useNamespaces)
   1014          1.1      tron       parser = XML_ParserCreateNS(encoding, NSSEP);
   1015          1.1      tron     else
   1016          1.1      tron       parser = XML_ParserCreate(encoding);
   1017      1.1.1.4       spz 
   1018      1.1.1.4       spz     if (! parser) {
   1019  1.1.1.5.6.1    martin       tperror(T("Could not instantiate parser"));
   1020      1.1.1.4       spz       exit(1);
   1021      1.1.1.4       spz     }
   1022      1.1.1.4       spz 
   1023          1.1      tron     if (requireStandalone)
   1024          1.1      tron       XML_SetNotStandaloneHandler(parser, notStandalone);
   1025          1.1      tron     XML_SetParamEntityParsing(parser, paramEntityParsing);
   1026          1.1      tron     if (outputType == 't') {
   1027          1.1      tron       /* This is for doing timings; this gives a more realistic estimate of
   1028          1.1      tron          the parsing time. */
   1029          1.1      tron       outputDir = 0;
   1030          1.1      tron       XML_SetElementHandler(parser, nopStartElement, nopEndElement);
   1031          1.1      tron       XML_SetCharacterDataHandler(parser, nopCharacterData);
   1032          1.1      tron       XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
   1033  1.1.1.5.6.1    martin     } else if (outputDir) {
   1034  1.1.1.5.6.1    martin       const XML_Char *delim = T("/");
   1035          1.1      tron       const XML_Char *file = useStdin ? T("STDIN") : argv[i];
   1036  1.1.1.5.6.1    martin       if (! useStdin) {
   1037          1.1      tron         /* Jump after last (back)slash */
   1038  1.1.1.5.6.1    martin         const XML_Char *lastDelim = tcsrchr(file, delim[0]);
   1039          1.1      tron         if (lastDelim)
   1040          1.1      tron           file = lastDelim + 1;
   1041      1.1.1.5  christos #if defined(_WIN32)
   1042          1.1      tron         else {
   1043  1.1.1.5.6.1    martin           const XML_Char *winDelim = T("\\");
   1044          1.1      tron           lastDelim = tcsrchr(file, winDelim[0]);
   1045          1.1      tron           if (lastDelim) {
   1046          1.1      tron             file = lastDelim + 1;
   1047          1.1      tron             delim = winDelim;
   1048          1.1      tron           }
   1049          1.1      tron         }
   1050          1.1      tron #endif
   1051          1.1      tron       }
   1052          1.1      tron       outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2)
   1053  1.1.1.5.6.1    martin                                    * sizeof(XML_Char));
   1054          1.1      tron       tcscpy(outName, outputDir);
   1055          1.1      tron       tcscat(outName, delim);
   1056          1.1      tron       tcscat(outName, file);
   1057  1.1.1.5.6.1    martin       userData.fp = tfopen(outName, T("wb"));
   1058  1.1.1.5.6.1    martin       if (! userData.fp) {
   1059          1.1      tron         tperror(outName);
   1060          1.1      tron         exit(1);
   1061          1.1      tron       }
   1062  1.1.1.5.6.1    martin       setvbuf(userData.fp, NULL, _IOFBF, 16384);
   1063          1.1      tron #ifdef XML_UNICODE
   1064  1.1.1.5.6.1    martin       puttc(0xFEFF, userData.fp);
   1065          1.1      tron #endif
   1066  1.1.1.5.6.1    martin       XML_SetUserData(parser, &userData);
   1067          1.1      tron       switch (outputType) {
   1068          1.1      tron       case 'm':
   1069          1.1      tron         XML_UseParserAsHandlerArg(parser);
   1070          1.1      tron         XML_SetElementHandler(parser, metaStartElement, metaEndElement);
   1071          1.1      tron         XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
   1072          1.1      tron         XML_SetCommentHandler(parser, metaComment);
   1073          1.1      tron         XML_SetCdataSectionHandler(parser, metaStartCdataSection,
   1074          1.1      tron                                    metaEndCdataSection);
   1075          1.1      tron         XML_SetCharacterDataHandler(parser, metaCharacterData);
   1076          1.1      tron         XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
   1077          1.1      tron                                   metaEndDoctypeDecl);
   1078          1.1      tron         XML_SetEntityDeclHandler(parser, metaEntityDecl);
   1079          1.1      tron         XML_SetNotationDeclHandler(parser, metaNotationDecl);
   1080          1.1      tron         XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
   1081          1.1      tron                                     metaEndNamespaceDecl);
   1082          1.1      tron         metaStartDocument(parser);
   1083          1.1      tron         break;
   1084          1.1      tron       case 'c':
   1085          1.1      tron         XML_UseParserAsHandlerArg(parser);
   1086          1.1      tron         XML_SetDefaultHandler(parser, markup);
   1087          1.1      tron         XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
   1088          1.1      tron         XML_SetCharacterDataHandler(parser, defaultCharacterData);
   1089          1.1      tron         XML_SetProcessingInstructionHandler(parser,
   1090          1.1      tron                                             defaultProcessingInstruction);
   1091          1.1      tron         break;
   1092          1.1      tron       default:
   1093          1.1      tron         if (useNamespaces)
   1094          1.1      tron           XML_SetElementHandler(parser, startElementNS, endElementNS);
   1095          1.1      tron         else
   1096          1.1      tron           XML_SetElementHandler(parser, startElement, endElement);
   1097          1.1      tron         XML_SetCharacterDataHandler(parser, characterData);
   1098          1.1      tron #ifndef W3C14N
   1099          1.1      tron         XML_SetProcessingInstructionHandler(parser, processingInstruction);
   1100  1.1.1.5.6.1    martin         if (requiresNotations) {
   1101  1.1.1.5.6.1    martin           XML_SetDoctypeDeclHandler(parser, startDoctypeDecl, endDoctypeDecl);
   1102  1.1.1.5.6.1    martin           XML_SetNotationDeclHandler(parser, notationDecl);
   1103  1.1.1.5.6.1    martin         }
   1104          1.1      tron #endif /* not W3C14N */
   1105          1.1      tron         break;
   1106          1.1      tron       }
   1107          1.1      tron     }
   1108          1.1      tron     if (windowsCodePages)
   1109          1.1      tron       XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
   1110          1.1      tron     result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
   1111          1.1      tron     if (outputDir) {
   1112          1.1      tron       if (outputType == 'm')
   1113          1.1      tron         metaEndDocument(parser);
   1114  1.1.1.5.6.1    martin       fclose(userData.fp);
   1115  1.1.1.5.6.1    martin       if (! result) {
   1116          1.1      tron         tremove(outName);
   1117      1.1.1.2       spz       }
   1118          1.1      tron       free(outName);
   1119          1.1      tron     }
   1120          1.1      tron     XML_ParserFree(parser);
   1121  1.1.1.5.6.1    martin     if (! result) {
   1122  1.1.1.5.6.1    martin       exit(2);
   1123  1.1.1.5.6.1    martin     }
   1124          1.1      tron   }
   1125          1.1      tron   return 0;
   1126          1.1      tron }
   1127