| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 | 
							- /* Read an XML document from standard input and print
 
-    element declarations (if any) to standard output.
 
-    It must be used with Expat compiled for UTF-8 output.
 
-                             __  __            _
 
-                          ___\ \/ /_ __   __ _| |_
 
-                         / _ \\  /| '_ \ / _` | __|
 
-                        |  __//  \| |_) | (_| | |_
 
-                         \___/_/\_\ .__/ \__,_|\__|
 
-                                  |_| XML parser
 
-    Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
 
-    Copyright (c) 2001-2003 Fred L. Drake, Jr. <[email protected]>
 
-    Copyright (c) 2004-2006 Karl Waclawek <[email protected]>
 
-    Copyright (c) 2005-2007 Steven Solie <[email protected]>
 
-    Copyright (c) 2016-2024 Sebastian Pipping <[email protected]>
 
-    Copyright (c) 2017      Rhodri James <[email protected]>
 
-    Copyright (c) 2019      Zhongyuan Zhou <[email protected]>
 
-    Copyright (c) 2024      Hanno Böck <[email protected]>
 
-    Licensed under the MIT license:
 
-    Permission is  hereby granted,  free of charge,  to any  person obtaining
 
-    a  copy  of  this  software   and  associated  documentation  files  (the
 
-    "Software"),  to  deal in  the  Software  without restriction,  including
 
-    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
 
-    distribute, sublicense, and/or sell copies of the Software, and to permit
 
-    persons  to whom  the Software  is  furnished to  do so,  subject to  the
 
-    following conditions:
 
-    The above copyright  notice and this permission notice  shall be included
 
-    in all copies or substantial portions of the Software.
 
-    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
 
-    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
 
-    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
 
-    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 
-    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
 
-    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 
-    USE OR OTHER DEALINGS IN THE SOFTWARE.
 
- */
 
- #include <stdbool.h>
 
- #include <stdio.h>
 
- #include <stdlib.h>
 
- #include <expat.h>
 
- #ifdef XML_LARGE_SIZE
 
- #  define XML_FMT_INT_MOD "ll"
 
- #else
 
- #  define XML_FMT_INT_MOD "l"
 
- #endif
 
- #ifdef XML_UNICODE_WCHAR_T
 
- #  define XML_FMT_STR "ls"
 
- #else
 
- #  define XML_FMT_STR "s"
 
- #endif
 
- // While traversing the XML_Content tree, we avoid recursion
 
- // to not be vulnerable to a denial of service attack.
 
- typedef struct StackStruct {
 
-   const XML_Content *model;
 
-   unsigned level;
 
-   struct StackStruct *prev;
 
- } Stack;
 
- static Stack *
 
- stackPushMalloc(Stack *stackTop, const XML_Content *model, unsigned level) {
 
-   Stack *const newStackTop = malloc(sizeof(Stack));
 
-   if (! newStackTop) {
 
-     return NULL;
 
-   }
 
-   newStackTop->model = model;
 
-   newStackTop->level = level;
 
-   newStackTop->prev = stackTop;
 
-   return newStackTop;
 
- }
 
- static Stack *
 
- stackPopFree(Stack *stackTop) {
 
-   Stack *const newStackTop = stackTop->prev;
 
-   free(stackTop);
 
-   return newStackTop;
 
- }
 
- static char *
 
- contentTypeName(enum XML_Content_Type contentType) {
 
-   switch (contentType) {
 
-   case XML_CTYPE_EMPTY:
 
-     return "EMPTY";
 
-   case XML_CTYPE_ANY:
 
-     return "ANY";
 
-   case XML_CTYPE_MIXED:
 
-     return "MIXED";
 
-   case XML_CTYPE_NAME:
 
-     return "NAME";
 
-   case XML_CTYPE_CHOICE:
 
-     return "CHOICE";
 
-   case XML_CTYPE_SEQ:
 
-     return "SEQ";
 
-   default:
 
-     return "???";
 
-   }
 
- }
 
- static char *
 
- contentQuantName(enum XML_Content_Quant contentQuant) {
 
-   switch (contentQuant) {
 
-   case XML_CQUANT_NONE:
 
-     return "NONE";
 
-   case XML_CQUANT_OPT:
 
-     return "OPT";
 
-   case XML_CQUANT_REP:
 
-     return "REP";
 
-   case XML_CQUANT_PLUS:
 
-     return "PLUS";
 
-   default:
 
-     return "???";
 
-   }
 
- }
 
- static void
 
- dumpContentModelElement(const XML_Content *model, unsigned level,
 
-                         const XML_Content *root) {
 
-   // Indent
 
-   unsigned u = 0;
 
-   for (; u < level; u++) {
 
-     printf("  ");
 
-   }
 
-   // Node
 
-   printf("[%u] type=%s(%u), quant=%s(%u)", (unsigned)(model - root),
 
-          contentTypeName(model->type), (unsigned int)model->type,
 
-          contentQuantName(model->quant), (unsigned int)model->quant);
 
-   if (model->name) {
 
-     printf(", name=\"%" XML_FMT_STR "\"", model->name);
 
-   } else {
 
-     printf(", name=NULL");
 
-   }
 
-   printf(", numchildren=%u", model->numchildren);
 
-   printf("\n");
 
- }
 
- static bool
 
- dumpContentModel(const XML_Char *name, const XML_Content *root) {
 
-   printf("Element \"%" XML_FMT_STR "\":\n", name);
 
-   Stack *stackTop = stackPushMalloc(NULL, root, 1);
 
-   if (! stackTop) {
 
-     return false;
 
-   }
 
-   while (stackTop) {
 
-     const XML_Content *const model = stackTop->model;
 
-     const unsigned level = stackTop->level;
 
-     dumpContentModelElement(model, level, root);
 
-     stackTop = stackPopFree(stackTop);
 
-     for (size_t u = model->numchildren; u >= 1; u--) {
 
-       Stack *const newStackTop
 
-           = stackPushMalloc(stackTop, model->children + (u - 1), level + 1);
 
-       if (! newStackTop) {
 
-         // We ran out of memory, so let's free all memory allocated
 
-         // earlier in this function, to be leak-clean:
 
-         while (stackTop != NULL) {
 
-           stackTop = stackPopFree(stackTop);
 
-         }
 
-         return false;
 
-       }
 
-       stackTop = newStackTop;
 
-     }
 
-   }
 
-   printf("\n");
 
-   return true;
 
- }
 
- static void XMLCALL
 
- handleElementDeclaration(void *userData, const XML_Char *name,
 
-                          XML_Content *model) {
 
-   XML_Parser parser = (XML_Parser)userData;
 
-   const bool success = dumpContentModel(name, model);
 
-   XML_FreeContentModel(parser, model);
 
-   if (! success) {
 
-     XML_StopParser(parser, /* resumable= */ XML_FALSE);
 
-   }
 
- }
 
- int
 
- main(void) {
 
-   XML_Parser parser = XML_ParserCreate(NULL);
 
-   int done;
 
-   if (! parser) {
 
-     fprintf(stderr, "Couldn't allocate memory for parser\n");
 
-     return 1;
 
-   }
 
-   XML_SetUserData(parser, parser);
 
-   XML_SetElementDeclHandler(parser, handleElementDeclaration);
 
-   do {
 
-     void *const buf = XML_GetBuffer(parser, BUFSIZ);
 
-     if (! buf) {
 
-       fprintf(stderr, "Couldn't allocate memory for buffer\n");
 
-       XML_ParserFree(parser);
 
-       return 1;
 
-     }
 
-     const size_t len = fread(buf, 1, BUFSIZ, stdin);
 
-     if (ferror(stdin)) {
 
-       fprintf(stderr, "Read error\n");
 
-       XML_ParserFree(parser);
 
-       return 1;
 
-     }
 
-     done = feof(stdin);
 
-     if (XML_ParseBuffer(parser, (int)len, done) == XML_STATUS_ERROR) {
 
-       enum XML_Error errorCode = XML_GetErrorCode(parser);
 
-       if (errorCode == XML_ERROR_ABORTED) {
 
-         errorCode = XML_ERROR_NO_MEMORY;
 
-       }
 
-       fprintf(stderr,
 
-               "Parse error at line %" XML_FMT_INT_MOD "u:\n%" XML_FMT_STR "\n",
 
-               XML_GetCurrentLineNumber(parser), XML_ErrorString(errorCode));
 
-       XML_ParserFree(parser);
 
-       return 1;
 
-     }
 
-   } while (! done);
 
-   XML_ParserFree(parser);
 
-   return 0;
 
- }
 
 
  |