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