diff --git a/CHANGES b/CHANGES index af47caf..f2427b3 100644 --- a/CHANGES +++ b/CHANGES @@ -1,8 +1,11 @@ -README - 12/01/2003 +README - 12/02/2003 ------------------- CHANGES IN Mini-XML 1.3 + - Fixed several bugs in the mxmldoc utility. + - Added new error callback function to catch a variety + of errors and log them to someplace other than stderr. - The mxmlElementSetAttr() function now allows for NULL attribute values. - The load and save functions now properly handle quoted diff --git a/documentation.html b/documentation.html index 092c82b..5ed7daf 100644 --- a/documentation.html +++ b/documentation.html @@ -55,6 +55,7 @@
  • mxmlSaveFile()
  • mxmlSaveString()
  • mxmlSetElement()
  • +
  • mxmlSetErrorCallback()
  • mxmlSetInteger()
  • mxmlSetOpaque()
  • mxmlSetReal()
  • @@ -512,6 +513,22 @@ mxmlSetElement(

    Returns

    0 on success, -1 on failure

    +

    mxmlSetErrorCallback()

    +

    Set the error message callback.

    +

    Syntax

    +
    +void
    +mxmlSetErrorCallback(
    +    void (*cb)(const char *));
    +
    +

    Arguments

    +

    + + + +
    NameDescription
    (*cb)(const char *)Error callback function

    +

    Returns

    +

    Nothing.

    mxmlSetInteger()

    Set the value of an integer node. diff --git a/mxml-attr.c b/mxml-attr.c index 437579c..775123d 100644 --- a/mxml-attr.c +++ b/mxml-attr.c @@ -1,5 +1,5 @@ /* - * "$Id: mxml-attr.c,v 1.5 2003/12/01 15:27:47 mike Exp $" + * "$Id: mxml-attr.c,v 1.6 2003/12/03 03:59:04 mike Exp $" * * Attribute support code for mini-XML, a small XML-like file parsing library. * @@ -44,6 +44,11 @@ mxmlElementGetAttr(mxml_node_t *node, /* I - Element node */ mxml_attr_t *attr; /* Cirrent attribute */ +#ifdef DEBUG + fprintf(stderr, "mxmlElementGetAttr(node=%p, name=\"%s\")\n", + node, name ? name : "(null)"); +#endif /* DEBUG */ + /* * Range check input... */ @@ -87,6 +92,11 @@ mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */ mxml_attr_t *attr; /* New attribute */ +#ifdef DEBUG + fprintf(stderr, "mxmlElementSetAttr(node=%p, name=\"%s\", value=\"%s\")\n", + node, name ? name : "(null)", value ? value : "(null)"); +#endif /* DEBUG */ + /* * Range check input... */ @@ -129,15 +139,15 @@ mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */ if (!attr) { - fprintf(stderr, "Unable to allocate memory for attribute '%s' in element %s!\n", - name, node->value.element.name); + mxml_error("Unable to allocate memory for attribute '%s' in element %s!", + name, node->value.element.name); return; } node->value.element.attrs = attr; attr += node->value.element.num_attrs; - attr->name = strdup(name); + attr->name = strdup(name); if (value) attr->value = strdup(value); else @@ -151,8 +161,8 @@ mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */ if (attr->value) free(attr->value); - fprintf(stderr, "Unable to allocate memory for attribute '%s' in element %s!\n", - name, node->value.element.name); + mxml_error("Unable to allocate memory for attribute '%s' in element %s!", + name, node->value.element.name); return; } @@ -162,5 +172,5 @@ mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */ /* - * End of "$Id: mxml-attr.c,v 1.5 2003/12/01 15:27:47 mike Exp $". + * End of "$Id: mxml-attr.c,v 1.6 2003/12/03 03:59:04 mike Exp $". */ diff --git a/mxml-file.c b/mxml-file.c index 8e5785b..585dbba 100644 --- a/mxml-file.c +++ b/mxml-file.c @@ -1,5 +1,5 @@ /* - * "$Id: mxml-file.c,v 1.22 2003/12/01 15:27:47 mike Exp $" + * "$Id: mxml-file.c,v 1.23 2003/12/03 03:59:04 mike Exp $" * * File loading code for mini-XML, a small XML-like file parsing library. * @@ -17,20 +17,21 @@ * * Contents: * - * mxmlLoadFile() - Load a file into an XML node tree. - * mxmlLoadString() - Load a string into an XML node tree. - * mxmlSaveAllocString() - Save an XML node tree to an allocated string. - * mxmlSaveFile() - Save an XML tree to a file. - * mxmlSaveString() - Save an XML node tree to a string. - * mxml_add_char() - Add a character to a buffer, expanding as needed. - * mxml_file_getc() - Get a character from a file. - * mxml_load_data() - Load data into an XML node tree. - * mxml_parse_element() - Parse an element for any attributes... - * mxml_string_getc() - Get a character from a string. - * mxml_write_name() - Write a name string. - * mxml_write_node() - Save an XML node to a file. - * mxml_write_string() - Write a string, escaping & and < as needed. - * mxml_write_ws() - Do whitespace callback... + * mxmlLoadFile() - Load a file into an XML node tree. + * mxmlLoadString() - Load a string into an XML node tree. + * mxmlSaveAllocString() - Save an XML node tree to an allocated string. + * mxmlSaveFile() - Save an XML tree to a file. + * mxmlSaveString() - Save an XML node tree to a string. + * mxmlSetErrorCallback() - Set the error message callback. + * mxml_add_char() - Add a character to a buffer, expanding as needed. + * mxml_file_getc() - Get a character from a file. + * mxml_load_data() - Load data into an XML node tree. + * mxml_parse_element() - Parse an element for any attributes... + * mxml_string_getc() - Get a character from a string. + * mxml_write_name() - Write a name string. + * mxml_write_node() - Save an XML node to a file. + * mxml_write_string() - Write a string, escaping & and < as needed. + * mxml_write_ws() - Do whitespace callback... */ /* @@ -263,6 +264,20 @@ mxmlSaveString(mxml_node_t *node, /* I - Node to write */ } +/* + * 'mxmlSetErrorCallback()' - Set the error message callback. + */ + +extern void (*mxml_error_cb)(const char *); + +void +mxmlSetErrorCallback(void (*cb)(const char *)) + /* I - Error callback function */ +{ + mxml_error_cb = cb; +} + + /* * 'mxml_add_char()' - Add a character to a buffer, expanding as needed. */ @@ -291,8 +306,7 @@ mxml_add_char(int ch, /* I - Character to add */ { free(*buffer); - fprintf(stderr, "Unable to expand string buffer to %d bytes!\n", - *bufsize); + mxml_error("Unable to expand string buffer to %d bytes!", *bufsize); return (-1); } @@ -358,7 +372,7 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ if ((buffer = malloc(64)) == NULL) { - fputs("Unable to allocate string buffer!\n", stderr); + mxml_error("Unable to allocate string buffer!"); return (NULL); } @@ -411,9 +425,9 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ * Bad integer/real number value... */ - fprintf(stderr, "Bad %s value '%s' in parent <%s>!\n", - type == MXML_INTEGER ? "integer" : "real", buffer, - parent ? parent->value.element.name : "null"); + mxml_error("Bad %s value '%s' in parent <%s>!", + type == MXML_INTEGER ? "integer" : "real", buffer, + parent ? parent->value.element.name : "null"); break; } @@ -426,8 +440,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ * Just print error for now... */ - fprintf(stderr, "Unable to add value node of type %d to parent <%s>!\n", - type, parent ? parent->value.element.name : "null"); + mxml_error("Unable to add value node of type %d to parent <%s>!", + type, parent ? parent->value.element.name : "null"); break; } } @@ -503,8 +517,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ * Just print error for now... */ - fprintf(stderr, "Unable to add comment node to parent <%s>!\n", - parent ? parent->value.element.name : "null"); + mxml_error("Unable to add comment node to parent <%s>!", + parent ? parent->value.element.name : "null"); break; } } @@ -546,8 +560,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ * Just print error for now... */ - fprintf(stderr, "Unable to add declaration node to parent <%s>!\n", - parent ? parent->value.element.name : "null"); + mxml_error("Unable to add declaration node to parent <%s>!", + parent ? parent->value.element.name : "null"); break; } @@ -572,8 +586,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ * Close tag doesn't match tree; print an error for now... */ - fprintf(stderr, "Mismatched close tag <%s> under parent <%s>!\n", - buffer, parent->value.element.name); + mxml_error("Mismatched close tag <%s> under parent <%s>!", + buffer, parent->value.element.name); break; } @@ -607,8 +621,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ * Just print error for now... */ - fprintf(stderr, "Unable to add element node to parent <%s>!\n", - parent ? parent->value.element.name : "null"); + mxml_error("Unable to add element node to parent <%s>!", + parent ? parent->value.element.name : "null"); break; } @@ -618,8 +632,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ { if ((ch = (*getc_cb)(p)) != '>') { - fprintf(stderr, "Expected > but got '%c' instead for element <%s/>!\n", - ch, buffer); + mxml_error("Expected > but got '%c' instead for element <%s/>!", + ch, buffer); break; } @@ -665,8 +679,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ *entptr++ = ch; else { - fprintf(stderr, "Entity name too long under parent <%s>!\n", - parent ? parent->value.element.name : "null"); + mxml_error("Entity name too long under parent <%s>!", + parent ? parent->value.element.name : "null"); break; } @@ -674,8 +688,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ if (ch != ';') { - fprintf(stderr, "Entity name \"%s\" not terminated under parent <%s>!\n", - entity, parent ? parent->value.element.name : "null"); + mxml_error("Entity name \"%s\" not terminated under parent <%s>!", + entity, parent ? parent->value.element.name : "null"); break; } @@ -698,8 +712,8 @@ mxml_load_data(mxml_node_t *top, /* I - Top node */ ch = '\"'; else { - fprintf(stderr, "Entity name \"%s;\" not supported under parent <%s>!\n", - entity, parent ? parent->value.element.name : "null"); + mxml_error("Entity name \"%s;\" not supported under parent <%s>!", + entity, parent ? parent->value.element.name : "null"); break; } @@ -836,7 +850,7 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */ if ((name = malloc(64)) == NULL) { - fputs("Unable to allocate memory for name!\n", stderr); + mxml_error("Unable to allocate memory for name!"); return (EOF); } @@ -845,7 +859,7 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */ if ((value = malloc(64)) == NULL) { free(name); - fputs("Unable to allocate memory for value!\n", stderr); + mxml_error("Unable to allocate memory for value!"); return (EOF); } @@ -857,9 +871,9 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */ while ((ch = (*getc_cb)(p)) != EOF) { -#ifdef DEBUG +#if DEBUG > 1 fprintf(stderr, "parse_element: ch='%c'\n", ch); -#endif /* DEBUG */ +#endif /* DEBUG > 1 */ /* * Skip leading whitespace... @@ -882,8 +896,8 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */ if (quote != '>') { - fprintf(stderr, "Expected '>' after '%c' for element %s, but got '%c'!\n", - ch, node->value.element.name, quote); + mxml_error("Expected '>' after '%c' for element %s, but got '%c'!", + ch, node->value.element.name, quote); ch = EOF; } @@ -947,8 +961,8 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */ if ((ch = (*getc_cb)(p)) == EOF) { - fprintf(stderr, "Missing value for attribute '%s' in element %s!\n", - name, node->value.element.name); + mxml_error("Missing value for attribute '%s' in element %s!", + name, node->value.element.name); return (EOF); } @@ -1024,8 +1038,8 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */ if (quote != '>') { - fprintf(stderr, "Expected '>' after '%c' for element %s, but got '%c'!\n", - ch, node->value.element.name, quote); + mxml_error("Expected '>' after '%c' for element %s, but got '%c'!", + ch, node->value.element.name, quote); ch = EOF; } @@ -1647,5 +1661,5 @@ mxml_write_ws(mxml_node_t *node, /* I - Current node */ /* - * End of "$Id: mxml-file.c,v 1.22 2003/12/01 15:27:47 mike Exp $". + * End of "$Id: mxml-file.c,v 1.23 2003/12/03 03:59:04 mike Exp $". */ diff --git a/mxml-node.c b/mxml-node.c index dba6552..072d65a 100644 --- a/mxml-node.c +++ b/mxml-node.c @@ -1,5 +1,5 @@ /* - * "$Id: mxml-node.c,v 1.9 2003/09/28 21:09:04 mike Exp $" + * "$Id: mxml-node.c,v 1.10 2003/12/03 03:59:04 mike Exp $" * * Node support code for mini-XML, a small XML-like file parsing library. * @@ -61,8 +61,10 @@ mxmlAdd(mxml_node_t *parent, /* I - Parent node */ mxml_node_t *child, /* I - Child node for where or MXML_ADD_TO_PARENT */ mxml_node_t *node) /* I - Node to add */ { -/* fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent, - where, child, node);*/ +#ifdef DEBUG + fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent, + where, child, node); +#endif /* DEBUG */ /* * Range check input... @@ -71,6 +73,14 @@ mxmlAdd(mxml_node_t *parent, /* I - Parent node */ if (!parent || !node) return; +#if DEBUG > 1 + fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent); + fprintf(stderr, " BEFORE: parent->child=%p\n", parent->child); + fprintf(stderr, " BEFORE: parent->last_child=%p\n", parent->last_child); + fprintf(stderr, " BEFORE: parent->prev=%p\n", parent->prev); + fprintf(stderr, " BEFORE: parent->next=%p\n", parent->next); +#endif /* DEBUG > 1 */ + /* * Remove the node from any existing parent... */ @@ -155,6 +165,14 @@ mxmlAdd(mxml_node_t *parent, /* I - Parent node */ } break; } + +#if DEBUG > 1 + fprintf(stderr, " AFTER: node->parent=%p\n", node->parent); + fprintf(stderr, " AFTER: parent->child=%p\n", parent->child); + fprintf(stderr, " AFTER: parent->last_child=%p\n", parent->last_child); + fprintf(stderr, " AFTER: parent->prev=%p\n", parent->prev); + fprintf(stderr, " AFTER: parent->next=%p\n", parent->next); +#endif /* DEBUG > 1 */ } @@ -171,7 +189,9 @@ mxmlDelete(mxml_node_t *node) /* I - Node to delete */ int i; /* Looping var */ -/* fprintf(stderr, "mxmlDelete(node=%p)\n", node);*/ +#ifdef DEBUG + fprintf(stderr, "mxmlDelete(node=%p)\n", node); +#endif /* DEBUG */ /* * Range check input... @@ -255,6 +275,11 @@ mxmlNewElement(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ mxml_node_t *node; /* New node */ +#ifdef DEBUG + fprintf(stderr, "mxmlNewElement(parent=%p, name=\"%s\")\n", parent, + name ? name : "(null)"); +#endif /* DEBUG */ + /* * Range check input... */ @@ -288,6 +313,10 @@ mxmlNewInteger(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ mxml_node_t *node; /* New node */ +#ifdef DEBUG + fprintf(stderr, "mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer); +#endif /* DEBUG */ + /* * Range check input... */ @@ -322,6 +351,11 @@ mxmlNewOpaque(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ mxml_node_t *node; /* New node */ +#ifdef DEBUG + fprintf(stderr, "mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent, + opaque ? opaque : "(null)"); +#endif /* DEBUG */ + /* * Range check input... */ @@ -355,6 +389,10 @@ mxmlNewReal(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ mxml_node_t *node; /* New node */ +#ifdef DEBUG + fprintf(stderr, "mxmlNewReal(parent=%p, real=%g)\n", parent, real); +#endif /* DEBUG */ + /* * Range check input... */ @@ -391,6 +429,11 @@ mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ mxml_node_t *node; /* New node */ +#ifdef DEBUG + fprintf(stderr, "mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n", + parent, whitespace, string ? string : "(null)"); +#endif /* DEBUG */ + /* * Range check input... */ @@ -432,6 +475,11 @@ mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ va_list ap; /* Pointer to arguments */ +#ifdef DEBUG + fprintf(stderr, "mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", ...)\n", + parent, whitespace, format ? format : "(null)"); +#endif /* DEBUG */ + /* * Range check input... */ @@ -467,12 +515,14 @@ mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */ void mxmlRemove(mxml_node_t *node) /* I - Node to remove */ { +#ifdef DEBUG + fprintf(stderr, "mxmlRemove(node=%p)\n", node); +#endif /* DEBUG */ + /* * Range check input... */ -/* fprintf(stderr, "mxmlRemove(node=%p)\n", node);*/ - if (!node || !node->parent) return; @@ -480,6 +530,19 @@ mxmlRemove(mxml_node_t *node) /* I - Node to remove */ * Remove from parent... */ +#if DEBUG > 1 + fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent); + if (node->parent) + { + fprintf(stderr, " BEFORE: node->parent->child=%p\n", node->parent->child); + fprintf(stderr, " BEFORE: node->parent->last_child=%p\n", node->parent->last_child); + } + fprintf(stderr, " BEFORE: node->child=%p\n", node->child); + fprintf(stderr, " BEFORE: node->last_child=%p\n", node->last_child); + fprintf(stderr, " BEFORE: node->prev=%p\n", node->prev); + fprintf(stderr, " BEFORE: node->next=%p\n", node->next); +#endif /* DEBUG > 1 */ + if (node->prev) node->prev->next = node->next; else @@ -493,6 +556,19 @@ mxmlRemove(mxml_node_t *node) /* I - Node to remove */ node->parent = NULL; node->prev = NULL; node->next = NULL; + +#if DEBUG > 1 + fprintf(stderr, " AFTER: node->parent=%p\n", node->parent); + if (node->parent) + { + fprintf(stderr, " AFTER: node->parent->child=%p\n", node->parent->child); + fprintf(stderr, " AFTER: node->parent->last_child=%p\n", node->parent->last_child); + } + fprintf(stderr, " AFTER: node->child=%p\n", node->child); + fprintf(stderr, " AFTER: node->last_child=%p\n", node->last_child); + fprintf(stderr, " AFTER: node->prev=%p\n", node->prev); + fprintf(stderr, " AFTER: node->next=%p\n", node->next); +#endif /* DEBUG > 1 */ } @@ -507,12 +583,26 @@ mxml_new(mxml_node_t *parent, /* I - Parent node */ mxml_node_t *node; /* New node */ +#if DEBUG > 1 + fprintf(stderr, "mxml_new(parent=%p, type=%d)\n", parent, type); +#endif /* DEBUG > 1 */ + /* * Allocate memory for the node... */ if ((node = calloc(1, sizeof(mxml_node_t))) == NULL) + { +#if DEBUG > 1 + fputs(" returning NULL\n", stderr); +#endif /* DEBUG > 1 */ + return (NULL); + } + +#if DEBUG > 1 + fprintf(stderr, " returning %p\n", node); +#endif /* DEBUG > 1 */ /* * Set the node type... @@ -536,5 +626,5 @@ mxml_new(mxml_node_t *parent, /* I - Parent node */ /* - * End of "$Id: mxml-node.c,v 1.9 2003/09/28 21:09:04 mike Exp $". + * End of "$Id: mxml-node.c,v 1.10 2003/12/03 03:59:04 mike Exp $". */ diff --git a/mxml-private.c b/mxml-private.c index 3428878..ad5a942 100644 --- a/mxml-private.c +++ b/mxml-private.c @@ -1,5 +1,5 @@ /* - * "$Id: mxml-private.c,v 1.1 2003/09/28 21:09:04 mike Exp $" + * "$Id: mxml-private.c,v 1.2 2003/12/03 03:59:04 mike Exp $" * * Private functions for mini-XML, a small XML-like file parsing library. * @@ -17,6 +17,7 @@ * * Contents: * + * mxml_error() - Display an error message. * mxml_integer_cb() - Default callback for integer values. * mxml_opaque_cb() - Default callback for opaque values. * mxml_real_cb() - Default callback for real number values. @@ -26,9 +27,67 @@ * Include necessary headers... */ +#include "config.h" #include "mxml.h" +/* + * Error callback function... + */ + +void (*mxml_error_cb)(const char *) = NULL; + + +/* + * 'mxml_error()' - Display an error message. + */ + +void +mxml_error(const char *format, /* I - Printf-style format string */ + ...) /* I - Additional arguments as needed */ +{ + va_list ap; /* Pointer to arguments */ + char *s; /* Message string */ + + + /* + * Range check input... + */ + + if (!format) + return; + + /* + * Format the error message string... + */ + + va_start(ap, format); + + s = mxml_strdupf(format, ap); + + va_end(ap); + + /* + * And then display the error message... + */ + + if (mxml_error_cb) + (*mxml_error_cb)(s); + else + { + fputs("mxml: ", stderr); + fputs(s, stderr); + putc('\n', stderr); + } + + /* + * Free the string... + */ + + free(s); +} + + /* * 'mxml_integer_cb()' - Default callback for integer values. */ @@ -69,5 +128,5 @@ mxml_real_cb(mxml_node_t *node) /* I - Current node */ /* - * End of "$Id: mxml-private.c,v 1.1 2003/09/28 21:09:04 mike Exp $". + * End of "$Id: mxml-private.c,v 1.2 2003/12/03 03:59:04 mike Exp $". */ diff --git a/mxml.h b/mxml.h index 722dcfb..b73dc01 100644 --- a/mxml.h +++ b/mxml.h @@ -1,5 +1,5 @@ /* - * "$Id: mxml.h,v 1.14 2003/09/28 21:09:04 mike Exp $" + * "$Id: mxml.h,v 1.15 2003/12/03 03:59:04 mike Exp $" * * Header file for mini-XML, a small XML-like file parsing library. * @@ -165,6 +165,7 @@ extern int mxmlSaveString(mxml_node_t *node, char *buffer, int bufsize, int (*cb)(mxml_node_t *, int)); extern int mxmlSetElement(mxml_node_t *node, const char *name); +extern void mxmlSetErrorCallback(void (*cb)(const char *)); extern int mxmlSetInteger(mxml_node_t *node, int integer); extern int mxmlSetOpaque(mxml_node_t *node, const char *opaque); extern int mxmlSetReal(mxml_node_t *node, double real); @@ -186,7 +187,10 @@ extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top, * Private functions... */ -extern mxml_type_t _mxml_opaque_cb(mxml_node_t *node); +extern void mxml_error(const char *format, ...); +extern mxml_type_t mxml_integer_cb(mxml_node_t *node); +extern mxml_type_t mxml_opaque_cb(mxml_node_t *node); +extern mxml_type_t mxml_real_cb(mxml_node_t *node); /* @@ -200,5 +204,5 @@ extern mxml_type_t _mxml_opaque_cb(mxml_node_t *node); /* - * End of "$Id: mxml.h,v 1.14 2003/09/28 21:09:04 mike Exp $". + * End of "$Id: mxml.h,v 1.15 2003/12/03 03:59:04 mike Exp $". */ diff --git a/mxml.xml b/mxml.xml index 0f0315f..07a0aa6 100644 --- a/mxml.xml +++ b/mxml.xml @@ -208,6 +208,9 @@ The node is not changed if it is not an element node.mxml_node_t *Node to set const char *New name string +Set the error message callback.voidError callback function + 0 on success, -1 on failureint Set the value of an integer node. diff --git a/mxmldoc.c b/mxmldoc.c index c0c5baf..ad1dd55 100644 --- a/mxmldoc.c +++ b/mxmldoc.c @@ -1,5 +1,5 @@ /* - * "$Id: mxmldoc.c,v 1.17 2003/09/28 21:09:04 mike Exp $" + * "$Id: mxmldoc.c,v 1.18 2003/12/03 03:59:04 mike Exp $" * * Documentation generator using mini-XML, a small XML-like file parsing * library. @@ -20,6 +20,7 @@ * * main() - Main entry for test program. * add_variable() - Add a variable or argument. + * safe_strcpy() - Copy a string allowing for overlapping strings. * scan_file() - Scan a source file. * sort_node() - Insert a node sorted into a tree. * update_comment() - Update a comment node. @@ -101,12 +102,26 @@ */ +/* + * Basic states for file parser... + */ + +#define STATE_NONE 0 /* No state - whitespace, etc. */ +#define STATE_PREPROCESSOR 1 /* Preprocessor directive */ +#define STATE_C_COMMENT 2 /* Inside a C comment */ +#define STATE_CXX_COMMENT 3 /* Inside a C++ comment */ +#define STATE_STRING 4 /* Inside a string constant */ +#define STATE_CHARACTER 5 /* Inside a character constant */ +#define STATE_IDENTIFIER 6 /* Inside a keyword/identifier */ + + /* * Local functions... */ static mxml_node_t *add_variable(mxml_node_t *parent, const char *name, mxml_node_t *type); +static void safe_strcpy(char *dst, const char *src); static int scan_file(const char *filename, FILE *fp, mxml_node_t *doc); static void sort_node(mxml_node_t *tree, mxml_node_t *func); @@ -303,16 +318,18 @@ add_variable(mxml_node_t *parent, /* I - Parent node */ /* - * Basic states for file parser... + * 'safe_strcpy()' - Copy a string allowing for overlapping strings. */ -#define STATE_NONE 0 /* No state - whitespace, etc. */ -#define STATE_PREPROCESSOR 1 /* Preprocessor directive */ -#define STATE_C_COMMENT 2 /* Inside a C comment */ -#define STATE_CXX_COMMENT 3 /* Inside a C++ comment */ -#define STATE_STRING 4 /* Inside a string constant */ -#define STATE_CHARACTER 5 /* Inside a character constant */ -#define STATE_IDENTIFIER 6 /* Inside a keyword/identifier */ +static void +safe_strcpy(char *dst, /* I - Destination string */ + const char *src) /* I - Source string */ +{ + while (*src) + *dst++ = *src++; + + *dst = '\0'; +} /* @@ -328,7 +345,7 @@ scan_file(const char *filename, /* I - Filename */ braces, /* Number of braces active */ parens; /* Number of active parenthesis */ int ch; /* Current character */ - char buffer[16384], /* String buffer */ + char buffer[65536], /* String buffer */ *bufptr; /* Pointer into buffer */ mxml_node_t *comment, /* node */ *constant, /* node */ @@ -454,7 +471,7 @@ scan_file(const char *filename, /* I - Filename */ type->child->value.text.string); #ifdef DEBUG - fprintf(stderr, "%c%s: <<< %s >>>\n", + fprintf(stderr, "%c%s: <<<< %s >>>\n", toupper(type->child->value.text.string[0]), type->child->value.text.string + 1, type->child->next ? @@ -503,7 +520,10 @@ scan_file(const char *filename, /* I - Filename */ comment->last_child); if (scan_file(filename, fp, structclass)) + { + mxmlDelete(comment); return (-1); + } #ifdef DEBUG fputs(" ended typedef...\n", stderr); @@ -535,7 +555,7 @@ scan_file(const char *filename, /* I - Filename */ enumeration = mxmlNewElement(MXML_NO_PARENT, "enumeration"); #ifdef DEBUG - fprintf(stderr, "Enumeration: <<< %s >>>\n", + fprintf(stderr, "Enumeration: <<<< %s >>>\n", type->child->next ? type->child->next->value.text.string : "(noname)"); #endif /* DEBUG */ @@ -603,14 +623,17 @@ scan_file(const char *filename, /* I - Filename */ if (braces > 0) braces --; else + { + mxmlDelete(comment); return (0); + } break; case '(' : if (type) { #ifdef DEBUG - fputs("Identifier: <<< ( >>>\n", stderr); + fputs("Identifier: <<<< ( >>>\n", stderr); #endif /* DEBUG */ mxmlNewText(type, 0, "("); } @@ -625,7 +648,7 @@ scan_file(const char *filename, /* I - Filename */ if (type && parens) { #ifdef DEBUG - fputs("Identifier: <<< ) >>>\n", stderr); + fputs("Identifier: <<<< ) >>>\n", stderr); #endif /* DEBUG */ mxmlNewText(type, 0, ")"); } @@ -655,7 +678,7 @@ scan_file(const char *filename, /* I - Filename */ if (type) { #ifdef DEBUG - fputs("Identifier: <<< : >>>\n", stderr); + fputs("Identifier: <<<< : >>>\n", stderr); #endif /* DEBUG */ mxmlNewText(type, 1, ":"); } @@ -665,7 +688,7 @@ scan_file(const char *filename, /* I - Filename */ if (type) { #ifdef DEBUG - fputs("Identifier: <<< * >>>\n", stderr); + fputs("Identifier: <<<< * >>>\n", stderr); #endif /* DEBUG */ ch = type->last_child->value.text.string[0]; mxmlNewText(type, isalnum(ch) || ch == '_', "*"); @@ -773,7 +796,7 @@ scan_file(const char *filename, /* I - Filename */ #endif /* DEBUG */ } #ifdef DEBUG - fprintf(stderr, "C comment: <<< %s >>>\n", buffer); + fprintf(stderr, "C comment: <<<< %s >>>\n", buffer); #endif /* DEBUG */ state = STATE_NONE; @@ -859,7 +882,7 @@ scan_file(const char *filename, /* I - Filename */ mxmlNewText(comment, 0, buffer); #ifdef DEBUG - fprintf(stderr, "C comment: <<< %s >>>\n", buffer); + fprintf(stderr, "C comment: <<<< %s >>>\n", buffer); #endif /* DEBUG */ state = STATE_NONE; @@ -937,7 +960,7 @@ scan_file(const char *filename, /* I - Filename */ mxmlNewText(comment, 0, buffer); #ifdef DEBUG - fprintf(stderr, "C++ comment: <<< %s >>>\n", buffer); + fprintf(stderr, "C++ comment: <<<< %s >>>\n", buffer); #endif /* DEBUG */ } else if (ch == ' ' && bufptr == buffer) @@ -1064,7 +1087,7 @@ scan_file(const char *filename, /* I - Filename */ buffer); #ifdef DEBUG - fprintf(stderr, "Argument: <<< %s >>>\n", buffer); + fprintf(stderr, "Argument: <<<< %s >>>\n", buffer); #endif /* DEBUG */ variable = add_variable(function, "argument", type); @@ -1080,7 +1103,7 @@ scan_file(const char *filename, /* I - Filename */ if (typedefnode || structclass) { #ifdef DEBUG - fprintf(stderr, "Typedef/struct/class: <<< %s >>>>\n", buffer); + fprintf(stderr, "Typedef/struct/class: <<<< %s >>>>\n", buffer); #endif /* DEBUG */ if (typedefnode) @@ -1119,7 +1142,7 @@ scan_file(const char *filename, /* I - Filename */ */ #ifdef DEBUG - fprintf(stderr, "Typedef: <<< %s >>>\n", buffer); + fprintf(stderr, "Typedef: <<<< %s >>>\n", buffer); #endif /* DEBUG */ typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef"); @@ -1146,7 +1169,7 @@ scan_file(const char *filename, /* I - Filename */ buffer); #ifdef DEBUG - fprintf(stderr, "Variable: <<< %s >>>>\n", buffer); + fprintf(stderr, "Variable: <<<< %s >>>>\n", buffer); #endif /* DEBUG */ variable = add_variable(MXML_NO_PARENT, "variable", type); @@ -1158,7 +1181,7 @@ scan_file(const char *filename, /* I - Filename */ else { #ifdef DEBUG - fprintf(stderr, "Identifier: <<< %s >>>>\n", buffer); + fprintf(stderr, "Identifier: <<<< %s >>>>\n", buffer); #endif /* DEBUG */ mxmlNewText(type, type->child != NULL && @@ -1170,7 +1193,7 @@ scan_file(const char *filename, /* I - Filename */ else if (enumeration) { #ifdef DEBUG - fprintf(stderr, "Constant: <<< %s >>>\n", buffer); + fprintf(stderr, "Constant: <<<< %s >>>\n", buffer); #endif /* DEBUG */ constant = mxmlNewElement(MXML_NO_PARENT, "constant"); @@ -1225,18 +1248,27 @@ sort_node(mxml_node_t *tree, /* I - Tree to sort into */ *nodename; /* Name of node */ +#if DEBUG > 1 + fprintf(stderr, " sort_node(tree=%p, node=%p)\n", tree, node); +#endif /* DEBUG > 1 */ + /* * Range check input... */ - if (!tree || !node) + if (!tree || !node || node->parent == tree) return; /* * Get the node name... */ - nodename = mxmlElementGetAttr(node, "name"); + if ((nodename = mxmlElementGetAttr(node, "name")) == NULL) + return; + +#if DEBUG > 1 + fprintf(stderr, " nodename=%p (\"%s\")\n", nodename, nodename); +#endif /* DEBUG > 1 */ /* * Delete any existing definition at this level, if one exists... @@ -1252,9 +1284,17 @@ sort_node(mxml_node_t *tree, /* I - Tree to sort into */ for (temp = tree->child; temp; temp = temp->next) { +#if DEBUG > 1 + fprintf(stderr, " temp=%p\n", temp); +#endif /* DEBUG > 1 */ + if ((tempname = mxmlElementGetAttr(temp, "name")) == NULL) continue; +#if DEBUG > 1 + fprintf(stderr, " tempname=%p (\"%s\")\n", tempname, tempname); +#endif /* DEBUG > 1 */ + if (strcmp(nodename, tempname) < 0) break; } @@ -1315,7 +1355,7 @@ update_comment(mxml_node_t *parent, /* I - Parent node */ while (isspace(*ptr)) ptr ++; - strcpy(comment->value.text.string, ptr); + safe_strcpy(comment->value.text.string, ptr); } } else if (!strncmp(ptr, "I ", 2) || !strncmp(ptr, "O ", 2) || @@ -1341,7 +1381,7 @@ update_comment(mxml_node_t *parent, /* I - Parent node */ while (isspace(*ptr)) ptr ++; - strcpy(comment->value.text.string, ptr); + safe_strcpy(comment->value.text.string, ptr); } /* @@ -1351,7 +1391,7 @@ update_comment(mxml_node_t *parent, /* I - Parent node */ for (ptr = comment->value.text.string; *ptr == '*'; ptr ++); for (; isspace(*ptr); ptr ++); if (ptr > comment->value.text.string) - strcpy(comment->value.text.string, ptr); + safe_strcpy(comment->value.text.string, ptr); for (ptr = comment->value.text.string + strlen(comment->value.text.string) - 1; ptr > comment->value.text.string && *ptr == '*'; @@ -2087,5 +2127,5 @@ ws_cb(mxml_node_t *node, /* I - Element node */ /* - * End of "$Id: mxmldoc.c,v 1.17 2003/09/28 21:09:04 mike Exp $". + * End of "$Id: mxmldoc.c,v 1.18 2003/12/03 03:59:04 mike Exp $". */