12e724bc9Sbluhm /* Read an XML document from standard input and print an element
22e724bc9Sbluhm outline on standard output.
32e724bc9Sbluhm Must be used with Expat compiled for UTF-8 output.
42e724bc9Sbluhm __ __ _
52e724bc9Sbluhm ___\ \/ /_ __ __ _| |_
62e724bc9Sbluhm / _ \\ /| '_ \ / _` | __|
72e724bc9Sbluhm | __// \| |_) | (_| | |_
82e724bc9Sbluhm \___/_/\_\ .__/ \__,_|\__|
92e724bc9Sbluhm |_| XML parser
101a3ddf8cSespie
1108819b41Sbluhm Copyright (c) 2000 Clark Cooper <coopercc@users.sourceforge.net>
1208819b41Sbluhm Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
13253fd6bfSbluhm Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
1408819b41Sbluhm Copyright (c) 2005-2006 Karl Waclawek <karl@waclawek.net>
15*751a8f41Sbluhm Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
1608819b41Sbluhm Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
172e724bc9Sbluhm Licensed under the MIT license:
182e724bc9Sbluhm
192e724bc9Sbluhm Permission is hereby granted, free of charge, to any person obtaining
202e724bc9Sbluhm a copy of this software and associated documentation files (the
212e724bc9Sbluhm "Software"), to deal in the Software without restriction, including
222e724bc9Sbluhm without limitation the rights to use, copy, modify, merge, publish,
232e724bc9Sbluhm distribute, sublicense, and/or sell copies of the Software, and to permit
242e724bc9Sbluhm persons to whom the Software is furnished to do so, subject to the
252e724bc9Sbluhm following conditions:
262e724bc9Sbluhm
272e724bc9Sbluhm The above copyright notice and this permission notice shall be included
282e724bc9Sbluhm in all copies or substantial portions of the Software.
292e724bc9Sbluhm
302e724bc9Sbluhm THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
312e724bc9Sbluhm EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
322e724bc9Sbluhm MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
332e724bc9Sbluhm NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
342e724bc9Sbluhm DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
352e724bc9Sbluhm OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
362e724bc9Sbluhm USE OR OTHER DEALINGS IN THE SOFTWARE.
372e724bc9Sbluhm */
381a3ddf8cSespie
391a3ddf8cSespie #include <stdio.h>
401a3ddf8cSespie #include <expat.h>
411a3ddf8cSespie
427d36914fSalek #ifdef XML_LARGE_SIZE
437d36914fSalek # define XML_FMT_INT_MOD "ll"
447d36914fSalek #else
457d36914fSalek # define XML_FMT_INT_MOD "l"
467d36914fSalek #endif
477d36914fSalek
489b8e2351Sbluhm #ifdef XML_UNICODE_WCHAR_T
499b8e2351Sbluhm # define XML_FMT_STR "ls"
509b8e2351Sbluhm #else
519b8e2351Sbluhm # define XML_FMT_STR "s"
529b8e2351Sbluhm #endif
539b8e2351Sbluhm
547d36914fSalek static void XMLCALL
startElement(void * userData,const XML_Char * name,const XML_Char ** atts)55*751a8f41Sbluhm startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
561a3ddf8cSespie int i;
57*751a8f41Sbluhm int *const depthPtr = (int *)userData;
581a3ddf8cSespie
59*751a8f41Sbluhm for (i = 0; i < *depthPtr; i++)
601a3ddf8cSespie printf(" ");
611a3ddf8cSespie
62*751a8f41Sbluhm printf("%" XML_FMT_STR, name);
631a3ddf8cSespie
64*751a8f41Sbluhm for (i = 0; atts[i]; i += 2) {
65*751a8f41Sbluhm printf(" %" XML_FMT_STR "='%" XML_FMT_STR "'", atts[i], atts[i + 1]);
661a3ddf8cSespie }
671a3ddf8cSespie
681a3ddf8cSespie printf("\n");
69*751a8f41Sbluhm *depthPtr += 1;
701a3ddf8cSespie }
711a3ddf8cSespie
727d36914fSalek static void XMLCALL
endElement(void * userData,const XML_Char * name)73*751a8f41Sbluhm endElement(void *userData, const XML_Char *name) {
74*751a8f41Sbluhm int *const depthPtr = (int *)userData;
75*751a8f41Sbluhm (void)name;
762feb5d2aSbluhm
77*751a8f41Sbluhm *depthPtr -= 1;
781a3ddf8cSespie }
791a3ddf8cSespie
801a3ddf8cSespie int
main(void)81*751a8f41Sbluhm main(void) {
82*751a8f41Sbluhm XML_Parser parser = XML_ParserCreate(NULL);
83*751a8f41Sbluhm int done;
84*751a8f41Sbluhm int depth = 0;
852feb5d2aSbluhm
86*751a8f41Sbluhm if (! parser) {
871a3ddf8cSespie fprintf(stderr, "Couldn't allocate memory for parser\n");
88*751a8f41Sbluhm return 1;
891a3ddf8cSespie }
901a3ddf8cSespie
91*751a8f41Sbluhm XML_SetUserData(parser, &depth);
92*751a8f41Sbluhm XML_SetElementHandler(parser, startElement, endElement);
931a3ddf8cSespie
94*751a8f41Sbluhm do {
95*751a8f41Sbluhm void *const buf = XML_GetBuffer(parser, BUFSIZ);
96*751a8f41Sbluhm if (! buf) {
97*751a8f41Sbluhm fprintf(stderr, "Couldn't allocate memory for buffer\n");
98*751a8f41Sbluhm XML_ParserFree(parser);
99*751a8f41Sbluhm return 1;
100*751a8f41Sbluhm }
1011a3ddf8cSespie
102*751a8f41Sbluhm const size_t len = fread(buf, 1, BUFSIZ, stdin);
103*751a8f41Sbluhm
1041a3ddf8cSespie if (ferror(stdin)) {
1051a3ddf8cSespie fprintf(stderr, "Read error\n");
106*751a8f41Sbluhm XML_ParserFree(parser);
107*751a8f41Sbluhm return 1;
1081a3ddf8cSespie }
109*751a8f41Sbluhm
1101a3ddf8cSespie done = feof(stdin);
1111a3ddf8cSespie
112*751a8f41Sbluhm if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) {
1139b8e2351Sbluhm fprintf(stderr,
1149b8e2351Sbluhm "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n",
115*751a8f41Sbluhm XML_GetCurrentLineNumber(parser),
116*751a8f41Sbluhm XML_ErrorString(XML_GetErrorCode(parser)));
117*751a8f41Sbluhm XML_ParserFree(parser);
118*751a8f41Sbluhm return 1;
1191a3ddf8cSespie }
120*751a8f41Sbluhm } while (! done);
1211a3ddf8cSespie
122*751a8f41Sbluhm XML_ParserFree(parser);
1231a3ddf8cSespie return 0;
1241a3ddf8cSespie }
125