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