xref: /openbsd-src/lib/libexpat/examples/outline.c (revision 751a8f41a926cac5cc0587722fe35d38520b2eb7)
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