xmlwf.c revision 1.1.1.3.4.1 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