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