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 |
} |