1104349Sphk/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd 2104349Sphk See the file COPYING for copying permission. 3104349Sphk*/ 4104349Sphk 5104349Sphk#include <stdio.h> 6104349Sphk#include <stdlib.h> 7104349Sphk#include <stddef.h> 8104349Sphk#include <string.h> 9104349Sphk 10104349Sphk#include "expat.h" 11104349Sphk#include "codepage.h" 12104349Sphk#include "xmlfile.h" 13104349Sphk#include "xmltchar.h" 14104349Sphk 15104349Sphk#ifdef _MSC_VER 16104349Sphk#include <crtdbg.h> 17104349Sphk#endif 18104349Sphk 19178848Scokane#if defined(__amigaos__) && defined(__USE_INLINE__) 20178848Scokane#include <proto/expat.h> 21178848Scokane#endif 22178848Scokane 23104349Sphk/* This ensures proper sorting. */ 24104349Sphk 25104349Sphk#define NSSEP T('\001') 26104349Sphk 27178848Scokanestatic void XMLCALL 28104349SphkcharacterData(void *userData, const XML_Char *s, int len) 29104349Sphk{ 30178848Scokane FILE *fp = (FILE *)userData; 31104349Sphk for (; len > 0; --len, ++s) { 32104349Sphk switch (*s) { 33104349Sphk case T('&'): 34104349Sphk fputts(T("&"), fp); 35104349Sphk break; 36104349Sphk case T('<'): 37104349Sphk fputts(T("<"), fp); 38104349Sphk break; 39104349Sphk case T('>'): 40104349Sphk fputts(T(">"), fp); 41104349Sphk break; 42104349Sphk#ifdef W3C14N 43104349Sphk case 13: 44104349Sphk fputts(T("
"), fp); 45104349Sphk break; 46104349Sphk#else 47104349Sphk case T('"'): 48104349Sphk fputts(T("""), fp); 49104349Sphk break; 50104349Sphk case 9: 51104349Sphk case 10: 52104349Sphk case 13: 53104349Sphk ftprintf(fp, T("&#%d;"), *s); 54104349Sphk break; 55104349Sphk#endif 56104349Sphk default: 57104349Sphk puttc(*s, fp); 58104349Sphk break; 59104349Sphk } 60104349Sphk } 61104349Sphk} 62104349Sphk 63104349Sphkstatic void 64104349SphkattributeValue(FILE *fp, const XML_Char *s) 65104349Sphk{ 66104349Sphk puttc(T('='), fp); 67104349Sphk puttc(T('"'), fp); 68104349Sphk for (;;) { 69104349Sphk switch (*s) { 70104349Sphk case 0: 71104349Sphk case NSSEP: 72104349Sphk puttc(T('"'), fp); 73104349Sphk return; 74104349Sphk case T('&'): 75104349Sphk fputts(T("&"), fp); 76104349Sphk break; 77104349Sphk case T('<'): 78104349Sphk fputts(T("<"), fp); 79104349Sphk break; 80104349Sphk case T('"'): 81104349Sphk fputts(T("""), fp); 82104349Sphk break; 83104349Sphk#ifdef W3C14N 84104349Sphk case 9: 85104349Sphk fputts(T("	"), fp); 86104349Sphk break; 87104349Sphk case 10: 88104349Sphk fputts(T("
"), fp); 89104349Sphk break; 90104349Sphk case 13: 91104349Sphk fputts(T("
"), fp); 92104349Sphk break; 93104349Sphk#else 94104349Sphk case T('>'): 95104349Sphk fputts(T(">"), fp); 96104349Sphk break; 97104349Sphk case 9: 98104349Sphk case 10: 99104349Sphk case 13: 100104349Sphk ftprintf(fp, T("&#%d;"), *s); 101104349Sphk break; 102104349Sphk#endif 103104349Sphk default: 104104349Sphk puttc(*s, fp); 105104349Sphk break; 106104349Sphk } 107104349Sphk s++; 108104349Sphk } 109104349Sphk} 110104349Sphk 111104349Sphk/* Lexicographically comparing UTF-8 encoded attribute values, 112104349Sphkis equivalent to lexicographically comparing based on the character number. */ 113104349Sphk 114104349Sphkstatic int 115104349Sphkattcmp(const void *att1, const void *att2) 116104349Sphk{ 117104349Sphk return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2); 118104349Sphk} 119104349Sphk 120178848Scokanestatic void XMLCALL 121104349SphkstartElement(void *userData, const XML_Char *name, const XML_Char **atts) 122104349Sphk{ 123104349Sphk int nAtts; 124104349Sphk const XML_Char **p; 125178848Scokane FILE *fp = (FILE *)userData; 126104349Sphk puttc(T('<'), fp); 127104349Sphk fputts(name, fp); 128104349Sphk 129104349Sphk p = atts; 130104349Sphk while (*p) 131104349Sphk ++p; 132178848Scokane nAtts = (int)((p - atts) >> 1); 133104349Sphk if (nAtts > 1) 134104349Sphk qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp); 135104349Sphk while (*atts) { 136104349Sphk puttc(T(' '), fp); 137104349Sphk fputts(*atts++, fp); 138104349Sphk attributeValue(fp, *atts); 139104349Sphk atts++; 140104349Sphk } 141104349Sphk puttc(T('>'), fp); 142104349Sphk} 143104349Sphk 144178848Scokanestatic void XMLCALL 145104349SphkendElement(void *userData, const XML_Char *name) 146104349Sphk{ 147178848Scokane FILE *fp = (FILE *)userData; 148104349Sphk puttc(T('<'), fp); 149104349Sphk puttc(T('/'), fp); 150104349Sphk fputts(name, fp); 151104349Sphk puttc(T('>'), fp); 152104349Sphk} 153104349Sphk 154104349Sphkstatic int 155104349Sphknsattcmp(const void *p1, const void *p2) 156104349Sphk{ 157104349Sphk const XML_Char *att1 = *(const XML_Char **)p1; 158104349Sphk const XML_Char *att2 = *(const XML_Char **)p2; 159104349Sphk int sep1 = (tcsrchr(att1, NSSEP) != 0); 160104349Sphk int sep2 = (tcsrchr(att1, NSSEP) != 0); 161104349Sphk if (sep1 != sep2) 162104349Sphk return sep1 - sep2; 163104349Sphk return tcscmp(att1, att2); 164104349Sphk} 165104349Sphk 166178848Scokanestatic void XMLCALL 167104349SphkstartElementNS(void *userData, const XML_Char *name, const XML_Char **atts) 168104349Sphk{ 169104349Sphk int nAtts; 170104349Sphk int nsi; 171104349Sphk const XML_Char **p; 172178848Scokane FILE *fp = (FILE *)userData; 173104349Sphk const XML_Char *sep; 174104349Sphk puttc(T('<'), fp); 175104349Sphk 176104349Sphk sep = tcsrchr(name, NSSEP); 177104349Sphk if (sep) { 178104349Sphk fputts(T("n1:"), fp); 179104349Sphk fputts(sep + 1, fp); 180104349Sphk fputts(T(" xmlns:n1"), fp); 181104349Sphk attributeValue(fp, name); 182104349Sphk nsi = 2; 183104349Sphk } 184104349Sphk else { 185104349Sphk fputts(name, fp); 186104349Sphk nsi = 1; 187104349Sphk } 188104349Sphk 189104349Sphk p = atts; 190104349Sphk while (*p) 191104349Sphk ++p; 192178848Scokane nAtts = (int)((p - atts) >> 1); 193104349Sphk if (nAtts > 1) 194104349Sphk qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp); 195104349Sphk while (*atts) { 196104349Sphk name = *atts++; 197104349Sphk sep = tcsrchr(name, NSSEP); 198104349Sphk puttc(T(' '), fp); 199104349Sphk if (sep) { 200104349Sphk ftprintf(fp, T("n%d:"), nsi); 201104349Sphk fputts(sep + 1, fp); 202104349Sphk } 203104349Sphk else 204104349Sphk fputts(name, fp); 205104349Sphk attributeValue(fp, *atts); 206104349Sphk if (sep) { 207104349Sphk ftprintf(fp, T(" xmlns:n%d"), nsi++); 208104349Sphk attributeValue(fp, name); 209104349Sphk } 210104349Sphk atts++; 211104349Sphk } 212104349Sphk puttc(T('>'), fp); 213104349Sphk} 214104349Sphk 215178848Scokanestatic void XMLCALL 216104349SphkendElementNS(void *userData, const XML_Char *name) 217104349Sphk{ 218178848Scokane FILE *fp = (FILE *)userData; 219104349Sphk const XML_Char *sep; 220104349Sphk puttc(T('<'), fp); 221104349Sphk puttc(T('/'), fp); 222104349Sphk sep = tcsrchr(name, NSSEP); 223104349Sphk if (sep) { 224104349Sphk fputts(T("n1:"), fp); 225104349Sphk fputts(sep + 1, fp); 226104349Sphk } 227104349Sphk else 228104349Sphk fputts(name, fp); 229104349Sphk puttc(T('>'), fp); 230104349Sphk} 231104349Sphk 232104349Sphk#ifndef W3C14N 233104349Sphk 234178848Scokanestatic void XMLCALL 235104349SphkprocessingInstruction(void *userData, const XML_Char *target, 236104349Sphk const XML_Char *data) 237104349Sphk{ 238178848Scokane FILE *fp = (FILE *)userData; 239104349Sphk puttc(T('<'), fp); 240104349Sphk puttc(T('?'), fp); 241104349Sphk fputts(target, fp); 242104349Sphk puttc(T(' '), fp); 243104349Sphk fputts(data, fp); 244104349Sphk puttc(T('?'), fp); 245104349Sphk puttc(T('>'), fp); 246104349Sphk} 247104349Sphk 248104349Sphk#endif /* not W3C14N */ 249104349Sphk 250178848Scokanestatic void XMLCALL 251104349SphkdefaultCharacterData(void *userData, const XML_Char *s, int len) 252104349Sphk{ 253104349Sphk XML_DefaultCurrent((XML_Parser) userData); 254104349Sphk} 255104349Sphk 256178848Scokanestatic void XMLCALL 257104349SphkdefaultStartElement(void *userData, const XML_Char *name, 258104349Sphk const XML_Char **atts) 259104349Sphk{ 260104349Sphk XML_DefaultCurrent((XML_Parser) userData); 261104349Sphk} 262104349Sphk 263178848Scokanestatic void XMLCALL 264104349SphkdefaultEndElement(void *userData, const XML_Char *name) 265104349Sphk{ 266104349Sphk XML_DefaultCurrent((XML_Parser) userData); 267104349Sphk} 268104349Sphk 269178848Scokanestatic void XMLCALL 270104349SphkdefaultProcessingInstruction(void *userData, const XML_Char *target, 271104349Sphk const XML_Char *data) 272104349Sphk{ 273104349Sphk XML_DefaultCurrent((XML_Parser) userData); 274104349Sphk} 275104349Sphk 276178848Scokanestatic void XMLCALL 277104349SphknopCharacterData(void *userData, const XML_Char *s, int len) 278104349Sphk{ 279104349Sphk} 280104349Sphk 281178848Scokanestatic void XMLCALL 282104349SphknopStartElement(void *userData, const XML_Char *name, const XML_Char **atts) 283104349Sphk{ 284104349Sphk} 285104349Sphk 286178848Scokanestatic void XMLCALL 287104349SphknopEndElement(void *userData, const XML_Char *name) 288104349Sphk{ 289104349Sphk} 290104349Sphk 291178848Scokanestatic void XMLCALL 292104349SphknopProcessingInstruction(void *userData, const XML_Char *target, 293104349Sphk const XML_Char *data) 294104349Sphk{ 295104349Sphk} 296104349Sphk 297178848Scokanestatic void XMLCALL 298104349Sphkmarkup(void *userData, const XML_Char *s, int len) 299104349Sphk{ 300178848Scokane FILE *fp = (FILE *)XML_GetUserData((XML_Parser) userData); 301104349Sphk for (; len > 0; --len, ++s) 302104349Sphk puttc(*s, fp); 303104349Sphk} 304104349Sphk 305104349Sphkstatic void 306104349SphkmetaLocation(XML_Parser parser) 307104349Sphk{ 308104349Sphk const XML_Char *uri = XML_GetBase(parser); 309104349Sphk if (uri) 310178848Scokane ftprintf((FILE *)XML_GetUserData(parser), T(" uri=\"%s\""), uri); 311178848Scokane ftprintf((FILE *)XML_GetUserData(parser), 312178848Scokane T(" byte=\"%" XML_FMT_INT_MOD "d\" nbytes=\"%d\" \ 313178848Scokane line=\"%" XML_FMT_INT_MOD "u\" col=\"%" XML_FMT_INT_MOD "u\""), 314104349Sphk XML_GetCurrentByteIndex(parser), 315104349Sphk XML_GetCurrentByteCount(parser), 316104349Sphk XML_GetCurrentLineNumber(parser), 317104349Sphk XML_GetCurrentColumnNumber(parser)); 318104349Sphk} 319104349Sphk 320104349Sphkstatic void 321104349SphkmetaStartDocument(void *userData) 322104349Sphk{ 323178848Scokane fputts(T("<document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData)); 324104349Sphk} 325104349Sphk 326104349Sphkstatic void 327104349SphkmetaEndDocument(void *userData) 328104349Sphk{ 329178848Scokane fputts(T("</document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData)); 330104349Sphk} 331104349Sphk 332178848Scokanestatic void XMLCALL 333104349SphkmetaStartElement(void *userData, const XML_Char *name, 334104349Sphk const XML_Char **atts) 335104349Sphk{ 336104349Sphk XML_Parser parser = (XML_Parser) userData; 337178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 338104349Sphk const XML_Char **specifiedAttsEnd 339104349Sphk = atts + XML_GetSpecifiedAttributeCount(parser); 340104349Sphk const XML_Char **idAttPtr; 341104349Sphk int idAttIndex = XML_GetIdAttributeIndex(parser); 342104349Sphk if (idAttIndex < 0) 343104349Sphk idAttPtr = 0; 344104349Sphk else 345104349Sphk idAttPtr = atts + idAttIndex; 346104349Sphk 347104349Sphk ftprintf(fp, T("<starttag name=\"%s\""), name); 348104349Sphk metaLocation(parser); 349104349Sphk if (*atts) { 350104349Sphk fputts(T(">\n"), fp); 351104349Sphk do { 352104349Sphk ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]); 353178848Scokane characterData(fp, atts[1], (int)tcslen(atts[1])); 354104349Sphk if (atts >= specifiedAttsEnd) 355104349Sphk fputts(T("\" defaulted=\"yes\"/>\n"), fp); 356104349Sphk else if (atts == idAttPtr) 357104349Sphk fputts(T("\" id=\"yes\"/>\n"), fp); 358104349Sphk else 359104349Sphk fputts(T("\"/>\n"), fp); 360104349Sphk } while (*(atts += 2)); 361104349Sphk fputts(T("</starttag>\n"), fp); 362104349Sphk } 363104349Sphk else 364104349Sphk fputts(T("/>\n"), fp); 365104349Sphk} 366104349Sphk 367178848Scokanestatic void XMLCALL 368104349SphkmetaEndElement(void *userData, const XML_Char *name) 369104349Sphk{ 370104349Sphk XML_Parser parser = (XML_Parser) userData; 371178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 372104349Sphk ftprintf(fp, T("<endtag name=\"%s\""), name); 373104349Sphk metaLocation(parser); 374104349Sphk fputts(T("/>\n"), fp); 375104349Sphk} 376104349Sphk 377178848Scokanestatic void XMLCALL 378104349SphkmetaProcessingInstruction(void *userData, const XML_Char *target, 379104349Sphk const XML_Char *data) 380104349Sphk{ 381104349Sphk XML_Parser parser = (XML_Parser) userData; 382178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 383104349Sphk ftprintf(fp, T("<pi target=\"%s\" data=\""), target); 384178848Scokane characterData(fp, data, (int)tcslen(data)); 385104349Sphk puttc(T('"'), fp); 386104349Sphk metaLocation(parser); 387104349Sphk fputts(T("/>\n"), fp); 388104349Sphk} 389104349Sphk 390178848Scokanestatic void XMLCALL 391104349SphkmetaComment(void *userData, const XML_Char *data) 392104349Sphk{ 393104349Sphk XML_Parser parser = (XML_Parser) userData; 394178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 395104349Sphk fputts(T("<comment data=\""), fp); 396178848Scokane characterData(fp, data, (int)tcslen(data)); 397104349Sphk puttc(T('"'), fp); 398104349Sphk metaLocation(parser); 399104349Sphk fputts(T("/>\n"), fp); 400104349Sphk} 401104349Sphk 402178848Scokanestatic void XMLCALL 403104349SphkmetaStartCdataSection(void *userData) 404104349Sphk{ 405104349Sphk XML_Parser parser = (XML_Parser) userData; 406178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 407104349Sphk fputts(T("<startcdata"), fp); 408104349Sphk metaLocation(parser); 409104349Sphk fputts(T("/>\n"), fp); 410104349Sphk} 411104349Sphk 412178848Scokanestatic void XMLCALL 413104349SphkmetaEndCdataSection(void *userData) 414104349Sphk{ 415104349Sphk XML_Parser parser = (XML_Parser) userData; 416178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 417104349Sphk fputts(T("<endcdata"), fp); 418104349Sphk metaLocation(parser); 419104349Sphk fputts(T("/>\n"), fp); 420104349Sphk} 421104349Sphk 422178848Scokanestatic void XMLCALL 423104349SphkmetaCharacterData(void *userData, const XML_Char *s, int len) 424104349Sphk{ 425104349Sphk XML_Parser parser = (XML_Parser) userData; 426178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 427104349Sphk fputts(T("<chars str=\""), fp); 428104349Sphk characterData(fp, s, len); 429104349Sphk puttc(T('"'), fp); 430104349Sphk metaLocation(parser); 431104349Sphk fputts(T("/>\n"), fp); 432104349Sphk} 433104349Sphk 434178848Scokanestatic void XMLCALL 435104349SphkmetaStartDoctypeDecl(void *userData, 436104349Sphk const XML_Char *doctypeName, 437104349Sphk const XML_Char *sysid, 438104349Sphk const XML_Char *pubid, 439104349Sphk int has_internal_subset) 440104349Sphk{ 441104349Sphk XML_Parser parser = (XML_Parser) userData; 442178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 443104349Sphk ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName); 444104349Sphk metaLocation(parser); 445104349Sphk fputts(T("/>\n"), fp); 446104349Sphk} 447104349Sphk 448178848Scokanestatic void XMLCALL 449104349SphkmetaEndDoctypeDecl(void *userData) 450104349Sphk{ 451104349Sphk XML_Parser parser = (XML_Parser) userData; 452178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 453104349Sphk fputts(T("<enddoctype"), fp); 454104349Sphk metaLocation(parser); 455104349Sphk fputts(T("/>\n"), fp); 456104349Sphk} 457104349Sphk 458178848Scokanestatic void XMLCALL 459104349SphkmetaNotationDecl(void *userData, 460104349Sphk const XML_Char *notationName, 461104349Sphk const XML_Char *base, 462104349Sphk const XML_Char *systemId, 463104349Sphk const XML_Char *publicId) 464104349Sphk{ 465104349Sphk XML_Parser parser = (XML_Parser) userData; 466178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 467104349Sphk ftprintf(fp, T("<notation name=\"%s\""), notationName); 468104349Sphk if (publicId) 469104349Sphk ftprintf(fp, T(" public=\"%s\""), publicId); 470104349Sphk if (systemId) { 471104349Sphk fputts(T(" system=\""), fp); 472178848Scokane characterData(fp, systemId, (int)tcslen(systemId)); 473104349Sphk puttc(T('"'), fp); 474104349Sphk } 475104349Sphk metaLocation(parser); 476104349Sphk fputts(T("/>\n"), fp); 477104349Sphk} 478104349Sphk 479104349Sphk 480178848Scokanestatic void XMLCALL 481104349SphkmetaEntityDecl(void *userData, 482104349Sphk const XML_Char *entityName, 483104349Sphk int is_param, 484104349Sphk const XML_Char *value, 485104349Sphk int value_length, 486104349Sphk const XML_Char *base, 487104349Sphk const XML_Char *systemId, 488104349Sphk const XML_Char *publicId, 489104349Sphk const XML_Char *notationName) 490104349Sphk{ 491104349Sphk XML_Parser parser = (XML_Parser) userData; 492178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 493104349Sphk 494104349Sphk if (value) { 495104349Sphk ftprintf(fp, T("<entity name=\"%s\""), entityName); 496104349Sphk metaLocation(parser); 497104349Sphk puttc(T('>'), fp); 498104349Sphk characterData(fp, value, value_length); 499104349Sphk fputts(T("</entity/>\n"), fp); 500104349Sphk } 501104349Sphk else if (notationName) { 502104349Sphk ftprintf(fp, T("<entity name=\"%s\""), entityName); 503104349Sphk if (publicId) 504104349Sphk ftprintf(fp, T(" public=\"%s\""), publicId); 505104349Sphk fputts(T(" system=\""), fp); 506178848Scokane characterData(fp, systemId, (int)tcslen(systemId)); 507104349Sphk puttc(T('"'), fp); 508104349Sphk ftprintf(fp, T(" notation=\"%s\""), notationName); 509104349Sphk metaLocation(parser); 510104349Sphk fputts(T("/>\n"), fp); 511104349Sphk } 512104349Sphk else { 513104349Sphk ftprintf(fp, T("<entity name=\"%s\""), entityName); 514104349Sphk if (publicId) 515104349Sphk ftprintf(fp, T(" public=\"%s\""), publicId); 516104349Sphk fputts(T(" system=\""), fp); 517178848Scokane characterData(fp, systemId, (int)tcslen(systemId)); 518104349Sphk puttc(T('"'), fp); 519104349Sphk metaLocation(parser); 520104349Sphk fputts(T("/>\n"), fp); 521104349Sphk } 522104349Sphk} 523104349Sphk 524178848Scokanestatic void XMLCALL 525104349SphkmetaStartNamespaceDecl(void *userData, 526104349Sphk const XML_Char *prefix, 527104349Sphk const XML_Char *uri) 528104349Sphk{ 529104349Sphk XML_Parser parser = (XML_Parser) userData; 530178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 531104349Sphk fputts(T("<startns"), fp); 532104349Sphk if (prefix) 533104349Sphk ftprintf(fp, T(" prefix=\"%s\""), prefix); 534104349Sphk if (uri) { 535104349Sphk fputts(T(" ns=\""), fp); 536178848Scokane characterData(fp, uri, (int)tcslen(uri)); 537104349Sphk fputts(T("\"/>\n"), fp); 538104349Sphk } 539104349Sphk else 540104349Sphk fputts(T("/>\n"), fp); 541104349Sphk} 542104349Sphk 543178848Scokanestatic void XMLCALL 544104349SphkmetaEndNamespaceDecl(void *userData, const XML_Char *prefix) 545104349Sphk{ 546104349Sphk XML_Parser parser = (XML_Parser) userData; 547178848Scokane FILE *fp = (FILE *)XML_GetUserData(parser); 548104349Sphk if (!prefix) 549104349Sphk fputts(T("<endns/>\n"), fp); 550104349Sphk else 551104349Sphk ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix); 552104349Sphk} 553104349Sphk 554178848Scokanestatic int XMLCALL 555104349SphkunknownEncodingConvert(void *data, const char *p) 556104349Sphk{ 557104349Sphk return codepageConvert(*(int *)data, p); 558104349Sphk} 559104349Sphk 560178848Scokanestatic int XMLCALL 561104349SphkunknownEncoding(void *userData, const XML_Char *name, XML_Encoding *info) 562104349Sphk{ 563104349Sphk int cp; 564104349Sphk static const XML_Char prefixL[] = T("windows-"); 565104349Sphk static const XML_Char prefixU[] = T("WINDOWS-"); 566104349Sphk int i; 567104349Sphk 568104349Sphk for (i = 0; prefixU[i]; i++) 569104349Sphk if (name[i] != prefixU[i] && name[i] != prefixL[i]) 570104349Sphk return 0; 571104349Sphk 572104349Sphk cp = 0; 573104349Sphk for (; name[i]; i++) { 574104349Sphk static const XML_Char digits[] = T("0123456789"); 575104349Sphk const XML_Char *s = tcschr(digits, name[i]); 576104349Sphk if (!s) 577104349Sphk return 0; 578104349Sphk cp *= 10; 579178848Scokane cp += (int)(s - digits); 580104349Sphk if (cp >= 0x10000) 581104349Sphk return 0; 582104349Sphk } 583104349Sphk if (!codepageMap(cp, info->map)) 584104349Sphk return 0; 585104349Sphk info->convert = unknownEncodingConvert; 586104349Sphk /* We could just cast the code page integer to a void *, 587104349Sphk and avoid the use of release. */ 588104349Sphk info->release = free; 589104349Sphk info->data = malloc(sizeof(int)); 590104349Sphk if (!info->data) 591104349Sphk return 0; 592104349Sphk *(int *)info->data = cp; 593104349Sphk return 1; 594104349Sphk} 595104349Sphk 596178848Scokanestatic int XMLCALL 597104349SphknotStandalone(void *userData) 598104349Sphk{ 599104349Sphk return 0; 600104349Sphk} 601104349Sphk 602104349Sphkstatic void 603104349SphkshowVersion(XML_Char *prog) 604104349Sphk{ 605104349Sphk XML_Char *s = prog; 606104349Sphk XML_Char ch; 607104349Sphk const XML_Feature *features = XML_GetFeatureList(); 608104349Sphk while ((ch = *s) != 0) { 609104349Sphk if (ch == '/' 610178848Scokane#if (defined(WIN32) || defined(__WATCOMC__)) 611104349Sphk || ch == '\\' 612104349Sphk#endif 613104349Sphk ) 614104349Sphk prog = s + 1; 615104349Sphk ++s; 616104349Sphk } 617104349Sphk ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion()); 618104349Sphk if (features != NULL && features[0].feature != XML_FEATURE_END) { 619104349Sphk int i = 1; 620104349Sphk ftprintf(stdout, T("%s"), features[0].name); 621104349Sphk if (features[0].value) 622104349Sphk ftprintf(stdout, T("=%ld"), features[0].value); 623104349Sphk while (features[i].feature != XML_FEATURE_END) { 624104349Sphk ftprintf(stdout, T(", %s"), features[i].name); 625104349Sphk if (features[i].value) 626104349Sphk ftprintf(stdout, T("=%ld"), features[i].value); 627104349Sphk ++i; 628104349Sphk } 629104349Sphk ftprintf(stdout, T("\n")); 630104349Sphk } 631104349Sphk} 632104349Sphk 633104349Sphkstatic void 634104349Sphkusage(const XML_Char *prog, int rc) 635104349Sphk{ 636104349Sphk ftprintf(stderr, 637104349Sphk T("usage: %s [-n] [-p] [-r] [-s] [-w] [-x] [-d output-dir] " 638104349Sphk "[-e encoding] file ...\n"), prog); 639104349Sphk exit(rc); 640104349Sphk} 641104349Sphk 642104349Sphkint 643104349Sphktmain(int argc, XML_Char **argv) 644104349Sphk{ 645104349Sphk int i, j; 646104349Sphk const XML_Char *outputDir = NULL; 647104349Sphk const XML_Char *encoding = NULL; 648104349Sphk unsigned processFlags = XML_MAP_FILE; 649104349Sphk int windowsCodePages = 0; 650104349Sphk int outputType = 0; 651104349Sphk int useNamespaces = 0; 652104349Sphk int requireStandalone = 0; 653178848Scokane enum XML_ParamEntityParsing paramEntityParsing = 654178848Scokane XML_PARAM_ENTITY_PARSING_NEVER; 655104349Sphk int useStdin = 0; 656104349Sphk 657104349Sphk#ifdef _MSC_VER 658104349Sphk _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF); 659104349Sphk#endif 660104349Sphk 661104349Sphk i = 1; 662104349Sphk j = 0; 663104349Sphk while (i < argc) { 664104349Sphk if (j == 0) { 665104349Sphk if (argv[i][0] != T('-')) 666104349Sphk break; 667104349Sphk if (argv[i][1] == T('-') && argv[i][2] == T('\0')) { 668104349Sphk i++; 669104349Sphk break; 670104349Sphk } 671104349Sphk j++; 672104349Sphk } 673104349Sphk switch (argv[i][j]) { 674104349Sphk case T('r'): 675104349Sphk processFlags &= ~XML_MAP_FILE; 676104349Sphk j++; 677104349Sphk break; 678104349Sphk case T('s'): 679104349Sphk requireStandalone = 1; 680104349Sphk j++; 681104349Sphk break; 682104349Sphk case T('n'): 683104349Sphk useNamespaces = 1; 684104349Sphk j++; 685104349Sphk break; 686104349Sphk case T('p'): 687104349Sphk paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS; 688104349Sphk /* fall through */ 689104349Sphk case T('x'): 690104349Sphk processFlags |= XML_EXTERNAL_ENTITIES; 691104349Sphk j++; 692104349Sphk break; 693104349Sphk case T('w'): 694104349Sphk windowsCodePages = 1; 695104349Sphk j++; 696104349Sphk break; 697104349Sphk case T('m'): 698104349Sphk outputType = 'm'; 699104349Sphk j++; 700104349Sphk break; 701104349Sphk case T('c'): 702104349Sphk outputType = 'c'; 703104349Sphk useNamespaces = 0; 704104349Sphk j++; 705104349Sphk break; 706104349Sphk case T('t'): 707104349Sphk outputType = 't'; 708104349Sphk j++; 709104349Sphk break; 710104349Sphk case T('d'): 711104349Sphk if (argv[i][j + 1] == T('\0')) { 712104349Sphk if (++i == argc) 713104349Sphk usage(argv[0], 2); 714104349Sphk outputDir = argv[i]; 715104349Sphk } 716104349Sphk else 717104349Sphk outputDir = argv[i] + j + 1; 718104349Sphk i++; 719104349Sphk j = 0; 720104349Sphk break; 721104349Sphk case T('e'): 722104349Sphk if (argv[i][j + 1] == T('\0')) { 723104349Sphk if (++i == argc) 724104349Sphk usage(argv[0], 2); 725104349Sphk encoding = argv[i]; 726104349Sphk } 727104349Sphk else 728104349Sphk encoding = argv[i] + j + 1; 729104349Sphk i++; 730104349Sphk j = 0; 731104349Sphk break; 732104349Sphk case T('h'): 733104349Sphk usage(argv[0], 0); 734104349Sphk return 0; 735104349Sphk case T('v'): 736104349Sphk showVersion(argv[0]); 737104349Sphk return 0; 738104349Sphk case T('\0'): 739104349Sphk if (j > 1) { 740104349Sphk i++; 741104349Sphk j = 0; 742104349Sphk break; 743104349Sphk } 744104349Sphk /* fall through */ 745104349Sphk default: 746104349Sphk usage(argv[0], 2); 747104349Sphk } 748104349Sphk } 749104349Sphk if (i == argc) { 750104349Sphk useStdin = 1; 751104349Sphk processFlags &= ~XML_MAP_FILE; 752104349Sphk i--; 753104349Sphk } 754104349Sphk for (; i < argc; i++) { 755104349Sphk FILE *fp = 0; 756104349Sphk XML_Char *outName = 0; 757104349Sphk int result; 758104349Sphk XML_Parser parser; 759104349Sphk if (useNamespaces) 760104349Sphk parser = XML_ParserCreateNS(encoding, NSSEP); 761104349Sphk else 762104349Sphk parser = XML_ParserCreate(encoding); 763104349Sphk if (requireStandalone) 764104349Sphk XML_SetNotStandaloneHandler(parser, notStandalone); 765104349Sphk XML_SetParamEntityParsing(parser, paramEntityParsing); 766104349Sphk if (outputType == 't') { 767104349Sphk /* This is for doing timings; this gives a more realistic estimate of 768104349Sphk the parsing time. */ 769104349Sphk outputDir = 0; 770104349Sphk XML_SetElementHandler(parser, nopStartElement, nopEndElement); 771104349Sphk XML_SetCharacterDataHandler(parser, nopCharacterData); 772104349Sphk XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction); 773104349Sphk } 774104349Sphk else if (outputDir) { 775178848Scokane const XML_Char * delim = T("/"); 776104349Sphk const XML_Char *file = useStdin ? T("STDIN") : argv[i]; 777178848Scokane if (!useStdin) { 778178848Scokane /* Jump after last (back)slash */ 779178848Scokane const XML_Char * lastDelim = tcsrchr(file, delim[0]); 780178848Scokane if (lastDelim) 781178848Scokane file = lastDelim + 1; 782178848Scokane#if (defined(WIN32) || defined(__WATCOMC__)) 783178848Scokane else { 784178848Scokane const XML_Char * winDelim = T("\\"); 785178848Scokane lastDelim = tcsrchr(file, winDelim[0]); 786178848Scokane if (lastDelim) { 787178848Scokane file = lastDelim + 1; 788178848Scokane delim = winDelim; 789178848Scokane } 790178848Scokane } 791104349Sphk#endif 792178848Scokane } 793178848Scokane outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2) 794104349Sphk * sizeof(XML_Char)); 795104349Sphk tcscpy(outName, outputDir); 796178848Scokane tcscat(outName, delim); 797104349Sphk tcscat(outName, file); 798104349Sphk fp = tfopen(outName, T("wb")); 799104349Sphk if (!fp) { 800104349Sphk tperror(outName); 801104349Sphk exit(1); 802104349Sphk } 803104349Sphk setvbuf(fp, NULL, _IOFBF, 16384); 804104349Sphk#ifdef XML_UNICODE 805104349Sphk puttc(0xFEFF, fp); 806104349Sphk#endif 807104349Sphk XML_SetUserData(parser, fp); 808104349Sphk switch (outputType) { 809104349Sphk case 'm': 810104349Sphk XML_UseParserAsHandlerArg(parser); 811104349Sphk XML_SetElementHandler(parser, metaStartElement, metaEndElement); 812104349Sphk XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction); 813104349Sphk XML_SetCommentHandler(parser, metaComment); 814104349Sphk XML_SetCdataSectionHandler(parser, metaStartCdataSection, 815104349Sphk metaEndCdataSection); 816104349Sphk XML_SetCharacterDataHandler(parser, metaCharacterData); 817104349Sphk XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl, 818104349Sphk metaEndDoctypeDecl); 819104349Sphk XML_SetEntityDeclHandler(parser, metaEntityDecl); 820104349Sphk XML_SetNotationDeclHandler(parser, metaNotationDecl); 821104349Sphk XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl, 822104349Sphk metaEndNamespaceDecl); 823104349Sphk metaStartDocument(parser); 824104349Sphk break; 825104349Sphk case 'c': 826104349Sphk XML_UseParserAsHandlerArg(parser); 827104349Sphk XML_SetDefaultHandler(parser, markup); 828104349Sphk XML_SetElementHandler(parser, defaultStartElement, defaultEndElement); 829104349Sphk XML_SetCharacterDataHandler(parser, defaultCharacterData); 830104349Sphk XML_SetProcessingInstructionHandler(parser, 831104349Sphk defaultProcessingInstruction); 832104349Sphk break; 833104349Sphk default: 834104349Sphk if (useNamespaces) 835104349Sphk XML_SetElementHandler(parser, startElementNS, endElementNS); 836104349Sphk else 837104349Sphk XML_SetElementHandler(parser, startElement, endElement); 838104349Sphk XML_SetCharacterDataHandler(parser, characterData); 839104349Sphk#ifndef W3C14N 840104349Sphk XML_SetProcessingInstructionHandler(parser, processingInstruction); 841104349Sphk#endif /* not W3C14N */ 842104349Sphk break; 843104349Sphk } 844104349Sphk } 845104349Sphk if (windowsCodePages) 846104349Sphk XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0); 847104349Sphk result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags); 848104349Sphk if (outputDir) { 849104349Sphk if (outputType == 'm') 850104349Sphk metaEndDocument(parser); 851104349Sphk fclose(fp); 852247296Sdelphij if (!result) { 853104349Sphk tremove(outName); 854247296Sdelphij exit(2); 855247296Sdelphij } 856104349Sphk free(outName); 857104349Sphk } 858104349Sphk XML_ParserFree(parser); 859104349Sphk } 860104349Sphk return 0; 861104349Sphk} 862