4 / _ \\ /| '_ \ / _` | __|
5 | __// \| |_) | (_| | |_
6 \___/_/\_\ .__/ \__,_|\__|
9 Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
10 Copyright (c) 2000-2017 Expat development team
11 Licensed under the MIT license:
13 Permission is hereby granted, free of charge, to any person obtaining
14 a copy of this software and associated documentation files (the
15 "Software"), to deal in the Software without restriction, including
16 without limitation the rights to use, copy, modify, merge, publish,
17 distribute, sublicense, and/or sell copies of the Software, and to permit
18 persons to whom the Software is furnished to do so, subject to the
21 The above copyright notice and this permission notice shall be included
22 in all copies or substantial portions of the Software.
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
29 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30 USE OR OTHER DEALINGS IN THE SOFTWARE.
40 #include "internal.h" /* for UNUSED_P only */
48 /* This ensures proper sorting. */
50 #define NSSEP T('\001')
53 characterData(void *userData, const XML_Char *s, int len)
55 FILE *fp = (FILE *)userData;
56 for (; len > 0; --len, ++s) {
59 fputts(T("&"), fp);
62 fputts(T("<"), fp);
65 fputts(T(">"), fp);
69 fputts(T("
"), fp);
73 fputts(T("""), fp);
78 ftprintf(fp, T("&#%d;"), *s);
89 attributeValue(FILE *fp, const XML_Char *s)
100 fputts(T("&"), fp);
103 fputts(T("<"), fp);
106 fputts(T("""), fp);
110 fputts(T("	"), fp);
113 fputts(T("
"), fp);
116 fputts(T("
"), fp);
120 fputts(T(">"), fp);
125 ftprintf(fp, T("&#%d;"), *s);
136 /* Lexicographically comparing UTF-8 encoded attribute values,
137 is equivalent to lexicographically comparing based on the character number. */
140 attcmp(const void *att1, const void *att2)
142 return tcscmp(*(const XML_Char **)att1, *(const XML_Char **)att2);
146 startElement(void *userData, const XML_Char *name, const XML_Char **atts)
150 FILE *fp = (FILE *)userData;
157 nAtts = (int)((p - atts) >> 1);
159 qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, attcmp);
163 attributeValue(fp, *atts);
170 endElement(void *userData, const XML_Char *name)
172 FILE *fp = (FILE *)userData;
180 nsattcmp(const void *p1, const void *p2)
182 const XML_Char *att1 = *(const XML_Char **)p1;
183 const XML_Char *att2 = *(const XML_Char **)p2;
184 int sep1 = (tcsrchr(att1, NSSEP) != 0);
185 int sep2 = (tcsrchr(att1, NSSEP) != 0);
188 return tcscmp(att1, att2);
192 startElementNS(void *userData, const XML_Char *name, const XML_Char **atts)
197 FILE *fp = (FILE *)userData;
201 sep = tcsrchr(name, NSSEP);
203 fputts(T("n1:"), fp);
205 fputts(T(" xmlns:n1"), fp);
206 attributeValue(fp, name);
217 nAtts = (int)((p - atts) >> 1);
219 qsort((void *)atts, nAtts, sizeof(XML_Char *) * 2, nsattcmp);
222 sep = tcsrchr(name, NSSEP);
225 ftprintf(fp, T("n%d:"), nsi);
230 attributeValue(fp, *atts);
232 ftprintf(fp, T(" xmlns:n%d"), nsi++);
233 attributeValue(fp, name);
241 endElementNS(void *userData, const XML_Char *name)
243 FILE *fp = (FILE *)userData;
247 sep = tcsrchr(name, NSSEP);
249 fputts(T("n1:"), fp);
260 processingInstruction(void *userData, const XML_Char *target,
261 const XML_Char *data)
263 FILE *fp = (FILE *)userData;
273 #endif /* not W3C14N */
276 defaultCharacterData(void *userData, const XML_Char *UNUSED_P(s), int UNUSED_P(len))
278 XML_DefaultCurrent((XML_Parser) userData);
282 defaultStartElement(void *userData, const XML_Char *UNUSED_P(name),
283 const XML_Char **UNUSED_P(atts))
285 XML_DefaultCurrent((XML_Parser) userData);
289 defaultEndElement(void *userData, const XML_Char *UNUSED_P(name))
291 XML_DefaultCurrent((XML_Parser) userData);
295 defaultProcessingInstruction(void *userData, const XML_Char *UNUSED_P(target),
296 const XML_Char *UNUSED_P(data))
298 XML_DefaultCurrent((XML_Parser) userData);
302 nopCharacterData(void *UNUSED_P(userData), const XML_Char *UNUSED_P(s), int UNUSED_P(len))
307 nopStartElement(void *UNUSED_P(userData), const XML_Char *UNUSED_P(name), const XML_Char **UNUSED_P(atts))
312 nopEndElement(void *UNUSED_P(userData), const XML_Char *UNUSED_P(name))
317 nopProcessingInstruction(void *UNUSED_P(userData), const XML_Char *UNUSED_P(target),
318 const XML_Char *UNUSED_P(data))
323 markup(void *userData, const XML_Char *s, int len)
325 FILE *fp = (FILE *)XML_GetUserData((XML_Parser) userData);
326 for (; len > 0; --len, ++s)
331 metaLocation(XML_Parser parser)
333 const XML_Char *uri = XML_GetBase(parser);
335 ftprintf((FILE *)XML_GetUserData(parser), T(" uri=\"%s\""), uri);
336 ftprintf((FILE *)XML_GetUserData(parser),
337 T(" byte=\"%" XML_FMT_INT_MOD "d\" nbytes=\"%d\" \
338 line=\"%" XML_FMT_INT_MOD "u\" col=\"%" XML_FMT_INT_MOD "u\""),
339 XML_GetCurrentByteIndex(parser),
340 XML_GetCurrentByteCount(parser),
341 XML_GetCurrentLineNumber(parser),
342 XML_GetCurrentColumnNumber(parser));
346 metaStartDocument(void *userData)
348 fputts(T("<document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
352 metaEndDocument(void *userData)
354 fputts(T("</document>\n"), (FILE *)XML_GetUserData((XML_Parser) userData));
358 metaStartElement(void *userData, const XML_Char *name,
359 const XML_Char **atts)
361 XML_Parser parser = (XML_Parser) userData;
362 FILE *fp = (FILE *)XML_GetUserData(parser);
363 const XML_Char **specifiedAttsEnd
364 = atts + XML_GetSpecifiedAttributeCount(parser);
365 const XML_Char **idAttPtr;
366 int idAttIndex = XML_GetIdAttributeIndex(parser);
370 idAttPtr = atts + idAttIndex;
372 ftprintf(fp, T("<starttag name=\"%s\""), name);
373 metaLocation(parser);
375 fputts(T(">\n"), fp);
377 ftprintf(fp, T("<attribute name=\"%s\" value=\""), atts[0]);
378 characterData(fp, atts[1], (int)tcslen(atts[1]));
379 if (atts >= specifiedAttsEnd)
380 fputts(T("\" defaulted=\"yes\"/>\n"), fp);
381 else if (atts == idAttPtr)
382 fputts(T("\" id=\"yes\"/>\n"), fp);
384 fputts(T("\"/>\n"), fp);
385 } while (*(atts += 2));
386 fputts(T("</starttag>\n"), fp);
389 fputts(T("/>\n"), fp);
393 metaEndElement(void *userData, const XML_Char *name)
395 XML_Parser parser = (XML_Parser) userData;
396 FILE *fp = (FILE *)XML_GetUserData(parser);
397 ftprintf(fp, T("<endtag name=\"%s\""), name);
398 metaLocation(parser);
399 fputts(T("/>\n"), fp);
403 metaProcessingInstruction(void *userData, const XML_Char *target,
404 const XML_Char *data)
406 XML_Parser parser = (XML_Parser) userData;
407 FILE *fp = (FILE *)XML_GetUserData(parser);
408 ftprintf(fp, T("<pi target=\"%s\" data=\""), target);
409 characterData(fp, data, (int)tcslen(data));
411 metaLocation(parser);
412 fputts(T("/>\n"), fp);
416 metaComment(void *userData, const XML_Char *data)
418 XML_Parser parser = (XML_Parser) userData;
419 FILE *fp = (FILE *)XML_GetUserData(parser);
420 fputts(T("<comment data=\""), fp);
421 characterData(fp, data, (int)tcslen(data));
423 metaLocation(parser);
424 fputts(T("/>\n"), fp);
428 metaStartCdataSection(void *userData)
430 XML_Parser parser = (XML_Parser) userData;
431 FILE *fp = (FILE *)XML_GetUserData(parser);
432 fputts(T("<startcdata"), fp);
433 metaLocation(parser);
434 fputts(T("/>\n"), fp);
438 metaEndCdataSection(void *userData)
440 XML_Parser parser = (XML_Parser) userData;
441 FILE *fp = (FILE *)XML_GetUserData(parser);
442 fputts(T("<endcdata"), fp);
443 metaLocation(parser);
444 fputts(T("/>\n"), fp);
448 metaCharacterData(void *userData, const XML_Char *s, int len)
450 XML_Parser parser = (XML_Parser) userData;
451 FILE *fp = (FILE *)XML_GetUserData(parser);
452 fputts(T("<chars str=\""), fp);
453 characterData(fp, s, len);
455 metaLocation(parser);
456 fputts(T("/>\n"), fp);
460 metaStartDoctypeDecl(void *userData,
461 const XML_Char *doctypeName,
462 const XML_Char *UNUSED_P(sysid),
463 const XML_Char *UNUSED_P(pubid),
464 int UNUSED_P(has_internal_subset))
466 XML_Parser parser = (XML_Parser) userData;
467 FILE *fp = (FILE *)XML_GetUserData(parser);
468 ftprintf(fp, T("<startdoctype name=\"%s\""), doctypeName);
469 metaLocation(parser);
470 fputts(T("/>\n"), fp);
474 metaEndDoctypeDecl(void *userData)
476 XML_Parser parser = (XML_Parser) userData;
477 FILE *fp = (FILE *)XML_GetUserData(parser);
478 fputts(T("<enddoctype"), fp);
479 metaLocation(parser);
480 fputts(T("/>\n"), fp);
484 metaNotationDecl(void *userData,
485 const XML_Char *notationName,
486 const XML_Char *UNUSED_P(base),
487 const XML_Char *systemId,
488 const XML_Char *publicId)
490 XML_Parser parser = (XML_Parser) userData;
491 FILE *fp = (FILE *)XML_GetUserData(parser);
492 ftprintf(fp, T("<notation name=\"%s\""), notationName);
494 ftprintf(fp, T(" public=\"%s\""), publicId);
496 fputts(T(" system=\""), fp);
497 characterData(fp, systemId, (int)tcslen(systemId));
500 metaLocation(parser);
501 fputts(T("/>\n"), fp);
506 metaEntityDecl(void *userData,
507 const XML_Char *entityName,
508 int UNUSED_P(is_param),
509 const XML_Char *value,
511 const XML_Char *UNUSED_P(base),
512 const XML_Char *systemId,
513 const XML_Char *publicId,
514 const XML_Char *notationName)
516 XML_Parser parser = (XML_Parser) userData;
517 FILE *fp = (FILE *)XML_GetUserData(parser);
520 ftprintf(fp, T("<entity name=\"%s\""), entityName);
521 metaLocation(parser);
523 characterData(fp, value, value_length);
524 fputts(T("</entity/>\n"), fp);
526 else if (notationName) {
527 ftprintf(fp, T("<entity name=\"%s\""), entityName);
529 ftprintf(fp, T(" public=\"%s\""), publicId);
530 fputts(T(" system=\""), fp);
531 characterData(fp, systemId, (int)tcslen(systemId));
533 ftprintf(fp, T(" notation=\"%s\""), notationName);
534 metaLocation(parser);
535 fputts(T("/>\n"), fp);
538 ftprintf(fp, T("<entity name=\"%s\""), entityName);
540 ftprintf(fp, T(" public=\"%s\""), publicId);
541 fputts(T(" system=\""), fp);
542 characterData(fp, systemId, (int)tcslen(systemId));
544 metaLocation(parser);
545 fputts(T("/>\n"), fp);
550 metaStartNamespaceDecl(void *userData,
551 const XML_Char *prefix,
554 XML_Parser parser = (XML_Parser) userData;
555 FILE *fp = (FILE *)XML_GetUserData(parser);
556 fputts(T("<startns"), fp);
558 ftprintf(fp, T(" prefix=\"%s\""), prefix);
560 fputts(T(" ns=\""), fp);
561 characterData(fp, uri, (int)tcslen(uri));
562 fputts(T("\"/>\n"), fp);
565 fputts(T("/>\n"), fp);
569 metaEndNamespaceDecl(void *userData, const XML_Char *prefix)
571 XML_Parser parser = (XML_Parser) userData;
572 FILE *fp = (FILE *)XML_GetUserData(parser);
574 fputts(T("<endns/>\n"), fp);
576 ftprintf(fp, T("<endns prefix=\"%s\"/>\n"), prefix);
580 unknownEncodingConvert(void *data, const char *p)
582 return codepageConvert(*(int *)data, p);
586 unknownEncoding(void *UNUSED_P(userData), const XML_Char *name, XML_Encoding *info)
589 static const XML_Char prefixL[] = T("windows-");
590 static const XML_Char prefixU[] = T("WINDOWS-");
593 for (i = 0; prefixU[i]; i++)
594 if (name[i] != prefixU[i] && name[i] != prefixL[i])
598 for (; name[i]; i++) {
599 static const XML_Char digits[] = T("0123456789");
600 const XML_Char *s = tcschr(digits, name[i]);
604 cp += (int)(s - digits);
608 if (!codepageMap(cp, info->map))
610 info->convert = unknownEncodingConvert;
611 /* We could just cast the code page integer to a void *,
612 and avoid the use of release. */
613 info->release = free;
614 info->data = malloc(sizeof(int));
617 *(int *)info->data = cp;
622 notStandalone(void *UNUSED_P(userData))
628 showVersion(XML_Char *prog)
632 const XML_Feature *features = XML_GetFeatureList();
633 while ((ch = *s) != 0) {
642 ftprintf(stdout, T("%s using %s\n"), prog, XML_ExpatVersion());
643 if (features != NULL && features[0].feature != XML_FEATURE_END) {
645 ftprintf(stdout, T("%s"), features[0].name);
646 if (features[0].value)
647 ftprintf(stdout, T("=%ld"), features[0].value);
648 while (features[i].feature != XML_FEATURE_END) {
649 ftprintf(stdout, T(", %s"), features[i].name);
650 if (features[i].value)
651 ftprintf(stdout, T("=%ld"), features[i].value);
654 ftprintf(stdout, T("\n"));
659 usage(const XML_Char *prog, int rc)
662 T("usage: %s [-s] [-n] [-p] [-x] [-e encoding] [-w] [-d output-dir] [-c] [-m] [-r] [-t] [file ...]\n"), prog);
667 tmain(int argc, XML_Char **argv)
670 const XML_Char *outputDir = NULL;
671 const XML_Char *encoding = NULL;
672 unsigned processFlags = XML_MAP_FILE;
673 int windowsCodePages = 0;
675 int useNamespaces = 0;
676 int requireStandalone = 0;
677 enum XML_ParamEntityParsing paramEntityParsing =
678 XML_PARAM_ENTITY_PARSING_NEVER;
682 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
689 if (argv[i][0] != T('-'))
691 if (argv[i][1] == T('-') && argv[i][2] == T('\0')) {
697 switch (argv[i][j]) {
699 processFlags &= ~XML_MAP_FILE;
703 requireStandalone = 1;
711 paramEntityParsing = XML_PARAM_ENTITY_PARSING_ALWAYS;
714 processFlags |= XML_EXTERNAL_ENTITIES;
718 windowsCodePages = 1;
735 if (argv[i][j + 1] == T('\0')) {
741 outputDir = argv[i] + j + 1;
746 if (argv[i][j + 1] == T('\0')) {
752 encoding = argv[i] + j + 1;
760 showVersion(argv[0]);
775 processFlags &= ~XML_MAP_FILE;
778 for (; i < argc; i++) {
780 XML_Char *outName = 0;
784 parser = XML_ParserCreateNS(encoding, NSSEP);
786 parser = XML_ParserCreate(encoding);
789 tperror("Could not instantiate parser");
793 if (requireStandalone)
794 XML_SetNotStandaloneHandler(parser, notStandalone);
795 XML_SetParamEntityParsing(parser, paramEntityParsing);
796 if (outputType == 't') {
797 /* This is for doing timings; this gives a more realistic estimate of
800 XML_SetElementHandler(parser, nopStartElement, nopEndElement);
801 XML_SetCharacterDataHandler(parser, nopCharacterData);
802 XML_SetProcessingInstructionHandler(parser, nopProcessingInstruction);
804 else if (outputDir) {
805 const XML_Char * delim = T("/");
806 const XML_Char *file = useStdin ? T("STDIN") : argv[i];
808 /* Jump after last (back)slash */
809 const XML_Char * lastDelim = tcsrchr(file, delim[0]);
811 file = lastDelim + 1;
814 const XML_Char * winDelim = T("\\");
815 lastDelim = tcsrchr(file, winDelim[0]);
817 file = lastDelim + 1;
823 outName = (XML_Char *)malloc((tcslen(outputDir) + tcslen(file) + 2)
825 tcscpy(outName, outputDir);
826 tcscat(outName, delim);
827 tcscat(outName, file);
828 fp = tfopen(outName, T("wb"));
833 setvbuf(fp, NULL, _IOFBF, 16384);
837 XML_SetUserData(parser, fp);
838 switch (outputType) {
840 XML_UseParserAsHandlerArg(parser);
841 XML_SetElementHandler(parser, metaStartElement, metaEndElement);
842 XML_SetProcessingInstructionHandler(parser, metaProcessingInstruction);
843 XML_SetCommentHandler(parser, metaComment);
844 XML_SetCdataSectionHandler(parser, metaStartCdataSection,
845 metaEndCdataSection);
846 XML_SetCharacterDataHandler(parser, metaCharacterData);
847 XML_SetDoctypeDeclHandler(parser, metaStartDoctypeDecl,
849 XML_SetEntityDeclHandler(parser, metaEntityDecl);
850 XML_SetNotationDeclHandler(parser, metaNotationDecl);
851 XML_SetNamespaceDeclHandler(parser, metaStartNamespaceDecl,
852 metaEndNamespaceDecl);
853 metaStartDocument(parser);
856 XML_UseParserAsHandlerArg(parser);
857 XML_SetDefaultHandler(parser, markup);
858 XML_SetElementHandler(parser, defaultStartElement, defaultEndElement);
859 XML_SetCharacterDataHandler(parser, defaultCharacterData);
860 XML_SetProcessingInstructionHandler(parser,
861 defaultProcessingInstruction);
865 XML_SetElementHandler(parser, startElementNS, endElementNS);
867 XML_SetElementHandler(parser, startElement, endElement);
868 XML_SetCharacterDataHandler(parser, characterData);
870 XML_SetProcessingInstructionHandler(parser, processingInstruction);
871 #endif /* not W3C14N */
875 if (windowsCodePages)
876 XML_SetUnknownEncodingHandler(parser, unknownEncoding, 0);
877 result = XML_ProcessFile(parser, useStdin ? NULL : argv[i], processFlags);
879 if (outputType == 'm')
880 metaEndDocument(parser);
888 XML_ParserFree(parser);