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