xref: /freebsd/contrib/expat/examples/outline.c (revision dc58b3fca5e7a7bb1e9aa640667944d0fe0601cd)
10a48773fSEric van Gyzen /* Read an XML document from standard input and print an element
20a48773fSEric van Gyzen    outline on standard output.
30a48773fSEric van Gyzen    Must be used with Expat compiled for UTF-8 output.
40a48773fSEric van Gyzen                             __  __            _
50a48773fSEric van Gyzen                          ___\ \/ /_ __   __ _| |_
60a48773fSEric van Gyzen                         / _ \\  /| '_ \ / _` | __|
70a48773fSEric van Gyzen                        |  __//  \| |_) | (_| | |_
80a48773fSEric van Gyzen                         \___/_/\_\ .__/ \__,_|\__|
90a48773fSEric van Gyzen                                  |_| XML parser
105bb6a25fSPoul-Henning Kamp 
11cc68614dSXin LI    Copyright (c) 2000      Clark Cooper <coopercc@users.sourceforge.net>
12cc68614dSXin LI    Copyright (c) 2001-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
13ac69e5d4SEric van Gyzen    Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
14cc68614dSXin LI    Copyright (c) 2005-2006 Karl Waclawek <karl@waclawek.net>
15*dc58b3fcSXin LI    Copyright (c) 2016-2022 Sebastian Pipping <sebastian@pipping.org>
16cc68614dSXin LI    Copyright (c) 2017      Rhodri James <rhodri@wildebeest.org.uk>
170a48773fSEric van Gyzen    Licensed under the MIT license:
180a48773fSEric van Gyzen 
190a48773fSEric van Gyzen    Permission is  hereby granted,  free of charge,  to any  person obtaining
200a48773fSEric van Gyzen    a  copy  of  this  software   and  associated  documentation  files  (the
210a48773fSEric van Gyzen    "Software"),  to  deal in  the  Software  without restriction,  including
220a48773fSEric van Gyzen    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
230a48773fSEric van Gyzen    distribute, sublicense, and/or sell copies of the Software, and to permit
240a48773fSEric van Gyzen    persons  to whom  the Software  is  furnished to  do so,  subject to  the
250a48773fSEric van Gyzen    following conditions:
260a48773fSEric van Gyzen 
270a48773fSEric van Gyzen    The above copyright  notice and this permission notice  shall be included
280a48773fSEric van Gyzen    in all copies or substantial portions of the Software.
290a48773fSEric van Gyzen 
300a48773fSEric van Gyzen    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
310a48773fSEric van Gyzen    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
320a48773fSEric van Gyzen    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
330a48773fSEric van Gyzen    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
340a48773fSEric van Gyzen    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
350a48773fSEric van Gyzen    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
360a48773fSEric van Gyzen    USE OR OTHER DEALINGS IN THE SOFTWARE.
370a48773fSEric van Gyzen */
385bb6a25fSPoul-Henning Kamp 
395bb6a25fSPoul-Henning Kamp #include <stdio.h>
405bb6a25fSPoul-Henning Kamp #include <expat.h>
415bb6a25fSPoul-Henning Kamp 
42220ed979SColeman Kane #ifdef XML_LARGE_SIZE
43220ed979SColeman Kane #  define XML_FMT_INT_MOD "ll"
44220ed979SColeman Kane #else
45220ed979SColeman Kane #  define XML_FMT_INT_MOD "l"
46220ed979SColeman Kane #endif
47220ed979SColeman Kane 
480a48773fSEric van Gyzen #ifdef XML_UNICODE_WCHAR_T
490a48773fSEric van Gyzen #  define XML_FMT_STR "ls"
500a48773fSEric van Gyzen #else
510a48773fSEric van Gyzen #  define XML_FMT_STR "s"
520a48773fSEric van Gyzen #endif
530a48773fSEric van Gyzen 
54220ed979SColeman Kane static void XMLCALL
startElement(void * userData,const XML_Char * name,const XML_Char ** atts)55*dc58b3fcSXin LI startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
565bb6a25fSPoul-Henning Kamp   int i;
57*dc58b3fcSXin LI   int *const depthPtr = (int *)userData;
585bb6a25fSPoul-Henning Kamp 
59*dc58b3fcSXin LI   for (i = 0; i < *depthPtr; i++)
605bb6a25fSPoul-Henning Kamp     printf("  ");
615bb6a25fSPoul-Henning Kamp 
62*dc58b3fcSXin LI   printf("%" XML_FMT_STR, name);
635bb6a25fSPoul-Henning Kamp 
64*dc58b3fcSXin LI   for (i = 0; atts[i]; i += 2) {
65*dc58b3fcSXin LI     printf(" %" XML_FMT_STR "='%" XML_FMT_STR "'", atts[i], atts[i + 1]);
665bb6a25fSPoul-Henning Kamp   }
675bb6a25fSPoul-Henning Kamp 
685bb6a25fSPoul-Henning Kamp   printf("\n");
69*dc58b3fcSXin LI   *depthPtr += 1;
705bb6a25fSPoul-Henning Kamp }
715bb6a25fSPoul-Henning Kamp 
72220ed979SColeman Kane static void XMLCALL
endElement(void * userData,const XML_Char * name)73*dc58b3fcSXin LI endElement(void *userData, const XML_Char *name) {
74*dc58b3fcSXin LI   int *const depthPtr = (int *)userData;
75*dc58b3fcSXin LI   (void)name;
76be8aff81SXin LI 
77*dc58b3fcSXin LI   *depthPtr -= 1;
785bb6a25fSPoul-Henning Kamp }
795bb6a25fSPoul-Henning Kamp 
805bb6a25fSPoul-Henning Kamp int
main(void)81*dc58b3fcSXin LI main(void) {
82*dc58b3fcSXin LI   XML_Parser parser = XML_ParserCreate(NULL);
83*dc58b3fcSXin LI   int done;
84*dc58b3fcSXin LI   int depth = 0;
85be8aff81SXin LI 
86*dc58b3fcSXin LI   if (! parser) {
875bb6a25fSPoul-Henning Kamp     fprintf(stderr, "Couldn't allocate memory for parser\n");
88*dc58b3fcSXin LI     return 1;
895bb6a25fSPoul-Henning Kamp   }
905bb6a25fSPoul-Henning Kamp 
91*dc58b3fcSXin LI   XML_SetUserData(parser, &depth);
92*dc58b3fcSXin LI   XML_SetElementHandler(parser, startElement, endElement);
935bb6a25fSPoul-Henning Kamp 
94*dc58b3fcSXin LI   do {
95*dc58b3fcSXin LI     void *const buf = XML_GetBuffer(parser, BUFSIZ);
96*dc58b3fcSXin LI     if (! buf) {
97*dc58b3fcSXin LI       fprintf(stderr, "Couldn't allocate memory for buffer\n");
98*dc58b3fcSXin LI       XML_ParserFree(parser);
99*dc58b3fcSXin LI       return 1;
100*dc58b3fcSXin LI     }
1015bb6a25fSPoul-Henning Kamp 
102*dc58b3fcSXin LI     const size_t len = fread(buf, 1, BUFSIZ, stdin);
103*dc58b3fcSXin LI 
1045bb6a25fSPoul-Henning Kamp     if (ferror(stdin)) {
1055bb6a25fSPoul-Henning Kamp       fprintf(stderr, "Read error\n");
106*dc58b3fcSXin LI       XML_ParserFree(parser);
107*dc58b3fcSXin LI       return 1;
1085bb6a25fSPoul-Henning Kamp     }
109*dc58b3fcSXin LI 
1105bb6a25fSPoul-Henning Kamp     done = feof(stdin);
1115bb6a25fSPoul-Henning Kamp 
112*dc58b3fcSXin LI     if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) {
1130a48773fSEric van Gyzen       fprintf(stderr,
1140a48773fSEric van Gyzen               "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n",
115*dc58b3fcSXin LI               XML_GetCurrentLineNumber(parser),
116*dc58b3fcSXin LI               XML_ErrorString(XML_GetErrorCode(parser)));
117*dc58b3fcSXin LI       XML_ParserFree(parser);
118*dc58b3fcSXin LI       return 1;
1195bb6a25fSPoul-Henning Kamp     }
120*dc58b3fcSXin LI   } while (! done);
1215bb6a25fSPoul-Henning Kamp 
122*dc58b3fcSXin LI   XML_ParserFree(parser);
1235bb6a25fSPoul-Henning Kamp   return 0;
1245bb6a25fSPoul-Henning Kamp }
125